background

Rollup was originally designed for the ES Module. It was born when the format wars between AMD, CMD, and UMD were still very hot. The author wanted to make full use of the ES Module mechanism to build a flat structure and outstanding performance library.

ES the module mechanism

The ES Module is designed to be as static as possible, so that module dependencies and input and output variables can be determined at compile time. Both CommonJS and AMD modules can only determine these things at runtime, for example:

  1. ES import can only be used as a top-level statement in a module, not in function or if.
  2. ES import module names can only be string constants.
  3. Regardless of where the import statement appears, all imports must have been imported when the module is initialized.
  4. Import binding is immutable, similar to const. For example, you can’t import {a} from ‘./a’ and then assign something else to a.

These designs, while less flexible than CommonJS require, ensure that ES modules’ dependencies are fixed and independent of the runtime state, thus ensuring that ES modules can be reliably statically analyzed.

A rollup contrast webpack

Let’s take a look at the webPack and Rollup code structure as an example.

The source file:

// index.js
import a from './a.js'
import b from './b.js' 

export default() = > {console.log(a())
}

// a.js
export default() = >'a'

// b.js
export default() = >'b'
Copy the code

Webpack generates:

(function(modules) { // webpackBootstrap
  // Lots of runtime code
  // ...({})"./src/a.js":
  (function(module, __webpack_exports__, __webpack_require__) {

  "use strict";
  eval("__webpack_require__.r(__webpack_exports__); \n/* harmony default export */ __webpack_exports__[\"default\"] = (() => 'a'); \n\n//# sourceURL=webpack:///./src/a.js?");

  }),

  "./src/b.js":
  (function(module, __webpack_exports__, __webpack_require__) {

  "use strict";
  eval("__webpack_require__.r(__webpack_exports__); \n/* harmony default export */ __webpack_exports__[\"default\"] = (() => 'b'); \n\n//# sourceURL=webpack:///./src/b.js?");

  }),

  "./src/index.js":
  (function(module, __webpack_exports__, __webpack_require__) {

  "use strict";
  eval("__webpack_require__.r(__webpack_exports__); \n/* harmony import */ var _a_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./a.js */ \"./src/a.js\"); \n/* harmony import */ var _b_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./b.js */ \"./src/b.js\"); \n\n \n\n/* harmony default export */ __webpack_exports__[\"default\"] = (() => {\n console.log(Object(_a_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"])())\n}); \n\n//# sourceURL=webpack:///./src/index.js?"); })})Copy the code

Rollup generates:

var test = (function () {
  'use strict';

  var a = (a)= > 'a';

  var index = (a)= > {
    console.log(a());
    
  };

  returnindex; } ());Copy the code

First, WebPack is dedicated to the modular construction of complex spas with the advantages of:

  1. Handle various resource dependencies through the Loader
  2. The HMR module is hot replaced
  3. According to the need to load
  4. Extract common modules

Rollup is dedicated to creating a high performance library with the following advantages:

  1. Compiled codeRead well
  2. The bundle content generated by rollup is tenclean, there is no redundant code, but only splices together each module in accordance with the dependent order. All modules are constructed in a function (Scope), which achieves higher execution efficiency. Rollup has an unmatched performance advantage over Webpack, which generates runtime code such as __webpack_require__ when packaged, depending on how dependencies are handled,Compile-time dependency handling (rollup) naturally performs better than runtime dependency handling (Webpack)
  3. For ES mode-dependent libraries, rollup statically analyzes imports in code and excludes any code that is not actually used (tree-shaking, explained below)
  4. Support for application flow analysis, more accurate determination of the side effects of the project code
  5. Supports exportesModule files (Webpack does not support exporting ES modules)

Of course, there are obvious downsides to rollup:

  1. Modules are too static to implement HMR
  2. For ES Module only, cannot reliably handleCommonjs and UMD dependencies

Principles for using Webpack and rollup

From the above comparison, it can be concluded that webpack is more suitable for building App applications, and rollup is more suitable for class libraries (pure JS projects).

Advantages of Webpack to build App are reflected in the following aspects:

  1. powerfulPlug-in ecological, mainstream front-end frameworks have corresponding Loaders
  2. App-oriented feature support, as mentioned earlierHMR.According to the need to load.Public moduleExtraction and so on are essential features for developing App applications
  3. Simplify all aspects of Web development, includingImage automatic base64, resource cache (chunkId), according to the route to do code split, lazy loadingEtc.
  4. Reliable dependency module handling, unlike rollup which is only for ES Modules, faces CJS problems (WebPack passes)__webpack_require__Implementing various types of module dependency issues)

The advantage of Rollup is to build high-performance bundles, which is exactly what a class library needs.

tree-shaking

Tree-shaking can be understood as a tool that “shakes” our JS files away code that is not needed. It is performance optimization.

Tree-shaking was implemented earlier by rollup, and later by WebPack2 with the help of UglifyJS.

The essence of tree-shaking is to eliminate useless JS code with static analysis of ES Modules. Useless code has the following characteristics:

  1. The code will not be executed
  2. The results of code execution are not used
  3. The code only affects dead variables

Tree-shaking example for rollup packaging

// add.js:
export default (a, b) => {
  return a + b
}

// index.js:
import add from './add.js'
export default () => {
  add(1.2)}// Bundle.js:
var index = (a)= >{};export default index;
Copy the code

The result of the add(1, 2) execution is not used in index.js, so it is’ shaken ‘out in bundle.js.

Tree-shaking will not work if there are side effects in the function:

// add.js:
export default (a, b) => {
  window.a = 'a'
  return a + b
}

// ...

// bundle.js:
var add = (a, b) = > {
  window.a = 'a';
  return a + b
};

var index = (a)= > {
  add(1.2);
};

export default index;
Copy the code

So we try not to write code with side effects.

Rollup tutorial

First install rollup in your project:

yarn add rollup -D
Copy the code

Add build script commands to package.json:

{
  "scripts": {
    "build": "rollup -c"}}Copy the code

The core attributes

Rollup supports both command line and JS API calls. Let’s focus on a few core attributes in the command line configuration file:

// rollup.config.js
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import babel from 'rollup-plugin-babel';

export default [{
  input: 'src/index.js'.output: {
    file: 'dist/bundle.js'.format: 'umd'.name: 'test'
  },
  plugins: [
    resolve(),
    commonjs(),
    babel({
      exclude: 'node_modules/**'}})]]Copy the code

1. Input: Enter the path of the packaged entry file

2. Output. format: source code build output format

  1. iife: a self-executing function that can pass<script>Label load
  2. amd: browser-side module specification, loadable with RequireJS
  3. cjs: Node default module specification, which can be loaded via Webpack
  4. umdCompatible with IIFE, AMD, CJS three module specifications
  5. esES Module specification, available Webpack, Rollup load

Rollup provides the es build format to make it easier for library users to tree-shaking:

The source file:

// add.js:
export default (a, b) => a + b

// index.js:
import add from './add.js'
export default() = > {var result = add(1.2)
  console.log(result)
}
Copy the code

Rollup is built in the es format:

var add = (a, b) = > {
  return a + b
};
var index = (a)= > {
  var result = add(1.2);
  console.log(result);
};
export default index;
Copy the code

As you can see, we have a bundle based on the ES Module specification, at which point the reader might wonder: Application projects typically set Babel to block files in the node_module directory. If you point pkg.main to the bundle of the current ES Module specification, the project’s final bundle will contain ES Module code.

To address the above problem, rollup first proposed pkg.module, which sets the path to export files in es format, and the packaging tool will preferentially use the PKG. module field when it encounters it.

In summary, the library rollup can set up to package two files, one UMD (optionally optional) and one ES, and set their paths to the values of main and Module in package.json, respectively. This makes it easier for users of the library to tree-shaking.

3. external + output.globals

Rollup marks external dependencies with external + output.globals, in the case of Lodash:

// rollup.config.js
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
export default[{input: 'src/index.js'.output: {
      file: 'dist/bundle.js'.format: 'iife'.name: 'test'.globals: {
        'lodash': '_'}},external: [
      'lodash'].plugins: [
      resolve(),
      commonjs()
    ]
  }
]

// index.js
import lodash from 'lodash'
export default() = > {console.log(lodash)
}

// bundle.js
var test = (function (lodash) {
  'use strict';

  lodash = lodash && lodash.hasOwnProperty('default')? lodash['default'] : lodash;

  var index = (a)= > {
    console.log(lodash);
  };

  returnindex; } (_));Copy the code

4. plugins

Rollup also provides plug-ins for compression, Babel conversion, and more. Here are a few commonly used plug-ins:

  1. rollup-plugin-alias: Sets the alias for the Module
  2. rollup-plugin-babel: Using Babel for transformation during packaging, Babel needs to be installed and configured
  3. rollup-plugin-eslint: Provides ESLint capability, which requires installing and configuring ESLint
  4. rollup-plugin-node-resolve: Resolves modules in node_modules
  5. rollup-plugin-commonjsConvert CJS -> ESM, usually used in conjunction with one of the plug-ins above
  6. rollup-plugin-replace: Similar to WebPack DefinePlugin

For other configurations, see the rollup website

Finally thank you for taking the time to read this article, I hope this article can be helpful to you.

Refer to the article: 1. www.zhihu.com/question/41… 2. Juejin. Cn/post / 684490… 3. www.ayqy.net/blog/rollup…


Shuidi front-end team recruiting partners, welcome to send resume to email: [email protected]