preface
In this tutorial, we will continue to explore the advanced techniques of rollup.js. If you want to read the conclusion directly, you can read the last chapter.
A rollup. Js plug-in
The rollup.js plug-in has a pluggable design that helps us enhance the basic functionality of rollup.js. Here I highlight four of the most commonly used rollup.js plug-ins.
Resolve the plugin
Why do you need the Resolve plug-in?
In the previous tutorial, the objects we packaged were local JS code and libraries, but in real development, it is unlikely that all libraries will be local and we will download remote libraries via NPM. Rollup.js: rollup.js: rollup.js: rollup.js: rollup.js: rollup.js: rollup.js
npm i -S sam-test-data
Copy the code
The sam-test-data library provides a UMD module by default, which exposes two variables A and B and a random function. A is a random integer between 0 and 9, and B is a random integer between 0 and 99. The parameter of the random function is an integer, such as 100. Return a random integer between 0 and 99 to create a test plug-in code folder locally:
mkdir src/plugin
Copy the code
Create test code:
touch src/plugin/main.js
Copy the code
Write the following code:
import * as test from 'sam-test-data'
console.log(test)
export default test.random
Copy the code
Try running the code directly from babel-Node without using rollup.js package:
babel-node
> require('./src/plugin/main.js')
{ a: 1, b: 17, random: [Function: random] }
{ default: [Function: random] }
> require('./src/plugin/main.js').default(100)
41
Copy the code
As you can see that the code works, let’s try to package the code with rollup.js and add a new configuration file:
touch rollup.plugin.config.js
Copy the code
Write the following:
import { comment } from './comment-helper-es'
export default {
input: './src/plugin/main.js'.output: [{
file: './dist/index-plugin-cjs.js'.format: 'cjs'.banner: comment('welcome to imooc.com'.'this is a rollup test project'),
footer: comment('powered by sam'.'copyright 2018')}, {file: './dist/index-plugin-es.js'.format: 'es'.banner: comment('welcome to imooc.com'.'this is a rollup test project'),
footer: comment('powered by sam'.'copyright 2018')}}]Copy the code
Here I provide a comment-helper-es module, which exposes a comment method, automatically reads our parameters, and helps generate comments. At the same time, I add equal length delimiters above and below the comments, which can be directly used by interested partners:
export function comment() {
if (arguments.length === 0) {
return // Return if the argument is 0
}
let maxlength = 0
for (let i = 0; i < arguments.length; i++) {
const length = arguments[i].toString().length
maxlength = length > maxlength ? length : maxlength // Get the longest parameter
}
maxlength = maxlength === 0 ? maxlength : maxlength + 1 // Add 1 to the length of the longest argument for aesthetic reasons
let seperator = ' '
for (let i = 0; i < maxlength; i++) {
seperator += '=' // Generate delimiters based on the length of the argument
}
const c = []
c.push('/**\n') // Add a comment header
c.push(The '*' + seperator + '\n') // Add a comment separator
for (let i = 0; i < arguments.length; i++) {
c.push(The '*' + arguments[i] + '\n') // Add parameters
}
c.push(The '*' + seperator + '\n') // Add a comment separator
c.push('* * /) // Add a comment tail
return c.join(' ') // Merge the argument to a string
}
Copy the code
Package via rollup.js:
$rollup -c rollup.plugin.config.js./ SRC /plugin/main.js →./dist/ index-plugin-js,./dist/index-plugin-es.js... (!) Unresolved dependencies https://rollupjs.org/guide/en#warning-treating-module-as-external-dependency
sam-test-data (imported by src/plugin/main.js)
created ./dist/index-plugin-cjs.js, ./dist/index-plugin-es.js in 13ms
Copy the code
Dist /index-plugin-es.js (dist/index-plugin-es.js, dist/index-plugin-es.js)
/** * ============================== * welcome to imooc.com * this is a rollup test project * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = * * /
import * as test from 'sam-test-data';
import { random } from 'sam-test-data';
console.log(test);
var main = random;
export default main;
/** * =============== * powered by sam * copyright 2018 * =============== **/
Copy the code
It is almost the same as the original code we wrote, except that the random function is obtained separately from Sam-test-data by es6 destructuring assignment, and then assigned to the variable main and exposed. Imagine if we were writing a Javascript class library and users had to manually download all of the library’s dependencies when referencing it. To solve this problem, by merging the source code we wrote with our dependent third-party libraries, rollup.js provides us with the resolve plug-in.
How to use the resolve plug-in
First, install the Resolve plug-in:
npm i -D rollup-plugin-node-resolve
Copy the code
Modify configuration file rollup.plugin.config.js:
import resolve from 'rollup-plugin-node-resolve'
export default {
input: './src/plugin/main.js'.output: [{
file: './dist/index-plugin-cjs.js'.format: 'cjs'
}, {
file: './dist/index-plugin-es.js'.format: 'es'}].plugins: [
resolve()
]
}
Copy the code
Repack:
$rollup -c rollup.plugin.config.js./ SRC /plugin/main.js →./dist/ index-plugin-js,./dist/index-plugin-es.js... created ./dist/index-plugin-cjs.js, ./dist/index-plugin-es.jsin 28ms
Copy the code
Dist /index-plugin-es.js: dist/index-plugin-es.js: dist/index-plugin-es.js
const a = Math.floor(Math.random() * 10);
const b = Math.floor(Math.random() * 100);
function random(base) {
if (base && base % 1= = =0) {
return Math.floor(Math.random() * base)
} else {
return 0}}var test = /*#__PURE__*/Object.freeze({
a: a,
b: b,
random: random
});
console.log(test);
var main = random;
export default main;
Copy the code
It is clear that the source code for the Sam-test-data library is already integrated with our source code.
tree-shaking
SRC /plugin/main.js SRC /plugin/main.js
import * as test from 'sam-test-data'
export default test.random
Copy the code
Remove console.log(test) from source code and repackage:
rollup -c rollup.plugin.config.js
Copy the code
Dist /index-plugin-es.js dist/index-plugin-es.js
function random(base) {
if (base && base % 1= = =0) {
return Math.floor(Math.random() * base)
} else {
return 0}}var main = random;
export default main;
Copy the code
We find that the definition of variables A and B is missing because they are not used in the source code. This is the well-known tree-shaking mechanism of the ES module, which dynamically cleans out unused code and makes it leaner, thus making our library load faster (naturally faster with less capacity).
External properties
In some cases, we need to use the external attribute to tell rollup. Js which libraries are external and modify the rollup. Js configuration file:
import resolve from 'rollup-plugin-node-resolve'
export default {
input: './src/plugin/main.js'.output: [{
file: './dist/index-plugin-cjs.js'.format: 'cjs'
}, {
file: './dist/index-plugin-es.js'.format: 'es'}].plugins: [
resolve()
],
external: ['sam-test-data']}Copy the code
Repack:
rollup -c rollup.plugin.config.js
Copy the code
Dist /index-plugin-es.js
import { random } from 'sam-test-data';
var main = random;
export default main;
Copy the code
You can see that the sam-test-data library is treated as an external library despite the use of the resolve plug-in
Commonjs plug-in
Why do WE need the CommonJS plug-in?
Rollup.js does not support CommonJS modules by default. Here I wrote a CommonJS module for testing. The contents of this module are exactly the same as sam-test-data, except that the former uses the CommonJS specification.
npm i -S sam-test-data-cjs
Copy the code
Create a new code file:
touch src/plugin/main-cjs.js
Copy the code
Write the following code:
import test from 'sam-test-data-cjs'
console.log(test)
export default test.random
Copy the code
This code is very simple. Next modify the rollup.js configuration file:
import resolve from 'rollup-plugin-node-resolve'
export default {
input: './src/plugin/main-cjs.js'.output: [{
file: './dist/index-plugin-cjs.js'.format: 'cjs'
}, {
file: './dist/index-plugin-es.js'.format: 'es'}].plugins: [
resolve()
]
}
Copy the code
Perform packaging:
Rollup -c rollup.plugin.config.js./ SRC /plugin/main-cjs.js →./dist/index-plugin-cjs.js,./dist/index-plugin-es.js... [!] Error:'default'Is not exported by node_modules / _sam - [email protected] @ Sam - test - data - CJS/index. Js https://rollupjs.org/guide/en#error-name-is-not-exported-by-module-
src/plugin/main-cjs.js (1:7)
1: import test from 'sam-test-data-cjs'
^
Copy the code
As you can see, rollup.js does not recognize CommonJS modules by default, so we need to use the CommonJS plugin to solve this problem.
How to use the CommonJS plugin
Install the CommonJS plugin first:
npm i -D rollup-plugin-commonjs
Copy the code
Modify the rollup.js configuration file:
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
export default {
input: './src/plugin/main-cjs.js'.output: [{
file: './dist/index-plugin-cjs.js'.format: 'cjs'
}, {
file: './dist/index-plugin-es.js'.format: 'es'}].plugins: [
resolve(),
commonjs()
]
}
Copy the code
Repacking:
rollup -c rollup.plugin.config.js
Copy the code
Dist /index-plugin-es.js
const a = Math.floor(Math.random() * 10);
const b = Math.floor(Math.random() * 100);
function random(base) {
if (base && base % 1= = =0) {
return Math.floor(Math.random() * base)
} else {
return 0}}var _samTestDataCjs_0_0_1_samTestDataCjs = {
a, b, random
};
console.log(_samTestDataCjs_0_0_1_samTestDataCjs);
var mainCjs = _samTestDataCjs_0_0_1_samTestDataCjs.random;
export default mainCjs;
Copy the code
You can see that the CommonJS module is integrated into the code, and try to execute the packaged code via babel-Node:
babel-node
> require('./dist/index-plugin-es')
{ a: 7, b: 45, random: [Function: random] }
{ default: [Function: random] }
> require('./dist/index-plugin-es').default(1000)
838
Copy the code
The code execution is successful, indicating that our code packaging is successful.
CommonJS and tree – shaking
SRC /plugin/main-cjs.js to verify that the CommonJS module supports tree-shaking:
import test from 'sam-test-data-cjs'
export default test.random
Copy the code
As in the resolve tree-shaking example, remove console.log(test), re-package, and then look at the package source:
const a = Math.floor(Math.random() * 10);
const b = Math.floor(Math.random() * 100);
function random(base) {
if (base && base % 1= = =0) {
return Math.floor(Math.random() * base)
} else {
return 0}}var _samTestDataCjs_0_0_1_samTestDataCjs = {
a, b, random
};
var mainCjs = _samTestDataCjs_0_0_1_samTestDataCjs.random;
export default mainCjs;
Copy the code
The CommonJS module does not support tree-shaking, so it is recommended that you use the ES module when using rollup.js to get more streamlined code.
UMD and tree – shaking
The UMD module is similar to CommonJS and does not support tree-shaking. Here is a test module for UMD, sam-test-data-umD. Sam-test-data is also a UMD module. Why does it support tree-shaking? Let’s open sam-test-data’s package.json to find out:
{
"name": "sam-test-data"."version": "0.0.4"."description": "provide test data"."main": "dist/sam-test-data.js"."module": "dist/sam-test-data-es.js"
}
Copy the code
You can see that the main attribute points to dist/sam-test-data.js, which is a UMD module, but the module attribute points to dist/sam-test-data-es.js, which is an ES module. Rollup.js by default finds and loads the module pointed to by the Module property first. So the ES module of Sam-test-Data is loaded first to support the tree-shaking feature. Let’s take a look at the official description of rollup.js:
Point to the current compiled version in the main property of the package.json file. If your package.json also has a module field, ES6-Aware tools like Rollup and WebPack 2 will import the ES6 module version directly.
Babel plug-in
Why do you need the Babel plug-in?
Create a new file main-es.js in the SRC /plugin directory:
touch src/plugin/main-es.js
Copy the code
Write the following code:
import { a, b, random } from 'sam-test-data-es'
console.log(a, b, random)
export default (base) => {
return random(base)
}
Copy the code
New ES6 features are adopted in the code: arrow function, modify configuration file:
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
export default {
input: './src/plugin/main-es.js'.output: [{
file: './dist/index-plugin-cjs.js'.format: 'cjs'
}, {
file: './dist/index-plugin-es.js'.format: 'es'}].plugins: [
resolve(),
commonjs()
]
}
Copy the code
Repacking:
rollup -c rollup.plugin.config.js
Copy the code
Dist /index-plugin-es.js
var mainEs = (base) = > {
return random(base)
};
export default mainEs;
Copy the code
As you can see, the arrow function is retained, and such code will not run in an environment that does not support ES6. We expect Babel to be used for code conversion during rollup.js packaging, so we need the Babel plug-in.
How to use the Babel plug-in
Install the Babel plugin first:
npm i -D rollup-plugin-babel
Copy the code
Modify the configuration file to add a reference to the Babel plug-in:
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import babel from 'rollup-plugin-babel'
export default {
input: './src/plugin/main-es.js'.output: [{
file: './dist/index-plugin-cjs.js'.format: 'cjs'
}, {
file: './dist/index-plugin-es.js'.format: 'es'}].plugins: [
resolve(),
commonjs(),
babel()
]
}
Copy the code
Repack:
rollup -c rollup.plugin.config.js
Copy the code
Dist /index-plugin-es.js dist/index-plugin-es.js
var mainEs = (function (base) {
return random(base);
});
export default mainEs;
Copy the code
You can see that the arrow function is converted to function, and the Babel plug-in works fine.
Json plug-in
Why do YOU need a JSON plug-in
Create a new file main-json.js under SRC /plugin:
touch src/plugin/main-json.js
Copy the code
Import package.json as a module and print the name and main properties in package.json:
import json from '.. /.. /package.json'
console.log(json.name, json.main)
Copy the code
Using able-node, try main-json.js:
$ babel-node src/plugin/main-json.js
rollup-test index.js
Copy the code
You can see that the name and main fields are printed out, and the babel-Node correctly recognizes the JSON module. Modify the rollup.js configuration file below:
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import babel from 'rollup-plugin-babel'
export default {
input: './src/plugin/main-json.js'.output: [{
file: './dist/index-plugin-cjs.js'.format: 'cjs'
}, {
file: './dist/index-plugin-es.js'.format: 'es'}].plugins: [
resolve(),
commonjs(),
babel()
]
}
Copy the code
Repack:
$rollup -c rollup.plugin.config.js./ SRC /plugin/ main-json-js →./dist/ index-plugin-js, ./dist/index-plugin-es.js... [!] Error: Unexpected token (Note that you need rollup-plugin-json to import JSON files)Copy the code
You can see that rollup.js does not support importing JSON modules by default, so we need to use json plug-ins to support this.
How to use the JSON plug-in
Download json plugin:
npm i -D rollup-plugin-json
Copy the code
Modifying a configuration file:
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import babel from 'rollup-plugin-babel'
import json from 'rollup-plugin-json'
export default {
input: './src/plugin/main-json.js'.output: [{
file: './dist/index-plugin-cjs.js'.format: 'cjs'
}, {
file: './dist/index-plugin-es.js'.format: 'es'}].plugins: [
resolve(),
commonjs(),
babel(),
json()
]
}
Copy the code
Repack:
rollup -c rollup.plugin.config.js
Copy the code
Dist /index-plugin-cjs.js json file is parsed as an object for processing:
var name = "rollup-test";
var version = "1.0.0";
var description = "";
var main = "index.js";
var scripts = {
test: "echo \"Error: no test specified\" && exit 1"
};
var author = "";
var license = "ISC";
var devDependencies = {
"@babel/core": "^ 7.1.6." "."@babel/plugin-external-helpers": "^ 7.0.0." "."@babel/preset-env": "^ 7.1.6." ".rollup: "^ 0.67.3"."rollup-plugin-babel": "^ 4.0.3"."rollup-plugin-commonjs": "^ 9.2.0"."rollup-plugin-json": "^ 3.1.0"."rollup-plugin-node-resolve": "^ 3.4.0"
};
var dependencies = {
epubjs: "^ 0.3.80".loadsh: "^ 0.0.3"."sam-test-data": "^ 0.0.4"."sam-test-data-cjs": "^ 0.0.1." "."sam-test-data-es": "^ 0.0.1." "."sam-test-data-umd": "^ 0.0.1." "
};
var json = {
name: name,
version: version,
description: description,
main: main,
scripts: scripts,
author: author,
license: license,
devDependencies: devDependencies,
dependencies: dependencies
};
console.log(json.name, json.main);
Copy the code
Uglify plug-in
The Uglify plug-in can help us further reduce the size of the code, first installing the plug-in:
npm i -D rollup-plugin-uglify
Copy the code
Modify the rollup.js configuration file:
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import babel from 'rollup-plugin-babel'
import json from 'rollup-plugin-json'
import { uglify } from 'rollup-plugin-uglify'
export default {
input: './src/plugin/main.js'.output: [{
file: './dist/index-plugin-cjs.js'.format: 'cjs'}].plugins: [
resolve(),
commonjs(),
babel(),
json(),
uglify()
]
}
Copy the code
The uglify plugin does not support the ES module and ES6 syntax, so it can only be packaged in non-ES format. If you encounter ES6 syntax, you will get an error:
$rollup -c rollup.plugin.config.js./ SRC /plugin/main.js →./dist/ index-plugin-js,./dist/index-plugin-es.js... 19 | var main = random; 20 | | > 21exportdefault main; | ^ Unexpected token: keyword (default) [!] (uglify plugin) Error: Unexpected token: keyword (default)Copy the code
So here we use sam-test-data test, because this module is compiled using Babel, the other several modules are not supported by Uglify (because the other modules use const, const is also an ES6 feature, uglify does not support). Use the Babel plugin to compile your own library. After the configuration is complete, pack it again:
$ rollup -c rollup.plugin.config.js
./src/plugin/main.js → ./dist/index-plugin-cjs.js...
created ./dist/index-plugin-cjs.js in 679ms
Copy the code
Dist /index-plugin-cjs.js
"use strict";var a=Math.floor(10*Math.random()),b=Math.floor(100*Math.random());function random(a){return a&&a%1= =0?Math.floor(Math.random()*a):0}var test=Object.freeze({a:a,b:b,random:random});console.log(test);var main=random;module.exports=main;
Copy the code
You can see that the code has been minimized and the size has been reduced a lot.
rollup.js watch
Command line mode
The watch mode of rollup.js supports monitoring code changes and automatically performs packaging once the code is modified. It is very convenient to use it by adding –watch after the packaging instruction:
$rollup -c rollup.plugin.config.js --watch rollup v0.67.1 bundles./ SRC /plugin/main-json.js → dist/index-plugin-cjs.js, dist/index-plugin-es.js... created dist/index-plugin-cjs.js, dist/index-plugin-es.jsin 24ms
[2018-11-20 22:26:24] waiting for changes...
Copy the code
The API schema
Rollup. js allows us to start watch mode through the API and create the following files in the project root directory:
- Rollup-watching-input-options. js: input configuration
- Rollup-watching-output-options. js: outputs the configuration
- Rollup-watching-options. js: listens for configuration
- Rollup-watch. js: Call the API of rollup.js to start the watch mode
To enable Node to execute our program, we use the CommonJS specification, rollup-watching-input-options. js:
const json = require('rollup-plugin-json')
const resolve = require('rollup-plugin-node-resolve')
const commonjs = require('rollup-plugin-commonjs')
const babel = require('rollup-plugin-babel')
const uglify = require('rollup-plugin-uglify').uglify
module.exports = {
input: './src/plugin/main.js'.plugins: [
json(),
resolve({
customResolveOptions: {
moduleDirectory: 'node_modules' // Only libraries in node_modules are processed
}
}),
babel({
exclude: 'node_modules/**' / / node_modules ruled out
}),
commonjs(),
uglify() // Code compression]}Copy the code
Rollup-watch-output-options. js: rollup-watch-output-options.js: rollup-watch-output-options.js
module.exports = [{
file: './dist/index-cjs.js'.format: 'cjs'.name: 'sam-cjs'
}]
Copy the code
Rollup-watching-options. js looks like this:
module.exports = {
include: 'src/**'.// Listen to the folder
exclude: 'node_modules/**' // Exclude listening folders
}
Copy the code
Rollup-watch.js code is as follows:
const rollup = require('rollup')
const inputOptions = require('./rollup-watch-input-options')
const outputOptions = require('./rollup-watch-output-options')
const watchOptions = require('./rollup-watch-options')
constoptions = { ... inputOptions,output: outputOptions,
watchOptions
} // Generate options for rollup
const watcher = rollup.watch(options) // Invoke the ROLLup API to start listening
watcher.on('event', event => {
console.log('Repacking... ', event.code)
}) // Handle listening events
// watcher.close() // Manually close the listener
Copy the code
Start listening directly from Node:
$node rollup-watch.js START repacking... BUNDLE_START repack... BUNDLE_END repack... ENDCopy the code
After modifying the SRC /plugin/main.js source code, rollup.js will automatically package the code.
conclusion
Rollup.js plugins, tree-shaking mechanism, and Watch mode are covered in detail in this tutorial.
- A rollup. Js plug-in
- Resolve plug-in: Integrate external modules
- Commonjs plug-in: Support for CommonJS modules
- Babel plug-in: Compiles ES6 syntax to be recognized by earlier browsers
- Json plug-in: Support JSON module
- Uglify: Code minimization packaging (ES module not supported)
- Tree-shaking: It is supported only by THE ES module
- Watch mode: supports command line and API modes to monitor code changes in real time