Rollup详解

一、什么是Rollup

    Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。Rollup 对代码模块使用新的标准化格式,这些标准都包含在 JavaScript 的 ES6 版本中,而不是以前的特殊解决方案,如 CommonJS 和 AMD。ES6 模块可以使你自由、无缝地使用你最喜爱的 library 中那些最有用独立函数,而你的项目不必携带其他未使用的代码。ES6 模块最终还是要由浏览器原生实现,但当前 Rollup 可以使你提前体验。

Rollup中文官网

二、为什么选择Rollup

1、Tree-Shaking

    tree shaking是rollup提出的,这也是rollup一个非常重要的feature,那什么是tree               shaking,rollup的解释是在构建代码时,在使用ES6模块化的代码中,会对你的代码进行静态分析,只打包使用到的代码。这样的好处是减少代码的体积,该功能也在webpack 4得到了实现。

2、多种输出格式的支持

    amd - AMD

    cjs -CommonJS

    es - ES6 modules

    umd - UMD

    system - SystemJS loader

3、兼容性

导入 CommonJS(Importing CommonJS)

Rollup 可以通过插件导入已存在的 CommonJS 模块。

发布 ES6 模块(Publishing ES6 Modules)

为了确保你的 ES6 模块可以直接与「运行在 CommonJS(例如 Node.js 和 webpack)中的工具(tool)」使用,你可以使用 Rollup 编译为 UMD 或 CommonJS 格式,然后在 package.json 文件的 main 属性中指向当前编译的版本。如果你的 package.json 也具有 module 字段,像 Rollup 和 webpack 2 这样的 ES6 感知工具(ES6-aware tools)将会直接导入 ES6 模块版本

浏览器兼容性

可以通过配置es3的编译工具,将目标代码编译至es3,配合polyfill,对于有向下兼容IE8的用户提供了兼容服务。

输出代码非常纯净,没有任何多余代码,不像webpack打包后生成的文件会自动注入很多代码,导致目标文件代码非常ugly。

三、脚手架选择

Rollup:

    适合写库(lib)、工具(sdk)以及小型应用,生成的目标代码更纯净。

Webpack:

    更适合写中大型应用程序,生态更佳,第三方插件更丰富。

四、使用Rollup

通常项目中使用配置文件去使用Rollup,项目中我习惯将配置文件分成三份:rollup.base.conf.js、rollup.dev.conf.js、rollup.prod.conf.js。

rollup.base.conf.js

import json from 'rollup-plugin-json';

import resolve from 'rollup-plugin-node-resolve';

import babel from 'rollup-plugin-babel';

import commonjs from 'rollup-plugin-commonjs';

import es3 from 'rollup-plugin-es3';

import {eslint} from 'rollup-plugin-eslint';

import pkg from '../package.json';

export default {

  input: pkg.src,

  output: {

    file: pkg.main,

    format: 'umd',

    name: 'EUtils',

    sourcemap: true

  },

  watch: {

    include: 'src/**'

  },

  plugins: [

    resolve(),

    commonjs(),

    json(),

    eslint({

      include: 'src/**',

      exclude: ['node_modules/**', 'dist/**'],

    }),

    babel({

      babelrc: false,

      presets: [['env', {modules: false, loose: true}]],

      include: ['src/**', 'test/**'],

      plugins: ['external-helpers'],

      runtimeHelpers: true

    }),

    es3({

      remove: ['defineProperty', 'freeze']

    }),

  ],

};

rollup.dev.conf.js

import { merge } from 'lodash';

import rollupBaseConf from './rollup.base.conf';

import serve from 'rollup-plugin-serve';

import livereload from 'rollup-plugin-livereload';

const devConfig = {

  plugins: [

    serve({

      open: true, // 是否打开浏览器

      contentBase: './', // 入口html的文件位置

      historyApiFallback: true, // Set to true to return index.html instead of 404

      host: 'localhost',

      port: 8888

    }),

    livereload(),

  ],

};

const config = merge(rollupBaseConf, devConfig);

export default config;

rollup.prod.conf.js

import baseConf from './rollup.base.conf';

import { merge } from 'lodash';

import { uglify } from 'rollup-plugin-uglify';

const prodConf = merge(baseConf, {

  plugins: [

    uglify({

      compress: {

        drop_console: true,

      }

    }),

  ]

});

export default prodConf;

本地启动项目:

package.json:

"scripts": {

    "build": "npm run clean && npm run lib && rollup --config build/rollup.prod.conf.js",

    "start": "npm run dev",

    "clean": "rimraf dist/** lib/**",

    "dev": "rollup --config build/rollup.dev.conf.js -w && livereload 'dist/'",

    "test": "jest --config ./jest.conf.js --coverage"

  },

此例是我用rollup来构建一个通用函数库所使用的配置,最终形成的.min.js文件非常纯净,同时可集成jest测试框架来测试编写的函数功能。

五、集成测试框架

jest是一个极易上手的测试框架,能测试很多应用场景,下面是我用来测试函数功能的配置文件:

const path = require('path');

module.exports = {

  rootDir: path.resolve(__dirname, './'),

  verbose: true,

  moduleFileExtensions: ['js', 'json',],

  moduleNameMapper: {'^@/(.*)$': '<rootDir>/src/$1',},

  transform: {'^.+\\.js$': '<rootDir>/node_modules/babel-jest',},

  testPathIgnorePatterns: ['<rootDir>/test/e2e',],

  coverageDirectory: '<rootDir>/test/coverage/',

  collectCoverageFrom: [

    'src/**/*.js',

    '!src/index.js',

    '!src/position.js',

    '!src/internal/**',

    '!src/scrollTop.js',

    '!**/node_modules/**',

    '!src/*Cookie*.js',

    '!src/getStylePrefix.js'

  ],

};

其中collectCoverageFrom是配置所要测试的文件,带“!”表示不覆盖该文件的测试。

推荐阅读更多精彩内容