Learning to use Rollup

1. What is Rollup

Rollup is also a packager for ES Module. It can also package some scattered small modules in our project into a whole piece of code, so that these divided modules can run better in the browser environment or nodeJs environment.

In terms of function, Rollup is very similar to Webpack, but compared to Webpack, Rollup is much smaller. Because Webpack can almost complete most of the front-end engineering work in our development process with the use of some plug-ins. And Rollup is just an ES Module packager, and does not have some other extra features. For example, Webpack has a very developer-friendly module hot-replacement function such as HMR, which cannot be fully supported in Rollup.

The purpose of Rollup is not to fully compete with Webpack, its original intention is to provide an efficient bundler that takes full advantage of the features of ESM.

2. Use rollup

Install

yarn add rollup --dev

Below is my sample code:

// ======================== logger.js ========================
export const log = msg => {
  console.log('---------- INFO ----------')
  console.log(msg)
  console.log('--------------------------')
}

export const error = msg => {
  console.error('---------- ERROR ----------')
  console.error(msg)
  console.error('---------------------------')
}

// ======================== message.js ========================
export default {
  hi: 'Hey Guys, I am zce~'
}

// ======================== index.js ========================
// import module member
import { log } from './logger'
import messages from './messages'

// Using module members
const msg = messages.hi

log(msg)

Run the rollup package, specify the entry file as index.js, specify the output format as iife through the format parameter, and specify the output path through the file parameter.

yarn rollup ./src/index.js --format iife --file dist/bundle.js

dist/bundle.js

(function () {
  'use strict';

  const log = msg => {
    console.log('---------- INFO ----------');
    console.log(msg);
    console.log('--------------------------');
  };

  var messages = {
    hi: 'Hey Guys, I am zce~'
  };

  // import module member

  // Using module members
  const msg = messages.hi;

  log(msg);

}());

It can be seen that the packaging result of rollup is very concise, basically the same as the code we wrote by hand before. Compared with a lot of bootstrap code and a bunch of module functions in Webpack, the output here has almost no redundant code. It just splices the modules together in the order of module dependencies in our packaging process.

And only those parts that are used are retained in the output results, and there is no output for the unreferenced parts. This is because Rollup will automatically turn on Tree-shaking to optimize the output results. The concept of Tree-shaking was first proposed in Rollup. .

2. Rollup configuration file

Create a rollup.config.js file in the project root directory

export default {
	input: "src/index.js", // Specify the package entry file
	ouput:{ // Specify output related configuration
		file: "dist/bundle.js", //Specifies the output filename
		format: "iife" // Specify the output format
	}
}

To perform packaging, we need to use the --config parameter to indicate that we want to use the relevant configuration file. By default, the configuration file will not be read.

yarn rollup --config

You can also specify the name of the configuration file to read

yarn rollup --config rollup.config.js

3. Use plugins

Rollup's own function is only the merging and packaging of ESM modules. If our project has more advanced requirements, for example, we want to load other types of resource modules, or we want to import CommonJS modules in the code, or we want to compile ES new Features, these additional requirements, Rollup also supports the use of extensions to achieve, and plug-ins are the only extension of Rollup.

For example, if we want to use the data in package.json, we need to configure the plugin

yarn add rollup-plugin-json --dev
// rollup.config.js
import json from 'rollup-plugin-json' // This plugin module exports a function by default

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    json() // Put the result of the function call into
  ]
}
//index.js
import { name, version } from '../package.json'
log(name)
log(version)

package yarn rollup --config

The packaging result is as follows:

(function () {
  'use strict';

  const log = msg => {
    console.log('---------- INFO ----------');
    console.log(msg);
    console.log('--------------------------');
  };

  var name = "03-plugins";
  var version = "0.1.0";

  log(name);
  log(version);

}());

4. Rollup loads npm modules

By default, Rollup can only load local file modules according to the file path. For those third-party modules in node_modules, it cannot directly import the corresponding module with the module name like Webpack. In order to smooth out such a difference, Rollup officially gives a The rollup-plugin-node-resolve plugin, by using this plugin, we can import the corresponding module directly using the module name in the code.

Install

yarn add rollup-plugin-node-resolve --dev

configure

import json from 'rollup-plugin-json'
import resolve from 'rollup-plugin-node-resolve'

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    json(),
    resolve()
  ]
}

use

// import module member
import _ from 'lodash-es'// Load the esm version of lodash installed in advance, because rollup can only process esm modules by default, if we want to use the normal version, we need to do additional processing

log(_.camelCase('hello world'))

Packaging results

The content in lodash-es is packaged into bundle.js.

Five, Rollup loads the CommonJS module

Because there are still many modules that use CommonJS to export members, in order to be compatible with these modules, a rollup-plugin-commonjs plugin is officially given.

Install

yarn add rollup-plugin-commonjs --dev

configure

import commonjs from 'rollup-plugin-commonjs'
export default {
  ...,
  plugins: [
    commonjs()
  ]
}

commonjs module example

// cjs-module.js
module.exports = {
  foo: 'bar'
}
// index.js 
import cjs from './cjs-module'

log(cjs)

Packaging results

(function () {
  'use strict';
  
  var cjsModule = {
    foo: 'bar'
  };

  log(cjsModule);

}());

6. Code splitting

In the latest version of Rollup, code splitting is already supported. We can use the dynamic import method that conforms to the ESM standard to achieve on-demand loading of modules. Rollup will automatically handle code splitting, that is, subcontracting.

The configuration needs to be modified as follows:

export default {
  input: 'src/index.js',
  output: {
    dir: 'dist', // Code splitting must output multiple files, so we can't use the file attribute, because file is the file name that specifies the output of a single file, we need to use the dir attribute to output multiple files
    format: 'amd' // The format format cannot be iife, because the iife self-executing function will put all modules into one function. It does not have some bootstrap code like webpack, so it has no way to achieve code splitting. To achieve code splitting, it must be To use a standard such as amd or commonjs, we can only use the amd standard in the browser
  }
}

Packing entry:

//index.js
import('./logger').then(({ log }) => {
  log('code splitting~')
})

Packaging results

The entry js and the bundle.js corresponding to the dynamic import are generated, and they are all output by the amd standard.

Seven, multi-entry packaging

Rollup also supports multi-entry packaging, and some common parts of different entries are automatically extracted into a single file as a separate bundle.
Configuration:

export default {
  input: ['src/index.js', 'src/album.js'],
  // input: {
  //   foo: 'src/index.js',
  //   bar: 'src/album.js'
  // },
  // Both of the above methods are possible
  output: {
    dir: 'dist',
    format: 'amd'// Because the multi-entry package will automatically extract public modules, that is to say, code splitting will be used internally, so the output format of iife cannot be used.
  }
}

Execute packaging, yarn rollup --config, after packaging, there will be three more packaging files in the dist directory

Among them are the packaged files of the two entries, and the common module from which the common part is extracted.

One thing to note is that for the js file output in amd format, we cannot directly reference it on the page, but must load it through a library that implements the amd standard.

We create a new index.html file in the dist directory.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
	<!-- requireJs able to pass data-main specify require The entry path of the loaded module-->
    <script src="https://unpkg.com/requirejs@2.3.6/require.js" data-main="album.js"></script>
</body>
</html>

Execute serve dist to start the server, and you can see that our packaging results are loaded and working normally.

Summarize

Through the above exploration and attempts, we found that Rollup does have its advantages.

  1. Its output results are flatter, and the execution efficiency will be higher.
  2. it automatically removes unreferenced code
  3. Packed results are still fully readable

But his shortcomings are also obvious:

  1. It is more complicated to load some non-ESM third-party modules
  2. Modules are eventually packaged into a function, which cannot implement HMR
  3. In the browser environment, the code splitting function depends on the AMD library

Combining the above characteristics, we found that if we are developing an application, we definitely need to introduce a large number of third-party modules. At the same time, we need functions such as HMR to improve our development experience. When it comes to having to subcontract, Rollup will have some deficiencies in meeting these requirements.

And if we are developing a framework or a class library, these advantages are especially necessary. This disadvantage can almost be ignored. Take loading third-party modules as an example. When we develop a class library, it is rarely in the code. Depends on some third-party modules, so many frameworks like React and Vue use Rollup as a module packager.

To sum up, Webpack is large and complete, while Rollup is small and beautiful. For the choice between the two, we basically choose Webpack for developing applications, and Rollup for developing frameworks or class libraries.

Tags: rollup

Posted by blueway on Wed, 04 May 2022 10:23:30 +0300