写在前面的Rollup是一个ESModulespackager,它也可以将项目中散落的小模块打包成一整块代码,让这些分好的模块在浏览器或者node.js环境下更好的运行。Rollup的作用和webpack很像,但是要小很多。它诞生的初衷是提供一个高效的ESModules打包器,充分利用ESModules的特性。Rollup的使用Rollup使用了一种新的代码模块标准化格式,它包含在ES6版本的JavaScript中,而不是以前的特殊解决方案,例如CommonJS和AMD。ES6模块让您可以自由无缝地使用您最喜欢的库中最有用的独立函数,而您的项目无需携带其他未使用的代码。ES6模块最终会被浏览器原生实现,但目前Rollup可以让你提前体验。首先当然需要执行安装命令安装rollup,然后需要像webpack一样配置相关的config文件。我们可以配置不同的配置文件直接用cli打包,但是如果加入更多的选项,这种命令行方式就变得很麻烦了。为此,我们需要创建一个配置文件以包含所需的选项。配置文件以rollup.config.js的形式命名,比cli更灵活。$npmirollup-D我们看到rollup配置和webpack类似。如果想要更详细的配置项信息,可以异步rollup官网。//src/helloWorld.jsexportdefaultfunctionsayHello(){console.log("nihao");}//src/index.jsimportsayHellofrom"./helloWorld"sayHello()//rollup.config.jsexportdefault{input:"src/index.js",//打包入口output:{//文件输出配置file:"dist/bundle.cjs.js",//打包后生成的文件位置和文件名format:"cjs",//文件输出格式,如下cjs规范,也就是官方的模块化规范名称:"bundleName"//包的全局变量名}}我们在package.json文件中配置的打包命令是"build":"rollup-c",我们在执行打包命令npmrunbuild后,生成的文件dist/bundle.cjs.js中的代码非常简洁,可读性强。//dist/bundle.cjs.js'usestrict';functionsayHello(){console.log("nihao");}sayHello();接下来详细说说rollup的配置问题。我们知道rollup使用的是ESM规范,但是如果要使用CommonJS规范,可以使用.cjs后缀来区分://rollup.config.cjsmodule.export={input:"src/index.js",output:{file:"dist/bundle.cjs.js",format:"cjs"}}我们之前创建了一个简单的打包配置文件,但是当你需要创建更复杂的bundle时,就需要更多的灵活性,比如如:通过npm安装导入模块,通过babel编译代码,使用json配置文件等等。为此,我们可以在打包过程中的关键点使用插件来改变rollup的行为。例如,我们可以使用@rollup/plugin-json插件来允许导入JSON文件,使用命令行npminstall--save-dev@rollup/plugin-json来安装。//src/main.jsimport{version}from"../package.json";exportdefaultfunction(){console.log('version'+version);}//rollup.config.jsimportjsonfrom'@rollup/plugin-json';exportdefault{input:'src/main.js',output:{file:'bundle.js',format:'cjs'},plugins:[json()]};这样执行npmrunbuild命令打包,生成的文件为:'usestrict';varversion='1.0.0';functionmain(){console.log('version'+version);}module.exports=main;当然,一些特殊的插件依赖于某些输出,请参阅插件挂钩以了解有关输出特定插件可以做什么的技术细节。如果将不兼容的插件用作特定于输出的插件,Rollup会警告您。为了练习那些依赖输出的插件,我们在之前简单项目打包的基础上进行相关配置,首先执行命令行npminstall--save-devrollup-plugin-terser,//rollup.config。jsimportjsonfrom'@rollup/plugin-json';import{terser}from'rollup-plugin-terser';exportdefault{input:'src/main.js',output:[{file:'bundle.js',format:'cjs'},{file:'bundle.min.js',format:'iife',name:'version',plugins:[terser()]}],plugins:[json()]};此时package:varversion=(function(){'usestrict';varn='1.0.0';returnfunction(){console.log('version'+n);};})();前面我们看到可以将多个文件的代码打包成一个文件,那么当项目比较大的时候,就需要对代码进行拆分。对于代码拆分,有时Rollup会自动将代码拆分成chunk,例如动态加载或多入口点,也有一种方法可以通过output.manualChunks选项明确告诉Rollup将哪些模块拆分成单独的chunk。//src/main.jsexportdefaultfunction(){import('./foo.js').then(({default:foo})=>console.log(foo));}Rollup将使用动态导入创建一个Split块文件仅在需要时加载。为了让rollup知道第二个块在哪里,您可以通过设置--file来设置规范,并通过--dir创建导出目录。$rollupsrc/main.js-fcjs-ddist将创建一个目录dist,其中包含两个文件main.js和chunk-[hash].js,其中[hash]是哈希字符串。你可以通过配置output.chunkFileNames和output.entryFileNames来设置你想要的文件命令模式。//→main.js:'usestrict';functionmain(){Promise.resolve(require('./chunk-b8774ea3.js')).then(({default:foo})=>console.log(foo));}module.exports=main;//→chunk-b8774ea3.js:('usestrict');varfoo='helloworld!';exports.default=foo;Rollup的优点是:输出更扁平,执行效率更高自动去除未引用代码打包结果仍然完全可读Rollup的缺点是:加载非ESM第三方模块更复杂,因为模块将最终会被打包到全局,所以HMR无法实现浏览器环境下的代码拆分函数必须在最后使用AMD的库如Require.js来编写。Webpack大而全,Rollup小而美。我选择的基本原则是应用开发优先使用webpack,类库或者框架开发使用Rollup。这是因为在开发js库的时候,webpack比较繁琐,打包后的文件太大,而rollup是针对js库和框架开发的。它只是生成代码,将我们的代码转换成目标js。如果想了解更多关于rollup的知识,可以阅读(官方文档)。
