preface

Rollup.js — Vue.js source code packaging process in-depth analysis of the “10 minutes fast master rollup.js – vue.js source code packaging process for the purpose of understanding, will not do too much expansion. In keeping with the rollup.js series, most of the knowledge points will provide examples of working code and actual results, so that you can see the implementation through the tutorial without having to test it yourself.

This tutorial requires you to understand the use of the Buble, Flow, and Terser modules. For those who are not already familiar with this tutorial, check out this tutorial: 10 Minutes for Quick Mastery of Rollup.js: Pre-Learning Basics.

1. The rollup plugin – buble plug-in

Convert ES2015 with buble.

The buble plugin is used to compile code during the rollup.js package. Compile ES6+ code to the ES2015 standard.

npm i -D rollup-plugin-buble
Copy the code

/ SRC /vue/buble/index.js

const a = 1 // New in ES6: const
let b = 2 // New in ES6: let
const c = (a)= > a + b New in ES6: arrow functions
console.log(a, b, c())
Copy the code

Modify the rollup.plugin.config.js configuration file:

import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import buble from 'rollup-plugin-buble'

export default {
  input: './src/vue/buble/index.js'.output: [{
    file: './dist/index-plugin-cjs.js'.format: 'cjs'}].plugins: [
    resolve(),
    commonjs(),
    buble()
  ]
}
Copy the code

Compile with rollup.js:

$ rollup -c rollup.plugin.config.js 
./src/vue/buble/index.js  ./dist/index-plugin-cjs.js...
created ./dist/index-plugin-cjs.js in 35ms
Copy the code

To view the contents of the build file:

$ cat dist/index-plugin-cjs.js 
'use strict';

var a = 1;
var b = 2;
var c = function () { return a + b; };
console.log(a, b, c());
Copy the code

Execute the packaged code from Node:

$ node dist/index-plugin-cjs.js 
1 2 3
Copy the code

2. A rollup plugin – alias plug-in

Provide an alias for modules in Rollup

The Alias plugin provides the ability to alias modules. If you have used WebPack, you should be familiar with this feature. First introduce the Alias plugin to your project:

npm i -D rollup-plugin-alias
Copy the code

Create a SRC /vue/alias directory and create a local test library lib.js and test code index.js:

mkdir -p src/vue/alias
touch src/vue/alias/index.js
touch src/vue/alias/lib.js
Copy the code

Write the following in lib.js:

export function square(n) {
  return n * n
}
Copy the code

In index.js, write the following:

import { square } from '@/vue/alias/lib' // Use an alias

console.log(square(2))
Copy the code

Modify the rollup.plugin.config.js configuration file:

import alias from 'rollup-plugin-alias'
import path from 'path'

const pathResolve = p= > path.resolve(__dirname, p)

export default {
  input: './src/vue/alias/index.js'.output: [{
    file: './dist/index-plugin-es.js'.format: 'es'}].plugins: [
    alias({
      The '@': pathResolve('src')]}})Copy the code

Here we provide a pathResolve method that generates an absolute path, introducing the Alias plugin where we pass in an object whose key is the alias used in the module, and whose value is the real path corresponding to the alias. Use rollup.js for packaging:

$ rollup -c rollup.plugin.config.js 

./src/vue/alias/index.js  ./dist/index-plugin-es.js...
created ./dist/index-plugin-es.js in 23ms
Copy the code

Looking at the packaged code, you can see that the path to the alias is correctly identified:

$ cat dist/index-plugin-es.js 
function square(n) {
  return n * n
}

console.log(square(2));
Copy the code

3. The rollup – plugin – flow – no – whitespace plug-in

The flow plugin is used to clear the flow type checking part of the code during the rollup.js packaging process. We modify the input property of rollup.plugin.config.js:

input: './src/vue/flow/index.js'.Copy the code

Try packaging the flow code directly:

$ rollup -c rollup.plugin.config.js ./src/vue/flow/index.js ./dist/index-plugin-cjs.js... [!]  Error: Unexpected token src/vue/flow/index.js (2:17) 1: /* @flow */ 2:function square(n: number): number {
                    ^
3:   return n * n
4: }
Error: Unexpected token
Copy the code

As you can see, rollup.js throws an exception. To solve this problem we introduced the flow plugin:

npm i -D rollup-plugin-flow-no-whitespace
Copy the code

Modifying a configuration file:

import flow from 'rollup-plugin-flow-no-whitespace'

export default {
  input: './src/vue/flow/index.js'.output: [{
    file: './dist/index-plugin-cjs.js'.format: 'cjs'}].plugins: [
    flow()
  ]
}
Copy the code

Re-run packaging:

$ rollup -c rollup.plugin.config.js 
./src/vue/flow/index.js  ./dist/index-plugin-cjs.js...
created ./dist/index-plugin-cjs.js in 40ms
Copy the code

View the packaged source code:

$ cat ./dist/index-plugin-cjs.js 
'use strict'; / * * /function square(n) {
  return n * n
}

console.log(square(2));
Copy the code

You can see that the flow code was cleared successfully, but /* @flow */ was changed to /* */. This problem can be fixed using the Terser plugin to remove comments.

4. A rollup plugin – replace plug-in

Replace content while bundling

The replace plugin is used to dynamically replace the content in the code when packaging, starting with the replace plugin:

npm i -D rollup-plugin-replace
Copy the code

Create the SRC /vue/replace folder and index.js test file:

mkdir -p src/vue/replace
touch src/vue/replace/index.js
Copy the code

In the index.js file, write the following:

const a = 1
let b = 2
if (__SAM__) { // Use the replace value __SAM__. Note that this value is undefined, and an error will be reported if run directly
  console.log(`__SAM__,${a}.${b}.${c}`) // Use __SAM__, which will be replaced when packaged
}
Copy the code

Modify the rollup.plugin.config.js configuration file:

import buble from 'rollup-plugin-buble'
import replace from 'rollup-plugin-replace'

export default {
  input: './src/vue/replace/index.js'.output: [{
    file: './dist/index-plugin-cjs.js'.format: 'cjs'}].plugins: [
    replace({
      __SAM__: true
    }),
    buble()
  ]
}
Copy the code

We pass an object to the Replace plug-in with key __SAM__ and value true. So rollups.js packaging will replace __SAM__ with true. It is worth noting that the code uses ES6 features, so we need to introduce the Buble plugin to compile. We execute the packaging instruction:

$ rollup -c rollup.plugin.config.js 
./src/vue/replace/index.js  ./dist/index-plugin-cjs.js...
created ./dist/index-plugin-cjs.js in 28ms
Copy the code

View packing results:

$ cat dist/index-plugin-cjs.js 
'use strict';

var a = 1;
var b = 2;
{
  console.log(("true," + a + "," + b + "," + c));
}
Copy the code

You can see that __SAM__ is correctly replaced with true. If you are using the WebStorm editor, there will be a warning if you use the flow syntax. In this case, you need to open the Settings, go to Languages & Frameworks > Javascript, and change the Javascript language version to Flow.

declare type Test = { a? : number;// THE type of a is number, which can be nullb? : string;// b is of type string and can be null
  c: (key: string) = > boolean; // c is of type function and can contain only one parameter. The type is string and the return value is Boolean. Note that c cannot be empty
}

declare var __SAM__: boolean; // Add custom variables
Copy the code

5. A rollup plugin – terser plug-in

Rollup plugin to minify generated es bundle

The Terser plugin helps us compress code during the rollup.js packaging process by introducing the Terser plugin:

npm i -D rollup-plugin-terser
Copy the code

SRC /vue/replace/index.js: SRC /vue/replace/index.js

/* @flow */
import { square } from '@/vue/alias/lib' // Import the local module through an alias
import { random } from 'sam-test-data' // Import es module
import { a as cjsA } from 'sam-test-data-cjs' // Import the CommonJS module

const a: number = 1 // Type check with flow
let b: number = 2 // Use the new ES6 feature: let
const c: string = ' ' // Add non-ASCII characters
if (__SAM__) { // Use the replace string
  console.log(`__SAM__,${a}.${b}.${c}`) // Use the new ES6 feature template string
}
export default {
  a, b, c, d: __SAM__, square, random, cjsA
} // Export ES module
Copy the code

We want to verify the following functionality with the above code:

  • Replace plugin: __SAM__ is replaced correctly in the code;
  • Flow plugins: Remove flow type checking code correctly;
  • Buble plugin: Compile ES6+ code to ES2015;
  • Alias plugin: replace the ‘@’ alias in the module with the ‘SRC’ directory;
  • Commonjs plugin: support commonJS module;
  • Resovle plug-in: merges external module code;
  • Terser plug-in: Code minimization packaging.

Modify the rollup.plugin.config.js configuration file:

import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import buble from 'rollup-plugin-buble'
import replace from 'rollup-plugin-replace'
import flow from 'rollup-plugin-flow-no-whitespace'
import { terser } from 'rollup-plugin-terser'
import alias from 'rollup-plugin-alias'
import path from 'path'

const pathResolve = p= > path.resolve(__dirname, p)

export default {
  input: './src/vue/replace/index.js'.output: [{
    file: './dist/index-plugin-es.js'.format: 'es'}].plugins: [
    replace({
      __SAM__: true
    }),
    flow(),
    buble(),
    alias({
      The '@': pathResolve('src')
    }),
    commonjs(),
    resolve(),
    terser({
      output: {
        ascii_only: true // Outputs only ASCII characters
      },
      compress: {
        pure_funcs: ['console.log'] // Remove the console.log function]}}}),Copy the code

The terser plug-in is configured in the same way as the API pattern, with the package code:

$ rollup -c rollup.plugin.config.js 
./src/vue/replace/index.js  ./dist/index-plugin-es.js...
created ./dist/index-plugin-es.js in 308ms
Copy the code

View the packaged code file:

$ cat dist/index-plugin-es.js 
function square(a){return a*a}function random(a){returna&&a%1==0? Math.floor(Math.random()*a):0}var aThe $1=Math.floor(10*Math.random()),bThe $1=Math.floor(100*Math.random());function randomThe $1(a){returna&&a%1==0? Math.floor(Math.random()*a):0}var _samTestDataCjs_0_0_1_samTestDataCjs={a:aThe $1,b:bThe $1,random:randomThe $1},_samTestDataCjs_0_0_1_samTestDataCjs_1=_samTestDataCjs_0_0_1_samTestDataCjs.a,a$2=1,b$2=2,c="\ud83d\ude00",index={a:a$2,b:b$2,c:c,d:! 0,square:square,random:random,cjsA:_samTestDataCjs_0_0_1_samTestDataCjs_1};export default index;
Copy the code

To see all the features in effect, try running the code through babel-Node:

$ babel-node 
> require('./dist/index-plugin-es')
{ default:
   { a: 1,
     b: 2,
     c: ' ',
     d: true,
     square: [Function: square],
     random: [Function: random],
     cjsA: 4 } }
Copy the code

If the code runs successfully, the packaging process succeeds.

6. Intro and outro configuration

The intro and outro attributes are similar to the banner and footer attributes we discussed earlier, and are used to add comments to code. So what’s the difference between these four attributes? The rollup.js website explains these four properties:

  • Intro: Inserts a piece of content at the very top of the wrapper inside the block of the wrapped file
  • Outro: Inserts a piece of content at the bottom of the wrapper inside the block of a wrapped file
  • Banner: Inserts a piece of content at the top of the wrapped file block outside the wrapper
  • Footer: Inserts a piece of content at the bottom of the wrapped file block outside the wrapper

SRC /plugin/main.js SRC /plugin/main.js SRC /plugin/main.js SRC /plugin/main.js SRC /plugin/ outro SRC/outro SRC/outro SRC/outro SRC/outro SRC/outro

const a = 1
console.log(a)
export default a
Copy the code

Modify rollup.config.js configuration:

export default {
  input: './src/plugin/main.js'.output: [{
    file: './dist/index-cjs.js'.format: 'cjs'.banner: '// this is banner'.footer: '// this is footer'.intro: '// this is a intro comment'.outro: '// this is a outro comment',}}]Copy the code

Package code:

$ rollup -c

./src/plugin/main.js  ./dist/index-cjs.js...
created ./dist/index-cjs.js in 11ms
Copy the code

Output result:

$ cat dist/index-cjs.js 
// this is banner
'use strict';

// this is a intro comment

const a = 1;
console.log(a);

module.exports = a;

// this is a outro comment
// this is footer
Copy the code

You can see that the banner and footer are on the outer layer, while the intro and outro are on the inner layer, and the intro is under ‘use strict’. So if you want to wrap something like module.exports or export default around the outer layer of your code, You need to use intro and outro, which are used in the vue.js source packaging process to add modular features to the code. We can also do this by writing the intro and outro configuration to the plugins method:

export default {
  input: './src/plugin/main.js'.output: [{
    file: './dist/index-cjs.js'.format: 'cjs'.banner: '// this is banner'.footer: '// this is footer'}].plugins: [{intro: '// this is a intro comment'.outro: '// this is a outro comment'}}]Copy the code

The configuration file generates the same effect as before.

conclusion

This tutorial focuses on the following points:

  • Rollup-plugin-buble: compiles ES6+ syntax to ES2015, requires no configuration, and is lighter than Babel.
  • Rollup-plugin-alias: replaces the alias in the module path;
  • Rollup-plugin-flow-no-whitespace: remove static type checking code for flow;
  • Rollup-plugin-replace: replaces the variable in the code with the specified value;
  • Rollup-plugin-terser: code compression, replaces Uglify, supports ES module.
  • Intro and Outro configurations: Add code comments within a code block.