Why learn rollup.js

Rollup. js is the ES module wrapper for Javascript, and many well-known frameworks or libraries such as Vue and React are packaged with rollup.js. Unlike Webpack’s orientation towards application packaging, rollup.js is more focused on Javascript library packaging (although rollup.js can also provide resource packaging, which is clearly not its strong suit). Rollup.js is a must for learning the source code of frameworks like Vue and React or writing our own Javascript libraries.

How rollup.js works

Rollup.js can package our own Javascript code (with plugins that support more languages like Tyepscript) with third-party modules into a file, which can be a Library or an App. Various plug-ins can be applied during the packaging process to achieve specific functionality. The following diagram illustrates how rollup.js works:

Install a rollup. Js

Rollup. js installation depends on nodejs. In the previous notes, I detailed how to manage nodeJS versions with NVM

Rollup.js is installed globally

First install rollup globally:

npm i rollup -g
Copy the code

Rollup.js packages the instance

After the installation is successful, we try a simple example using rollup to create a SRC directory:

mkdir src
Copy the code

Create a.js under SRC directory:

vim src/a.js
Copy the code

This module is very simple and exposes only one variable, a:

const a = 1
export default a
Copy the code

Create main.js from SRC:

vim src/main.js
Copy the code

This module will introduce module A and expose a function:

import a from './a.js'
  
export default function() {
  console.log(a)
}
Copy the code

With the rollup directive, we can quickly preview the packaged source code, much like Babel:

$ rollup src/main.js -f es

src/main.js  stdout...
const a = 1;

function main() {
  console.log(a);
}

export default main;
created stdout in 26ms
Copy the code

Note that rollup must have a -f parameter, otherwise an error will be reported:

$ rollup src/main.js src/main.js stdout... [!]  Error: You must specify output.format,which can be one of 'amd'.'cjs'.'system'.'esm'.'iife' or 'umd'
https://rollupjs.org/guide/en#output-format-f-format
Copy the code

The rollup error notification is great for locating errors and fixing problems. From the error above, we know that the value of -f can be any of ‘AMD’, ‘CJS’, ‘system’, ‘ESM’ (‘es’ also works), ‘iife’, or ‘umD’. The -f argument is short for –format, which indicates the format of the generated code, AMD indicates the AMD standard, CJS is the CommonJS standard, and ESM (or ES) is the ES module standard. We then output this code to a file:

$ rollup src/main.js -f es -o dist/bundle.js

src/main.js  dist/bundle.js...
created dist/bundle.js in 29ms
Copy the code

The -o parameter specifies the output path. Here we output the packaged file to bundle.js in the dist directory. The contents of the file are exactly the same as what we previewed earlier. Let’s print CommonJS code again:

$ rollup src/main.js --format cjs --output.file dist/bundle-cjs.js

src/main.js  dist/bundle-cjs.js...
created dist/bundle-cjs.js in 27ms
Copy the code

–output.file is the full name of -o. They are equivalent. After output, we have a bundle-cjs.js file in the dist directory.

'use strict';
  
const a = 1;

function main() {
  console.log(a);
}

module.exports = main;
Copy the code

As you can see, the code is written in CommonJS standard and fuses a.js and main.js files.

Verify the rollup.js package results

After successful packaging, we try to run the dist/bundle-cjs.js code:

$ node
> const m = require('./dist/bundle-cjs.js')
> m()
1 
Copy the code

Dist /bundle.js is not supported by the ES standard.

$ node
> require('./dist/bundle.js')()
/Users/sam/Desktop/rollup-test/dist/bundle.js:7
export default main;
^^^^^^

SyntaxError: Unexpected token export
Copy the code

Babel provides us with a tool: Babel-node, which converts ES code to CommonJS format at runtime, makes it possible to run ES code. @babel/cli contains Babel, and both tools rely on @babel/core, so it is recommended to install both:

npm i @babel/core @babel/node @babel/cli -g
Copy the code

Note that Babel 7 has changed the name of the NPM package. The previous versions of babel-core and babel-cli have been deprecated.

npm uninstall babel-cli babel-core -g
Copy the code

Then go to the root directory of the code and initialize the project:

npm init
Copy the code

After press Enter, create a configuration file for Babel in the code root directory. Babelrc and write the following configuration

{
  "presets": ["@babel/preset-env"]}Copy the code

Install Babel dependencies after configuring Babel:

npm i -D @babel/core @babel/preset-env
Copy the code

Try compiling code with Babel:

$ babel dist/bundle.js 
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var a = 1;

function main() {
  console.log(a);
}

var _default = main;
exports.default = _default;
Copy the code

You can see the ES module code compiled into CommonJS format and run the code through babel-Node:

$ babel-node 
> require('./dist/bundle.js')
{ default: [Function: main] }
> require('./dist/bundle.js').default()
1
Copy the code

Note that Babel considers export default function() to be a function named default. If you want to change the function name, you can modify main.js:

import a from './a.js'
  
export function test() {
  console.log(a)
}
Copy the code

Rewrite packaged and run via babel-node:

$ rollup -f es --file dist/bundle.js src/main.js 

src/main.js  dist/bundle.js...
created dist/bundle.js in 26ms

$ babel-node 
> require('./dist/bundle.js').test()
1
Copy the code

Note that –file is priced at -o and –output.file. With the above example, we completed the rollup package and verified the package result. Most of the time we don’t do this because using the command line directly is one-dimensional and plug-ins are not available, so we need to use configuration files to do this.

Rollup.js configuration file

First create the rollup.config.js file in the code root:

touch rollup.config.js
Copy the code

Write the following configuration:

export default {
  input: './src/main.js'.output: [{
    file: './dist/index-cjs.js'.format: 'cjs'.banner: '// welcome to imooc.com'.footer: '// powered by sam'
  }, {
    file: './dist/index-es.js'.format: 'es'.banner: '// welcome to imooc.com'.footer: '// powered by sam'}}]Copy the code

The rollup configuration file is very easy to understand, and there are a few things to note:

  • Rollup configuration files need to be written in ES module standard
  • Input indicates the path of the entry file (the old version is Entry, which has been abandoned)
  • Output represents the contents of an output file. It allows an object or an array to be passed in. When an array is passed in, multiple files in turn are output, which contains the following contents:
    • Output. file: path to the output file (dest in the older version is deprecated)
    • Format: indicates the format of the output file
    • Output. banner: the content added to the file header
    • Output. footer: The content added to the end of the file

Rollup.js automatically looks for a configuration file named rollup.config.js, which is packaged with the rollup -c directive:

$ rollup -c

./src/main.js  ./dist/index-cjs.js, ./dist/index-es.js...
created ./dist/index-cjs.js, ./dist/index-es.js in 13ms
Copy the code

Dist /index-es.js

// welcome to imooc.com
const a = 1;

function test() {
  console.log(a);
}

export { test };
// powered by sam
Copy the code

The content of the code is identical to that generated on the command line, but custom comment information is added to the header and end. Next we change the name of the configuration file and package it by specifying the configuration file with the -c argument:

$ mv rollup.config.js rollup.config.dev.js
$ rollup -c rollup.config.dev.js 

./src/main.js  ./dist/index-cjs.js, ./dist/index-es.js...
created ./dist/index-cjs.js, ./dist/index-es.js in 13ms
Copy the code

A rollup. Js API package

Write the rollup.js configuration

In many cases, the packaging method of command line and configuration file cannot meet the requirements, and we need more personalized packaging method. In this case, we can consider packaging through the API of rollup.js, create rollup-input-options.js, which is the input configuration, and package a module separately. Improved reusability and scalability:

touch rollup-input-options.js
Copy the code

Add the following to the input configuration file. Note that the file must be in CommonJS format because nodeJS is used for execution:

module.exports = {
  input: './src/main.js'
}
Copy the code

Add another output configuration file:

touch rollup-output-options.js
Copy the code

In the output configuration file, we still use an array to implement the output of multiple file formats. Note that the UMD format must specify the name of the module, which is implemented through the name attribute:

module.exports = [{
  file: './dist/index-cjs.js'.format: 'cjs'.banner: '// welcome to imooc.com'.footer: '// powered by sam'
}, {
  file: './dist/index-es.js'.format: 'es'.banner: '// welcome to imooc.com'.footer: '// powered by sam'}, {file: './dist/index-amd.js'.format: 'amd'.banner: '// welcome to imooc.com'.footer: '// powered by sam'}, {file: './dist/index-umd.js'.format: 'umd'.name: 'sam-umd'.// Specify the file name
  banner: '// welcome to imooc.com'.footer: '// powered by sam',}]Copy the code

Write the rollup.js build code

Next we will install the rollup library in the current project:

npm i -D rollup
Copy the code

Create a rollup-build file that calls the ROLLup API:

touch rollup-build.js
Copy the code

Rollup-build: rollup-build:

const rollup = require('rollup')
const inputOptions = require('./rollup-input-options')
const outputOptions = require('./rollup-output-options')

async function rollupBuild(input, output) {
  const bundle = await rollup.rollup(input) // Package according to the input configuration
  console.log('generating:${output.file}`)
  await bundle.write(output) // Configure the output file according to output
  console.log(`${output.file}Build successful! `)} (async function () {
  for (let i = 0; i < outputOptions.length; i++) {
    await rollupBuild(inputOptions, outputOptions[i])
  }
})()
Copy the code

At the heart of the code are two things:

  • throughrollup.rollup(input)Get the package object
  • throughbundle.write(output)Output package file

Here we can also synchronize operations with async and await, because bundle.write(output) is asynchronous and will return a Promise object, we can use async mechanism to implement packaging in configuration order. Execute rollup-build file:

$node rollup-build.js:./dist/index-cjs.js./dist/index-cjs.js. Dist /index-es. Js./dist/index-es. Js. /dist/index-amd.js /dist/index-amd.js generated successfully! /dist/index-umd.js:./dist/index-umd.jsCopy the code

Dist /index-umd.js

(function (global, factory) {
  typeof exports === 'object' && typeof module! = ='undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (factory((global['sam-umd'] = {}))); } (this, (function (exports) {
	// ...
}
Copy the code

You can see in the index-umd.js file that the sam-umd attribute was added to the global variable, which is why we needed to add the name attribute to the UMD configuration earlier.

conclusion

This article introduced you to three ways to package Rollup.js: command line, configuration file, and API. In the next tutorial, I will continue to introduce you to more features of Rollup.js, such as tree-shaking, watch, and more.