冗余代码都走开——前端模块打包利器 Rollup.js 入门

摘要:
从“./”导入{cube}Mathematic.js';console.log(立方体(5));//请注意,该方法尚未在条目文件中调用//汇总将最终消除exportfunctionsquare(x){returnx*x;}//方法exportfunctioncube(x){returnx*x;}模块。exports=需要在条目文件中调用的main;

之前翻译过一篇文章,介绍了通过 ES2015 的解构赋值语法引入模块,可以让打包工具(browserify)最终编译出来的代码量最小化。

殊不知在 webpack 1.X 版本是无法利用该特性来避免引入冗余模块代码的,导致打出来的 bundle 文件大小难免略有臃肿。

今天则向大家介绍一个当红炸子鸡——Rollup.js,通过它可以让你的 bundle 最小化,有效减少文件请求大小——以至于连 vue 都迅速地转投它来打包模块。

冗余代码都走开——前端模块打包利器 Rollup.js 入门第1张

Tree-shaking

在 Rollup 编译模块的过程中,通过 Tree-shacking 的方式来剔除各模块中最终未被引用到的方法,通过仅保留被调用到的代码块来缩减 bundle 的大小。

我们来看下官网的例子。

页面入口文件 main.js:

import { cube } from './maths.js';
console.log( cube( 5 ) ); // 125,即5的立方值

被引如的 math.js 模块如下:

// 注意这个方法在入口文件里没有被调用过
//最终会被 Rollup 剔除
export function square ( x ) {
    return x * x;
}

//入口文件需要调用到的求立方值的方法
export function cube ( x ) {
    return x * x * x;
}

通过 Rollup 打包之后如下:

'use strict';

function cube ( x ) {
    // rewrite this as `square( x ) * x`
    // and see what happens!
    return x * x * x;
}

console.log( cube( 5 ) ); // 125

可以很明显地体会到 Tree-shaking 的作用 —— Math 模块里有个从未用到的 square 方法,咱们在 bundle 文件里把它消灭掉了。

另外 TS 会抽取引用到的模块内容,将它们置于同一个作用域下,进而直接用变量名就可以访问各个模块的接口;而不像 webpack 这样每个模块外还要包一层函数定义,再通过合并进去的 define/require 相互调用。

当然这种方法需要 ES2015 的解构赋值语法来配合,多亏了它,Rollup 才能有效地对模块内容进行可靠的静态分析。

冗余代码都走开——前端模块打包利器 Rollup.js 入门第1张

使用方式

安装自然不用说,走 npm 的老套路:

npm i rollup

执行打包的方式也是简单到爆:

rollup src/main.js -o rel/bundle.js

这意味着将入口文件 src/main.js 打包为 rel/bundle.js 文件。

很多时候我们开发走的 ES2015 模块语法,但最终编译出来的模块希望它能走 commonjs 语法,只需要加上 -f cjs 运行时参数(f for format)即可:

rollup src/main.js -o rel/bundle.js -f cjs

当然,如果你想编译为其它格式,可以把 cjs 更换为:

amd /  es6 / iife / umd

我们分别来个参考~ 假设入口文件 src/main.js 如下:

var name = 'VaJoy';

function main () {
    console.log(name);
}

export default main;

编译为各种模式后的bundle:

//////////////////////////////commonjs(-f cjs)
'use strict';

var name = 'VaJoy';

function main () {
    console.log(name);
}

module.exports = main;


//////////////////////////////AMD(-f amd)
define(function () { 'use strict';

    var name = 'VaJoy';

    function main () {
        console.log(name);
    }

    return main;

});

//ES2015/ES6(-f es6)
var name = 'VaJoy';

function main () {
    console.log(name);
}

export default main;


//////////////////////////////Global(-f iife)
//注意该方法需要通过配置文件形式来执行(见下一节)
var main = (function () {
    'use strict';

    var name = 'VaJoy';

    function main () {
        console.log(name);
    }

    return main;

}());

//////////////////////////////UMD(-f umd)
//注意该方法需要通过配置文件形式来执行(见下一节)
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global.main = factory());
}(this, function () { 'use strict';

    var name = 'VaJoy';

    function main () {
        console.log(name);
    }

    return main;

}));

冗余代码都走开——前端模块打包利器 Rollup.js 入门第1张

配置文件

和 webpack 一样,rollup 也支持通过配置文件来实现更灵活的功能。

我们在项目根目录新建一个 rollup.config.js :

export default {
  entry: 'src/main.js',
  format: 'cjs',
  dest: 'rel/bundle.js' // 输出文件
};

然后执行

rollup -c

即可通过默认配置文件(rollup.config.js)所设置的信息来进行打包。

如果你的配置文件另有其名(例如“rollup.config.dev.js”),在后面加上配置文件名即可:

rollup -c rollup.config.dev.js

冗余代码都走开——前端模块打包利器 Rollup.js 入门第1张

Rollup 也支持使用插件,写到配置对象的 plugin 里即可,这里我们以 rollup-plugin-babel 为例:

import babel from 'rollup-plugin-babel';

export default {
  entry: 'src/main.js',
  format: 'cjs',
  plugins: [ babel() ],
  dest: 'rel/bundle.js'
};

比较不爽的是,babel 的预设不像 webpack 可以直接写在配置文件里,而还是得独立写个“src/.babelrc”(注意我们可以写在 src 下,而不是非得放在项目根目录下)

{
  "presets": ["es2015-rollup"]
}

注意咱得确保安装了 rollup-plugin-babel 和 babel 预设 babel-preset-es2015-rollup

npm i rollup-plugin-babel babel-preset-es2015-rollup

这时候就能配合 babel 一起把 ES6 的模块编译为 ES5 的 bundle 了。

更多有趣的插件可以在 rollup 项目组织里找,貌似没有 webpack 那样专门有个插件列表页汇总,这点找起来不太方便。

冗余代码都走开——前端模块打包利器 Rollup.js 入门第1张

Rollup 也支持直接在模块中来被调用执行,这样很方便跟 grunt/gulp 等工具进行协作。

如我们修改 rollup.config.dev.js 内容为:

var rollup = require( 'rollup' );
var babel = require('rollup-plugin-babel');

rollup.rollup({
    entry: 'src/main.js',
    plugins: [ babel() ]
}).then( function ( bundle ) {
    bundle.write({
        format: 'umd',
        moduleName: 'main', //umd或iife模式下,若入口文件含 export,必须加上该属性
        dest: 'rel/bundle.js'
    });
});

然后用 node 直接执行

node rollup.config.dev.js

可以得到一样的执行结果。

注意 “rollup.rollup()”返回一个带着 bundle 作为 resolve 回调参数的 Promise 对象,我们常规直接使用语法糖 bundle.write 来打包输出文件:

    bundle.write({
        format: 'umd',
        moduleName: 'main',
        dest: 'rel/bundle.js'
    });

其等价于

  var result = bundle.generate({ //生成一个 bundle + sourcemap
    format: 'umd',
    moduleName: 'main',
    dest: 'rel/bundle.js',
  });

  fs.writeFileSync( 'rel/bundle.js', result.code );

冗余代码都走开——前端模块打包利器 Rollup.js 入门第1张

SourceMap

为了方便调试编译后的文件,rollup 肯定不会忘记添加 source map 功能,而且其配置也非常简单:

    {
        format: 'umd',
        moduleName: 'main',
        dest: 'rel/bundle.js',
        sourceMap: true   //加上这里即可
    }

这样编译后,rollup 会自动生成一个 rel/bundle.js.map 关联到 rel/bundle.js 中。

也可以将其直接内联在 bundle 里而不是独立生成一个 map 文件:

    {
        format: 'umd',
        moduleName: 'main',
        dest: 'rel/bundle.js',
        sourceMap: 'inline'
    }

若希望 map 文件可以自定义位置和名称,就得使用上面稍微提到的 bundle.generate 方法了:

  var result = bundle.generate({ //生成一个 bundle + sourcemap
    //...
  });

  fs.writeFileSync( 'rel/bundle.js', result.code );
  fs.writeFileSync( 'map/bundle.js.map', result.map.toString() );

冗余代码都走开——前端模块打包利器 Rollup.js 入门第1张

issue

Rollup 虽然利用 ES6 的特性帮咱节省了不少文件大小,但它并没有类似 webpack 的 -p 参数帮你压缩混淆文件。

因此即使是官方文档也推荐配合使用 UglifyJS 来进一步缩小 bundle 体积。

另外 webpack2 已经出来好几款 beta 版本了,同样也加上了对 Tree-shaking 的支持,相信 webpack2 出来后,Rollup 的热度会大大消减。

共勉~

donate

免责声明:文章转载自《冗余代码都走开——前端模块打包利器 Rollup.js 入门》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇基于Memcached的tomcat集群session共享所用的jar及多个tomcat各种序列化策略配置【PCIE-2】---PCIE配置空间及访问方式简介下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

django类视图的使用

1 类视图引入 以函数的方式定义的视图称为函数视图,函数视图便于理解。 但是遇到一个视图对应的路径提供了多种不同HTTP请求方式的支持时,便需要在一个函数中编写不同的业务逻辑,代码可读性与复用性都不佳。 def register(request): """处理注册""" # 获取请求方法,判断是GET/POST请求 if requ...

ueditor使用遇到的问题

1、文件没法上传,需要引入ueditor官网说的那几个jar包才行 2、上传的文件读不出来,路径不对,需要把config.json里面的所有【“”】替换成【/你的项目路径】,即把所有的Prefix路径都改成你的项目路径 3、上传的视频打不开,这是一个ueditor(1.4.4.4版)的bug,config.json文件里的【whitList】改为【whit...

SpringCloud 配置文件 application.yml和 bootstrap.yml区别

SpringCloud 配置文件 application.yml和 bootstrap.yml区别 bootstrap.yml 先于 application.yml 加载,也就是比application.yml先加载 bootstrap.yml(bootstrap.properties)用来程序引导时执行,应用于更加早期配置信息读取,如可以使用bootst...

vue video.js使用技巧

1 初始化 Video.js初始化有两种方式。 1.1 标签方式 一种是在<video>标签里面加上class="video-js"和data-setup='{}'属性。 注意,两者缺一不可。 刚开始的时候我觉得后面的值为空对象{},不放也行, 导致播放器加载不出来,后来加上来就可以了。 1.2 JS方式 另外一种初始化 video.js 的方...

SpringBoot 开发案例之整合FastDFS分布式文件系统

1、pom依赖 <!--fastdfs--> <dependency> <groupId>com.github.tobato</groupId> <artifactId>fastdfs-client</artifactId> <version>1.2...

二进制部署K8S-2集群部署

二进制部署K8S-2集群部署 感谢老男孩教育王导的公开视频,文档整理自https://www.yuque.com/duduniao/k8s。 因为在后期运行容器需要有大量的物理硬件资源使用的环境是用的Wmware EXSI如果使用笔记本可适当调整虚拟机配置。 角色 主机名 IP CPU Mem OS (主)负载均衡、内网DNS hdss7-11...