In the previous chapter we learned how to quickly get started with rollup and how to use rollup for packaging operations. What are the three most important rollup configurations? Yes, that’s input, output, and plugins. This is how plugins work in rollup.

Rollup

What are plugins?

Let’s first look at how plugins are used in configuration

//rollup.config.js import myExample from './rollup-plugin-my-example.js'; export default ({ input: 'index.js', // resolved by our plugin output: [{ file: './dist/bundle.js', format: }], plugins: [myExample()] // });Copy the code

Plugins are an array of plugins that can be referenced as multiple plugins. If you want to use a plugin, you need to import the plugins and install the plugins.

The rollup documentation is a good way to learn

You can seerollupA plug-in is an object consisting of one or more attributes, hooks, etc.

Go to Github and search rollup/plugins-> Packages to find the plugins. Use json as an example to see the code

import { createFilter, dataToEsm } from '@rollup/pluginutils';

export default function json(options = {}) {
  const filter = createFilter(options.include, options.exclude);
  const indent = 'indent' in options ? options.indent : '\t';

  return {
    name: 'json',

    // eslint-disable-next-line no-shadow
    transform(json, id) {
      if (id.slice(-5) !== '.json' || !filter(id)) return null;

      try {
        const parsed = JSON.parse(json);
        return {
          code: dataToEsm(parsed, {
            preferConst: options.preferConst,
            compact: options.compact,
            namedExports: options.namedExports,
            indent
          }),
          map: { mappings: '' }
        };
      } catch (err) {
        const message = 'Could not parse JSON file';
        const position = parseInt(/[\d]/.exec(err.message)[0], 10);
        this.warn({ message, id, position });
        return null;
      }
    }
  };
}
Copy the code

You can pass in an option argument, which defaults to null, and see that return returns an object containing the property name and hook transform.

I’ll explain hooks in more detail below. Check out the plugins I wrote myself

Export default {input: './index.js', // output: {// export file: './dist/bundle.js', // File path format: 'CJS' // output format}, plugins: [{ buildStart() { console.log(1, 'buildStart'); }, a() { console.log(a); } }, { options() { console.log(2, 'options'); }}};Copy the code

Now that I know that a plug-in is an object with properties and hooks in it, isn’t it okay if I just add an object with hooks in it? Is the principle the same? If you can’t verify it, run it

2 options and 1 buildStart. Why only two functions are printed when there are three? If you write a custom function, it doesn’t have the hook inside, so it doesn’t execute. What’s the second conclusion? The order in which the plug-in is introduced is independent of the order in which the plug-in is introduced, since the introduction is 1 first.

Now that you know something about rollup plugins,

The build process

After looking at this image, we need to take a look at the packaging process of rollup to understand it.

options

This is the first hook before the build, and can be passed in parameters to replace the default configuration parameters. If no parameters are configured, it is packaged with the default configuration of rollup.config.js.

buildStart

Begin to build

resolveId

This hook is used to parse the path of all files. For example:

import jq from 'jquery' import b from './b.js' import JQ from 'http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js' in the console. The log (b); console.log(jq); console.log(JQ);Copy the code

How to package a file when local files, online files and third-party files may be imported? Think about it……

You might say, just add it to the packaged file, but a computer is a computer, not what a human eye sees, so it needs to be transformed into a path that he can recognize.

There are five import modes: virtual module, user module, third-party module, built-in module and data protocol. The hook resolves the import mode paths of these modules, such as relative paths that will eventually be converted to absolute paths, which are implemented internally.

load

ResolveId = resolveId = resolveId = resolveId = resolveId = resolveId = resolveId

For example

//a.js
import './b.js'
Copy the code
//b.js
import './c.js'

const b = 'b'
console.log(b);
Copy the code
//c.js
console.log('c');
Copy the code

In this side, A is the entry file, which packages A. js. B. js file is introduced into A. js, and C. js file is introduced into B. Js file. When loading, all contents will be loaded into the same JS file. Check out the results:

//bundle.js
'use strict';

console.log('c');

const b = 'b';
console.log(b);

Copy the code

transform

Js /.json /.node files are not recognized, but you can’t have only these files in a project. Simple things like image.jpg or.ts files are not parsed. So we need the transform hook to transform an unrecognized file into a recognized.js file so that we can continue packaging.

moduleParsed

If the imported file has other dependencies, the module will return ·resolveId and continue execution until all modules have been loaded and converted, at which point the loaded content will be a string, and moduleParsed will render the string, Convert to AST (Abstract Syntax Tree) format.

import a from '12313'

let tips = [
  "Click on any AST node with a '+' to expand it",

  "Hovering over a node highlights the \
   corresponding location in the source code",

  "Shift click on an AST node to expand the whole subtree"
];

function printTips() {
  tips.forEach((tip, i) => console.log(`Tip ${i}:` + tip));
}
Copy the code

This is a basic JS file structure, there are imports, there are variables, there are functions, by this step has all the content parsing in, let’s look at the generated AST tree structure, each structure has the type attribute and the start end character number and end position, converted into a clear tree structure

buildEnd

The end of the construct

summary

Now that you know about the hooks in the build phase, go back to the plugins above. Plugins are objects that contain properties and hooks, and the hooks are those in the build phase. When are those hooks executed? How to enforce it?

Here I wrote an example, to deepen the impression, you can also try their own, so as to better memory.

Export default {input: './a.js', // output: {// export file: './dist/bundle.js', // file path format: 'CJS' // output format}, plugins: [{ buildStart() { console.log(1, 'buildStart'); }, }, { options() { console.log(2, 'options');  }, resolveId() { console.log(2, 'resolveId'); } }, { transform() { console.log(3, 'transform');  }, load() { console.log(3, 'load'); }, moduleParsed() { console.log(3, 'moduleParsed');  } }, { buildStart() { console.log(4, 'buildStart'); }, buildEnd() { console.log(4, 'buildEnd'); } } ] };Copy the code

Here we have our own plugins, and we need nothing more to test hook execution. The first plugins output 1 + the name of the hook, and so on. There are four plugins, all of which contain different hooks.

The first printed code is “2 options”, which is the code executed by the options hook in the second plug-in. Therefore, it is confirmed that the order in which the plug-in is introduced is not related to the execution order, but is related to the hooks contained in the plug-in. At each step of execution, the plugins are iterated once to check whether there are corresponding hooks in the plug-in. And execute it. In simple terms, assuming that buildStart is implemented, every object in the plug-in will be automatically iterated to see if any of them have a buildStart hook, executed if they do, and continued if they do not. And every hook is like that.

How is VUe2 packaged using rollup

After learning about rollup, let’s take a look at how rollup is packaged in other projects. Using VUe2 as an example, let’s look at more advanced uses of rollup or ways you may not know how to use rollup.

To view the code of a project first of course is to pull the code, here attached vue2 source code, first pull down the code, we continue.

package.json

Json file. README looks at the description and usage of the project. Package. json looks at some commands. So let’s start with the package.json file.

We found the package.json field, but if there is no purpose to it, I don’t know what to do with it. It is very difficult to find the package.json field. Look at the build directive first.

Nodescripts /build.js command is used to execute the build.js file under scripts.

build.js

Rollup has been introduced in build.js, so you don’t need to read the source code line by line, just the key parts, so let’s move on.

Call build() and pass in an argument. Build () is a function that builds a package

function build (builds) {
  let built = 0
  const total = builds.length
  const next = () => {
    buildEntry(builds[built]).then(() => {
      built++
      if (built < total) {
        next()
      }
    }).catch(logError)
  }
  next()
}
Copy the code

As you can see from the code, there’s another function called, buildEntry, which is also an asynchronous function, continuing with the buildEntyr function.

function buildEntry (config) {
  const output = config.output
  const { file, banner } = output
  const isProd = /(min|prod)\.js$/.test(file)
  return rollup.rollup(config)
    .then(bundle => bundle.generate(output))
    .then(({ output: [{ code }] }) => {
      if (isProd) {
        const minified = (banner ? banner + '\n' : '') + terser.minify(code, {
          toplevel: true,
          output: {
            ascii_only: true
          },
          compress: {
            pure_funcs: ['makeMap']
          }
        }).code
        return write(file, minified, true)
      } else {
        return write(file, code)
      }
    })
}
Copy the code

What’s the most important thing about looking at a function? Rollup returns a method rollup. Rollup returns a method rollup. Rollup returns a method rollup.

rollup.rollup

Rollup. Rollup takes a configuration object as an argument and returns a Promise object that resolves the bundle object with various properties and methods. In this step, tree-shaking,

In a bundle object, you can use the bundle.generate method to package different versions of the bundle.

 rollup.rollup(config)
    .then(bundle => bundle.generate(output))
    .then(({ output: [{ code }] }) => {
      if (isProd) {
        const minified = (banner ? banner + '\n' : '') + terser.minify(code, {
          toplevel: true,
          output: {
            ascii_only: true
          },
          compress: {
            pure_funcs: ['makeMap']
          }
        }).code
        return write(file, minified, true)
      } else {
        return write(file, code)
      }
    })
Copy the code

Rollup.rollup (config).then(bundle => bundle.generate(output)) Let’s go back and look at the input parameter. What is the configuration parameter passed in?

Follow the parameters up to see what builds are defined at the beginning, with the config.js file introduced, so let’s go to the config.js file to see what builds are defined and what getAllBuilds() does. The vue source code is too long to paste over, so you have to do it yourself. Here is how to view and learn how to use the rollup package for VUe2.

config.js

Config.js introduces a large number of rollup plugins.

The next step is to find out where the getAllBuilds method is, as it is introduced in build.js, and go to the bottom:

Keys would be used to iterate over builds, generate a map, and return the Settings to the build.js file.

conclusion

Learn how to view the source of the project, the first thing to determine their own goals, with the purpose and the problems to see, so just have a direction, after all, a project is so big, it is not practical to a file is a file is a waste of time, learning efficiency is not high, even to the last may also look not to understand, the specific process step by step I have detailed list, And the analysis, is also a beginner, there is a lot of room for improvement, we can learn from.