Rollup 使用教程
概述
Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。Rollup 对代码模块使用新的标准化格式,这些标准都包含在 JavaScript 的 ES6 版本中,而不是以前的特殊解决方案,如 CommonJS 和 AMD。ES6 模块可以使你自由、无缝地使用你最喜爱的 library 中那些最有用独立函数,而你的项目不必携带其他未使用的代码。ES6 模块最终还是要由浏览器原生实现,但当前 Rollup 可以使你提前体验。
本项目提供了多种较为完整使用案例, 体验方式
npm install && npm run build
安装方法
首先必须在node,npm环境下
使用教程
全局安装的可以直接使用rollup 命令行工具。
rollup 或者 rollup -h roll --help 相关api使用说明
eg. rollup --enviroment INCLUDE_DEPS,BUILD:production 相当于设置 Build = 'production' INCLUDE_DEPS = 'true'
rollup -i ./src/index.js -o ./dist/index.js -f umd -n test --watch --silent
局部安装的 通过使用配置文件 构建类库
- ``` js
- // rollup.config.js
- export default {
- // 核心选项
- input, // 必须
- external,
- plugins,
- // 额外选项
- onwarn,
- // danger zone
- acorn,
- context,
- moduleContext,
- legacy
- output: { // 必须 (如果要输出多个,可以是一个数组)
- // 核心选项
- file, // 必须
- format, // 必须
- name,
- globals,
- // 额外选项
- paths,
- banner,
- footer,
- intro,
- outro,
- sourcemap,
- sourcemapFile,
- interop,
- // 高危选项
- exports,
- amd,
- indent
- strict
- },
- };
- ```
配置文件选项详解
注意 : 使用数组或者字符串作为选项值的时候的时候, 默认使用的是文件的原始名称, 作为文件的basename,可以在output:entryFileNames = 'entry-[name].js' 配置选项作为 '[name]' 动态参数传递进去
注意: 使用键值对{key: value}的选项值作为参数,使用的对象的键作为文件的basename, 用来在output:entryFileNames 配置选项作为 '[name]' 动态参数传递进去
- ``` js
- {
- ...,
- plugins: [
- resolve(),
- commonjs(),
- isProduction && (await import('rollup-plugin-terser')).terser()
- ]
- }
- ```
该用例 同时展示了如何动态控制在不同环境变量下构建使用不同的插件.
- ``` js
- {
- ...,
- external: [
- 'some-externally-required-library',
- 'another-externally-required-library'
- ]
- }
- or
- {
- ...,
- external: (id, parent, isResolved) => {
- return true;
- }
- }
- ```
1.当format类型为 iife 或者 umd 格式的时候 需要配置 output.globals 选项参数 以提供全局变量名来替换外部导入. 2.当external是一个函数的时候。各个参数代表的含义分别是 id: 所有导入的文件id,(import访问的路径) parent:import 所在的文件绝对路径 isResolved: 表示文件id是否已通过插件处理过
- ``` js
- {
- ...,
- external: ['./src/loadash.js']
- output: { './src/loadash.js': '_' }
- }
- or
- const externalId = path.resolve(__dirname, './src/jquery.js');
- {
- ...,
- external: [externalId],
- output: {
- [externalId]: '<%= main %>#39;
- }
- }
- or
- {
- ...,
- external: (id, parent, isResolved) => {
- if(id === externalId && !isResolved) {
- return true;
- }
- return false;
- },
- output: (id) => {
- if(id === externalId) {
- return '<%= main %>#39;
- }
- }
- }
- ```
注意:当使用函数作为globals指定项的时候 id 表示的是每一个导入文件的id(即访问路径的文件名)。
高级参数
- ``` js
- {
- manualChunks: {
- modal: ['./component/toast.js', './component/dialog.js'],
- vendor: ['./redux.js', './react.js']
- }
- }
- or
- {
- manualChunks: (id) => {
- // 导入模块id 路径名
- if(id.includes('node_modules')) {
- return vendor;
- }
- }
- }
- ```
注意:共享模块包包名是键值对模式 的 key + 文件hash 或者 函数返回值 + 文件hash, 在共享文件模块不发生改变的情况下 不会重新构建, 文件名也不会变。
- ``` js
- {
- ...,
- output: {
- ...,
- banner: '/* my-library version ' + version + ' */',
- footer: '/* follow me on Twitter! @rich_harris */',
- intro: '/* this is a library */',
- outro: '/* this is end */'
- }
- };
- ```
该配置只会压缩打包后的有rollup生成的包装代码, 对于用户自己编写的代码不会改变 代码结构
简单理解 这个参数的意思就是,当全局有定义 同样name 的全局变量的时候, 使用extend = true 打包的时候使用的是 global.name = global.name || {} 优先使用已经存在的变量, extend = false 的话就会直接覆盖该全局变量 gloabl.name = {};
当sourcemap属性为true 的时候 ,会单独创建 sourcemap 源图文件, 当值为 inline 则会将源图数据uri 附加到源代码文件底部
- ``` js
- {
- output: {
- sourcemap: true,
- sourcemapPathTransform: (relativePath) => {
- return relativePath.replace('src', 'anotherSrc');
- }
- }
- ```
应用场景很少, 在特殊场景 需要改变 sourcemap 的指向文件地址时才会用到
危险选项参数
这里只介绍几个会用到的选项配置
- ``` js
- import jsx from 'acorn-jsx';
- export default {
- // … other options …
- acornInjectPlugins: [
- jsx()
- ]
- };
- ```
注意:这个acorn-jsx 插件和 使用babel 并不是同一个意思,这个插件的左右是让 acorn js解析器能认识jsx语法,经过rollup打包后展示的还是jsx 语法,而babel 会直接修改jsx结构成为普通js 语法
watch观察选项配置
这些选项仅在使用--watch标志运行Rollup 或使用rollup.watch
常用的选项配置就是这些 下面提供一个较为完整的 配置文件demo
- ``` js
- import path from 'path';
- export default {
- input: ['./src/index.js', './utils/index,js'],
- external: [
- path.resolve(__dirname, './src', 'dependA.js')
- ],
- output: {
- dir: path.resolve(__dirname, '.', 'dist'),
- format: 'cjs',
- name: 'test',
- entryFileNames: 'index-[name].js',
- banner: '/* JohnApache JSLib */',
- footer: '/* CopyRight */',
- intro: 'const ENVIRONMENT = "production";',
- outro: 'const ENVIRONMENT = "development";',
- preserveModules: false,
- sourcemap: true,
- sourcemapPathTransform: (relativePath) => {
- // will transform e.g. "src/main.js" -> "main.js"
- console.log(relativePath);
- console.log(path.relative('src', relativePath));
- return path.relative('src', relativePath)
- }
- },
- preferConst: false,
- manualChunks(id) {
- if (id.includes('dependC')) {
- return 'vendor';
- }
- }
- }
- ```
使用Javascript Api的方式构建打包程序
rollup还提供了在nodejs中使用的api,相比于配置文件,直接使用rollup的nodeapi 可以提供更为复杂深奥的配置方式,以编程方式生成boundle
- ``` js
- const rollup = require('rollup');
- // see below for details on the options
- const inputOptions = {...};
- const outputOptions = {...};
- async function build() {
- // create a bundle
- const bundle = await rollup.rollup(inputOptions);
- console.log(bundle.watchFiles); // an array of file names this bundle depends on
- // generate code
- const { output } = await bundle.generate(outputOptions);
- for (const chunkOrAsset of output) {
- if (chunkOrAsset.isAsset) {
- // For assets, this contains
- // {
- // isAsset: true, // signifies that this is an asset
- // fileName: string, // the asset file name
- // source: string | Buffer // the asset source
- // }
- console.log('Asset', chunkOrAsset);
- } else {
- // For chunks, this contains
- // {
- // code: string, // the generated JS code
- // dynamicImports: string[], // external modules imported dynamically by the chunk
- // exports: string[], // exported variable names
- // facadeModuleId: string | null, // the id of a module that this chunk corresponds to
- // fileName: string, // the chunk file name
- // imports: string[], // external modules imported statically by the chunk
- // isDynamicEntry: boolean, // is this chunk a dynamic entry point
- // isEntry: boolean, // is this chunk a static entry point
- // map: string | null, // sourcemaps if present
- // modules: { // information about the modules in this chunk
- // [id: string]: {
- // renderedExports: string[]; // exported variable names that were included
- // removedExports: string[]; // exported variable names that were removed
- // renderedLength: number; // the length of the remaining code in this module
- // originalLength: number; // the original length of the code in this module
- // };
- // },
- // name: string // the name of this chunk as used in naming patterns
- // }
- console.log('Chunk', chunkOrAsset.modules);
- }
- }
- // or write the bundle to disk
- await bundle.write(outputOptions);
- }
- build();
- ```
- ``` js
- // inputOptions
- const inputOptions = {
- // core input options
- external,
- input, // required
- plugins,
- // advanced input options
- cache,
- inlineDynamicImports,
- manualChunks,
- onwarn,
- preserveModules,
- strictDeprecations,
- // danger zone
- acorn,
- acornInjectPlugins,
- context,
- moduleContext,
- preserveSymlinks,
- shimMissingExports,
- treeshake,
- // experimental
- chunkGroupingSize,
- experimentalCacheExpiry,
- experimentalOptimizeChunks,
- experimentalTopLevelAwait,
- perf
- };
- ```
- ``` js
- //outputOptions
- const outputOptions = {
- // core output options
- dir,
- file,
- format, // required
- globals,
- name,
- // advanced output options
- assetFileNames,
- banner,
- chunkFileNames,
- compact,
- entryFileNames,
- extend,
- externalLiveBindings,
- footer,
- interop,
- intro,
- outro,
- paths,
- sourcemap,
- sourcemapExcludeSources,
- sourcemapFile,
- sourcemapPathTransform,
- // danger zone
- amd,
- dynamicImportFunction,
- esModule,
- exports,
- freeze,
- indent,
- namespaceToStringTag,
- noConflict,
- preferConst,
- strict
- };
- ```
- ``` js
- const rollup = require('rollup');
- const watchOptions = {...};
- const watcher = rollup.watch(watchOptions);
- watcher.on('event', event => {
- // event.code can be one of:
- // START — the watcher is (re)starting
- // BUNDLE_START — building an individual bundle
- // BUNDLE_END — finished building a bundle
- // END — finished building all bundles
- // ERROR — encountered an error while bundling
- // FATAL — encountered an unrecoverable error
- });
- // stop watching
- watcher.close();
- ```
- ``` js
- const watchOptions = {
- ...inputOptions,
- output: [outputOptions],
- watch: {
- chokidar,
- clearScreen,
- exclude,
- include
- }
- };
- ```
rollup 常用插件介绍
使用方法:
- ``` js
- import resolve from 'rollup-plugin-node-resolve';
- {
- ...
- plugins: [
- resolve()
- ]
- }
- ```
使用方法
- ``` js
- import common from 'rollup-plugin-commonjs';
- {
- ...
- plugins: [
- resolve()
- common({
- include: 'node_modules/**', // 包括
- exclude: [], // 排除
- })
- ]
- }
- ```
使用方法
- ``` js
- import {terser} from 'rollup-plugin-terser';
- import os from 'os';
- const cpuNums = os.cpus().length;
- {
- ...
- plugins: [
- terser({
- output: {
- comments: false,
- },
- numWorkers: cpuNums, //多线程压缩
- sourcemap: false,
- include: [/^.+\.js$/],
- exclude: [ 'node_modules/**' ]