When I was looking for a job, I was almost scorned by an interviewer for saying “skilled in building rollup.js” on my resume, but I couldn’t figure out what formats rollup could package.

It really shouldn’t!

So I restudied and combed it again and shared it with everyone.

Learn this article 📖

You will be:

  1. Understand several formats for vite and rollup output, and understand their relationships and usage scenarios.
  2. Get one of the simplestrollup.jspackagingdemoA.
  3. thedemoThere is also an executable for each packaging resultdemo of demo

Why do you want to learn this?

As viet.js has grown in popularity, it has also become a frequent question in job production and interview q&A sessions.

As we all know, the core of the viet.js build is rollup.js.

So why is it necessary to learn the JS modularity specification before learning them?

Because we need to understand what the end product is and how it works.

“Worship magic” is a taboo for programming learners, “curiosity” is the ladder of our growth and progress.

Let’s take a look at the packaged code and see what it is!

DEMO and sample building

Please cooperate with the demo to eat, you will gain more!

I built a simple demo for this article, and the source code is available on Github.

Demo address: github.com/zhangshichu… The code structure of Demo is as follows:

├ ─ ─ answer. Js ├ ─ ─ index. The js ├ ─ ─ out ├ ─ ─ package. The json ├ ─ ─ a rollup. Config. Js └ ─ ─ yarn. The lockCopy the code

Among them, index.js and answer.js belong to the business code and are the objects to be packaged. Answer.js is relied on in index.js. As follows:

// answer.js
export default 42

// index.js
import answer from "./answer";
import { repeat } from 'lodash'
// Define a null variable, test tree-shaking
const unusedVar = 'May the 4th'

export const printAnswer = () = > {
  / / print
  console.log(`the answer is ${answer}`)
  // Test lodash's ability to print 42 ones
  console.log(repeat('1', answer))
}
Copy the code

Rollup.config. js is the rollup configuration file, in which we specify the output of amd, CJS, ESM, IIFE, UMD, system files respectively.

The output files are packaged into the out folder.

When we execute YARN build or NPM build, we generate code in the following format under OUT:

├ ─ ─ out │ ├ ─ ─ amd │ │ └ ─ ─ bundle. Js │ ├ ─ ─ CJS │ │ └ ─ ─ bundle. Js │ ├ ─ ─ ems │ │ └ ─ ─ bundle. Js │ ├ ─ ─ iife │ │ └ ─ ─ bundle. Js │ ├ ─ ─ system │ │ └ ─ ─ bundle. Js │ └ ─ ─ umd │ └ ─ ─ bundle. JsCopy the code

In order to understand how bundle.js files in each format work, I have customized a few small attached demos for them.

Let’s learn and analyze format by format.

IIFE self-executing functions

The full name of IIFE is “Immediately Invoked Function Expression”.

1.1 Analysis of packaging results

Let’s take a look at what the iife package looks like.

To simplify the above code:

var Test = (function (exports, lodash) {
  'use strict'; // Come with strict mode to avoid some weird compatibility issues

  Const unusedVar = 'May the 4th' ** /

  var answer = 42; // A single reference module in the business is directly erased

  const printAnswer = () = > {
    console.log(`the answer is ${answer}`);

    console.log(lodash.repeat('1', answer));
  };

  exports.printAnswer = printAnswer; // Hang the property to export on exports

  return exports;

})({}, $); // exports is the first entry and dependent jquery is the second

Copy the code

IIFE is an early product of front-end modularization. Its core ideas are:

  1. Build an anonymous function
  2. Execute the anonymous function immediately, with external dependencies passed in as input arguments
  3. Returns the output of this module

1.2 How to Run it

IIFE is easy to run, if it has no other dependencies, just import the file and fetch the corresponding variable on the window. Such as:

  <script src="http://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
  <script> 
    // jquery is a typical self-executing function. When you introduce it, it will hang on the window.$
    window. $// Get jquery
  </script>

Copy the code

However, if you rely on other modules like in this demo, you need to make sure that the following two things work:

  1. The package on which this package depends has been loaded before this package.
  2. Pre-dependent packages, andIIFEVariable names that only take input arguments are consistent.

Take the IIFE construction results of this demo as an example:

  1. It’s pre-dependentlodash, so it needs to be done before it loadslodashThe load.
  2. thisIIFEThe second input parameter to islodashAs a precondition we need to makewindow.lodashPoint tolodash.

Therefore, at runtime, the code looks like this:

<head>
  <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
  <script>window.lodash = window. _</script>  
  <script src="./bundle.js"></script>
</head>
<body>
  <script>
    window.Test.printAnswer();
  </script>
</body>
Copy the code

1.3 the advantages and disadvantages

  • Advantages:
    1. Closures create a “private” namespace that prevents global effects and prevents private variables from being modified externally.
    2. Easy to understand
    3. The effect on code size is small
  • Disadvantages:
    1. Output variables may affect global variables; Depend on global variables when importing dependent packages.
    2. It needs to be maintained by usersscriptThe loading sequence of labels.

I won’t go into the advantages, but I’ll explain the disadvantages in detail.

Disadvantage 1: Output variables may affect global variables; Depend on global variables when importing dependent packages.

Output variables may affect global variables; It’s easy to understand, for example: window.test is already affected. This obvious side effect is actually a hidden danger in the program.

Importing dependency packages depends on global variables. We added a line of code to make window.lodash point to LoDash to keep the demo running, but it was too fragile.

<! -- Without this line, demo will not run properly -->
<script>window.lodash = window. _</script>
Copy the code

You see, IIFE’s implementation is harsh on the environment unless it doesn’t rely on external packages at all. (Jquery: I am!)

Despite its many shortcomings, IIFE has greatly improved the web development process in the era of Jquery, because it does solve many of the problems of JS itself.

So? Are there better front-end modularity solutions to follow?

Of course, read on.

Second, the CommonJS

2.1 Analysis of packaging results

First take a look atCommonJsPacking results:

To simplify, it looks like this:

'use strict';

var lodash = require('lodash');

var answer = 42;

const printAnswer = () = > {
  / / print
  console.log(`the answer is ${answer}`);
  // Test lodash's ability to print 42 ones
  console.log(lodash.repeat('1', answer));
};

exports.printAnswer = printAnswer;

Copy the code

The above format is the CommonJS specification.

// CommonJS introduces modules through a global require method
var lodash = require('lodash');
// CommonJS implements method output in modules
module.exports.printAnswer = printAnswer;
// This is also equivalent to:
exports.printAnswer = printAnswer;
// exports is the same as module.exports
Copy the code

The CommonJS specification was first proposed in October 2009 to address node.js’s lack of modularity.

Note this keyword: node.js.

Yes, CommonJS is not a specification that runs in a browser environment, it runs in node.js.

2.2 How to Run it

So, I wrote a run.js script. As follows:

// run.js
const Test = require('./bundle-by-lodash')
Test.printAnswer()
Copy the code

Then, execute the following command:

# execute script
node ./out/cjs/run.js 
# output 1:
> the answer is 42
# output 2:
> 111111111111111111111111111111111111111111
Copy the code

As you can see, the Node.js environment naturally supports CommonJS.

2.3 the advantages and disadvantages

  • advantages
  1. Perfect modular solution, perfect solutionIIFEAll kinds of disadvantages.
  • disadvantages
  1. The browser environment is not supported, as this introduction of synchronization can cause the browser to feign death.

Therefore, the front-end industry urgently needs a perfect modular solution that can run perfectly in the browser environment.

AMD and Requirejs!

AMD, YES!

In 2011, AMDJS-API was formally proposed in the industry.

3.1 Analysis of packaging results

Packaging results for AMD format are as follows:As you can see, the core is a global methoddefine

The define method has three inputs:

  • "Test", module name
  • [exports.lodash]Represents the output and external dependencies of the module, respectively
  • In aexportslodashAs an input method, represents the actual contents of the module.

Compared to IIFE and CommonJs, AMD’s writing is definitely complex and awkward.

However, it does solve the problems faced by IIFE and CommonJS, providing a complete solution to the “perfect JS module method in the browser”.

In particular, the IMPLEMENTATION of the AMD standard: Requirejs.

The AMD implemented by Requirejs not only solves CommonJS ‘discomfort in the browser, but also realizes the ability of not causing false death by loading modules asynchronously. It makes up for all kinds of defects of IIFE.

Requirejs is typically used in four steps:

  1. Import in the browserrequire.js
  2. throughrequirejs.configMethod defines global dependencies
  3. throughrequirejs.defineRegistration module
  4. throughrequirejs()Module import is complete.

3.2 How do I Run it?

In index.html in the out/ AMD package directory, arrange the code as follows:

<head>
  <! -- 1. Introduce require.js -->
  <script src="./require.js"></script>
  <! -- define global dependencies -->
  <script>
    window.requirejs.config({
      paths: {
        "lodash": "https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min"}});</script>
  <! -- 3. Define module -->
  <script src="./bundle.js"></script>
</head>
<body>
  <script>
    // 4. Overhead module
    window.requirejs(
      ['Test'].function   (test) {
        test.printAnswer()
      }
    );
  </script>
</body>
Copy the code

When we open the browser, we can normally see 42 and 42 ones printed out in the console.

3.3 the advantages and disadvantages

  • advantages
  1. To solve theCommonJSThe disadvantages of the
  2. To solve theIIFEThe disadvantages of the
  3. A complete set of browsersjsFile modularization scheme
  • disadvantages
  1. The code is poorly organized and readable

But thanks to all the packaging tools we have, it doesn’t matter how poorly readable the code is in the browser.

We now have CommonJs for Node.js and AMD for browsers.

What do I do if I want my code to be recognized by both the browser and NodeJS?

4. Great integration of UMD

It didn’t do anything groundbreaking, but it did it all.

4.1 Packaging Analysis

The readability of code built in UMD is further reduced.

I’m sure any sane person would be shocked to see the following code:

Yes, a whole chunk of code, just dealing with compatibility issues, deciding whether to use AMD or CommonJS at the moment.

So the UMD code and implementation doesn’t go into too much analysis here, all it does is make the same code compatible with AMD and CommonJS.

4.2 How Do I Run it?

  • On the browser side, it works the same wayamdIt’s exactly the same. It’s totally referable3.2Section of thedemo.
  • On the Node.js side, it andCommonJSIs exactly the same, so I won’t repeat it here.

4.3 the advantages and disadvantages

  • advantages
    1. Smoothed out a bag inAMDCommonJSDifferences in the
  • disadvantages
    1. Produces a lot of code for compatibility that is hard to understand. (Understand difficulty and package size)

CommonJS, AMD and UMD have all given their answers to the industry, thanks to the efforts of the community.

But clearly, they are choices of choice.

Browsers should have their own loading standards.

The ES6 draft does not have a “loader specification”, although it describes how modules should be loaded.

Fifth, SystemJs

Therefore, WHATWG (Web Hypertext Application Technology Working Group), namely Web Hypertext Application Technology Working Group, proposed a more far-sighted specification: WHATWG/Loader.

JavaScript Loader Standard (JavaScript Loader Standard)

This specification describes the behavior of loading a JavaScript module from a JavaScript hosting environment. It also provides apis for intercepting the module loading process and customizing the loading behavior.

Based on this specification, SystemJS was born.

SystemJS is currently the best practitioner of the WHATWG/Loader specification.

It can be seen that the packaging results of system are actually similar to AMD, providing a global object system, and providing a registration method and a unified writing method.

Simply from the packaging results, in fact, do not see it compared to AMD + require.js has any advantage, is there only a difference in writing?

It doesn’t stop there!

SystemJS’s system.import (‘module/name’) approach allows you to load modules more lazily than require.js, which means you don’t have to load a bunch of bundles each time, and the user only needs to spend bandwidth for the pages he can see.

Also, because SystemJS is oriented towards the WHATWG/Loader specification practices, it is a future-oriented approach to module dependency.

Sorry, I did not understand the demo, so I will not mislead you. Hope to have a clear boss can help improve the demo.

Sixth, the ESM

ECMAScript Modules, also known as ESM, is the official standard format for Javascript modularization.

6.1 Packaging Analysis

Until the ESM came along, JavaScript didn’t really have a module architecture.

The specification is to specify the output code explicitly through the export command, followed by the import command.

// Import the module
import { foo } from 'bar';
// Export commands
export { zap };
Copy the code

This is the way we’re most familiar with daily development.

As a result,esmFormat out of the package, readability is really great:

It’s no different than reading the business code we normally write. Rollup is still tree-shaking

6.2 How Do I Run it?

Congratulations, you are the front-end development of the era.

Some modern browsers have started to implement

But running the throw requires a few preliminary steps.

  1. Start a local static service in the js-modules directory
Create a local static service in js-modules
cd js-modules && http-server
Copy the code
  1. theesm/bundle.jsChange the first line of the file to:
import repeat from '.. /.. /node_modules/lodash-es/repeat.js';
// Since the default loDash is not an ESM format for output, we need to do some special processing for demo purposes
Copy the code
  1. Open the browser page (assuming the port is 8080), are open: http://127.0.0.1:8080/out/esm/index.html

That way, the code runs successfully, and the console can successfully print 42 and 42 ones.

Summary: Which scenarios are suitable for use?

  • IIFE:Suitable for some scenarios to use as an SDK, especially if you need to attach yourself towindowOn the scene.
  • CommonJS: a library used only by Node.js.
  • AMD: scenarios that only need to be used on the browser side.
  • UMD: Scenarios that can be used either in the browser or in Node.js.
  • SystemJs:Similar to UMD. One of the more famous at presentAngularThat’s what we use.
  • ESM:1. Scenarios that will also be referenced and re-compiled (component libraries, etc.); 2. The browser debugging scenario is as followsvite.jsThe development of. 3. Scenarios that are very flexible with browser compatibility.

conclusion

I’m Spring brother. I love vue.js, ElementUI, and Element Plus. My goal is to share the most practical and useful knowledge points with you. I hope you can leave work early, finish your work quickly, and feel calm 🐟.

You can follow me on the Nuggets, and you can also find me on the public account: Touch the fish in front. I hope you all have fun.