“This is the ninth day of my participation in the First Challenge 2022. For details: First Challenge 2022”
preface
We’ve all used build tools, webPack is probably the most used, but there’s another great build tool besides WebPack, and that’s Rollup, so today we’re going to look at Rollup.
Tree-shaking
Tree-shaking is a rollup feature. What is tree-shaking? When building code, it statically analyzes the imports in the code and excludes any unused code. This has the advantage of reducing the size of the code. For example: we create two files, index.js and math.js, in the root directory
// math.js
export function plus (a) {
return a + a;
}
export function square (a) {
return a * a;
}
Copy the code
// index.js
import { square } from './math.js';
console.log( square( 5));Copy the code
Rollup index.js –o bundle.js –f iife where –o stands for output file, if not output directly to the console, –f stands for output file type, iife stands for immediate execution of the function, and other types are
- amd – AMD
- cjs -CommonJS
- es – ES6 modules
- umd – UMD
- system – SystemJS loader
Let’s look at bundle.js once we’ve built it
(function () {
'use strict';
// math.js
function square (a) {
return a * a;
}
console.log( square( 5 ) );
}());
Copy the code
We notice that only the square function we introduced is present, and we don’t include the plus function as well.
Webpack and rollup
Webpack was created in 2012 to build complex single-page applications (spAs). Two features in particular have changed everything:
- The code segment
- Import of static resources
Rollup’s development philosophy is different, leveraging the clever design of ES2015 modules to build a lean and easily distributed JavaScript library as efficiently as possible. Webpack does this by wrapping modules into functions, then packaging those functions with the require method (__webpack_require__) that can be implemented in the browser, and then processing those functions in turn. This is handy when you need to implement load on demand, but it introduces a lot of extraneous code and is a waste of resources.
There are really three types of code that WebPack builds output.
- Your business logic code
- Runtime – Bootstrap for code execution
- Manifest – A record of module dependencies
For example, in the above example, we run webpack index.js –mode development to build, and the packaged file looks like this:
/ * * * * * * / (function(modules) { // webpackBootstrap
/ * * * * * * / // The module cache
/ * * * * * * / var installedModules = {};
/ * * * * * * /
/ * * * * * * / // The require function
/ * * * * * * / function __webpack_require__(moduleId) {
/ * * * * * * /
/ * * * * * * / // Check if module is in cache
/ * * * * * * / if(installedModules[moduleId]) {
/ * * * * * * / return installedModules[moduleId].exports;
/ * * * * * * / }
/ * * * * * * / // Create a new module (and put it into the cache)
/ * * * * * * / var module = installedModules[moduleId] = {
/ * * * * * * / i: moduleId,
/ * * * * * * / l: false./ * * * * * * / exports: {}
/ * * * * * * / };
/ * * * * * * /
/ * * * * * * / // Execute the module function
/ * * * * * * / modules[moduleId].call(module.exports, module.module.exports, __webpack_require__);
/ * * * * * * /
/ * * * * * * / // Flag the module as loaded
/ * * * * * * / module.l = true;
/ * * * * * * /
/ * * * * * * / // Return the exports of the module
/ * * * * * * / return module.exports;
/ * * * * * * / }
/ * * * * * * /
/ * * * * * * /
/ * * * * * * / // expose the modules object (__webpack_modules__)
/ * * * * * * / __webpack_require__.m = modules;
/ * * * * * * /
/ * * * * * * / // expose the module cache
/ * * * * * * / __webpack_require__.c = installedModules;
/ * * * * * * /
/ * * * * * * / // define getter function for harmony exports
/ * * * * * * / __webpack_require__.d = function(exports, name, getter) {
/ * * * * * * / if(! __webpack_require__.o(exports, name)) {
/ * * * * * * / Object.defineProperty(exports, name, { enumerable: true.get: getter });
/ * * * * * * / }
/ * * * * * * / };
/ * * * * * * /
/ * * * * * * / // define __esModule on exports
/ * * * * * * / __webpack_require__.r = function(exports) {
/ * * * * * * / if(typeof Symbol! = ='undefined' && Symbol.toStringTag) {
/ * * * * * * / Object.defineProperty(exports.Symbol.toStringTag, { value: 'Module' });
/ * * * * * * / }
/ * * * * * * / Object.defineProperty(exports.'__esModule', { value: true });
/ * * * * * * / };
/ * * * * * * /
/ * * * * * * / // create a fake namespace object
/ * * * * * * / // mode & 1: value is a module id, require it
/ * * * * * * / // mode & 2: merge all properties of value into the ns
/ * * * * * * / // mode & 4: return value when already ns object
/ * * * * * * / // mode & 8|1: behave like require
/ * * * * * * / __webpack_require__.t = function(value, mode) {
/ * * * * * * / if(mode & 1) value = __webpack_require__(value);
/ * * * * * * / if(mode & 8) return value;
/ * * * * * * / if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/ * * * * * * / var ns = Object.create(null);
/ * * * * * * / __webpack_require__.r(ns);
/ * * * * * * / Object.defineProperty(ns, 'default', { enumerable: true.value: value });
/ * * * * * * / if(mode & 2 && typeofvalue ! ='string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/ * * * * * * / return ns;
/ * * * * * * / };
/ * * * * * * /
/ * * * * * * / // getDefaultExport function for compatibility with non-harmony modules
/ * * * * * * / __webpack_require__.n = function(module) {
/ * * * * * * / var getter = module && module.__esModule ?
/ * * * * * * / function getDefault() { return module['default']; } :
/ * * * * * * / function getModuleExports() { return module; };
/ * * * * * * / __webpack_require__.d(getter, 'a', getter);
/ * * * * * * / return getter;
/ * * * * * * / };
/ * * * * * * /
/ * * * * * * / // Object.prototype.hasOwnProperty.call
/ * * * * * * / __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/ * * * * * * /
/ * * * * * * / // __webpack_public_path__
/ * * * * * * / __webpack_require__.p = "";
/ * * * * * * /
/ * * * * * * /
/ * * * * * * / // Load entry module and return exports
/ * * * * * * / return __webpack_require__(__webpack_require__.s = "./index.js");
/ * * * * * * / })
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ * * * * * * / ({
/ * * * / "./index.js":
/ *! * * * * * * * * * * * * * * * * * *! * \! *** ./index.js ***! \ * * * * * * * * * * * * * * * * * * /
/ *! no exports provided */
/ * * * / (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__); \n/* harmony import */ var _math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./math.js */ \"./math.js\"); \n\n\nconst num = Object(_math_js__WEBPACK_IMPORTED_MODULE_0__[\"square\"])( 5 ) ; \nconsole.log( num ); \n\n//# sourceURL=webpack:///./index.js?");
/ * * * / }),
/ * * * / "./math.js":
/ *! * * * * * * * * * * * * * * * * *! * \! *** ./math.js ***! \ * * * * * * * * * * * * * * * * * /
/ *! exports provided: plus, square */
/ * * * / (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__); \n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"plus\", function() { return plus; }); \n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"square\", function() { return square; }); \n// math.js\nfunction plus (a) {\n return a + a; \n}\nfunction square (a) {\n return a * a; \n}\n\n//# sourceURL=webpack:///./math.js?");
/ * * * / })
/ * * * * * * / });
Copy the code
- You can see the business logic code, Runtime and Manifest in the build result
- Dependencies are recorded in the Manifest and loaded with __webpack_require__
- The build results include the unused Plus
- The build volume is significantly larger than the IIFE format in ROLLup
- When the code is executed, the iIFE output format is in rollup, and the code execution speed is faster. Webpack builds dependency lookup, and each module is wrapped in a function form. When executing, it forms one closure after another, occupying memory
So rollup is a good way to package JS SDKS or frameworks, for example, vue source code is rollup. Webpack is good for packaging applications such as SPAs or isomorphic projects.
use
In addition to executing the build directly from the command, you can also configure some properties using the configuration file. Create rollup.config.js in the root directory
// rollup.config.js
export default {
input: 'src/index.js'.output: {
file: 'bundle.js'.format: 'cjs'}};Copy the code
Then execute rollup -c to generate the bundle.js file
'use strict';
// math.js
function square (a) {
return a * a;
}
console.log( square( 5));Copy the code
As you can see, this is the same as what we built above, except we set the file type to CJS. Rollup also has a powerful plugin system, so let’s modify index.js
import { version } from '.. /package.json';
export default function() {
console.log('version: ' + version);
}
Copy the code
Directly introducing package. Json to version, and then the execution of a rollup -c,’s complains to the command line at this moment, because the json file could not be introduced, but there is a plug-in rollup plugin – json can solve this problem, we first installation, NPM install rollup-plugin-json –save, modify rollup.config.js
import json from 'rollup-plugin-json'; // Import plug-ins
export default {
input: 'src/index.js'.output: {
file: 'bundle.js'.format: 'cjs'
},
plugins: [ json() ] // Use plugins
};
Copy the code
After executing the build command, the build succeeded
'use strict';
var version = "1.0.0";
function index() {
console.log('version: ' + version);
}
module.exports = index;
Copy the code
The version attribute was successfully obtained from package.json.
Outside the chain (external – e/external)
Use rollup packaging, for example if we need to use a third-party library such as LoDash in our own library and don’t want LoDash to appear in the resulting packaging file. At this point we need to use the external attribute.
import _ from 'lodash'
_.chunk(['a'.'b'.'c'.'d'].2);
Copy the code
After the build, we found that the final file included the entire LoDash package, which increased the size of our package, so we needed to use the external attribute.
import resolve from 'rollup-plugin-node-resolve'; Rollup cannot recognize packages in node_modules and needs this plugin
export default {
input: 'src/index.js'.output: {
file: 'bundle.js'.format: 'cjs'
},
external: ['lodash'].plugins: [ resolve() ] // Use plugins
};
Copy the code
After the build
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var _ = _interopDefault(require('lodash'));
_.chunk(['a'.'b'.'c'.'d'].2);
Copy the code
The final file doesn’t pack Lodash in.
Other attributes
Rollup provides a number of personalized configuration properties, such as footer and banner, to add text to the header and tail of the file, and more properties to view the document