This is the first time I participate in 2022 more challenge the third day, view the full details of: 2022 for the first time, the more challenging | create learning continues to grow, indiana stage mode and win prizes

With the rapid development of Internet technology, page interaction has become increasingly complex, resulting in more and more JavaScript code being written and more and more JS files being split. Prior to ES6, JavaScript did not support a modular system, which was a huge obstacle to the development of complex and large projects. Front-end modularization is proposed to solve the naming conflict, global variable pollution, dependency order and performance problems among JS files without modularization. Think of modularity as a Lego toy. Each module has a specific function, and lego can be made by using the modules according to certain rules. Using modularity solves naming conflicts, provides reusability, eliminates the need to pay attention to the order in which JS files are introduced, and so on.

History of front-end modularization

CommonJS, AMD and CMD

Prior to ES6, there were two main modularity specifications. One is CommonJS on the server side and the other is AMD on the browser side.

CommonJS

NodeJS, launched in 2009, uses the CommonJS specification. Its features are:

  • Each file is a module, and each module has its own independent scope, variables, methods, etc., which are not visible to other modules.
  • All modules are loaded synchronously. The first time the cache results are loaded, and the cache results are directly read after loading. For the module to run again, the cache must be cleared.
  • moduleThe variable represents the current module, which is an object. throughmodule.exportsExpose the contents of the module.
  • throughrequireImports the specified module.

An 🌰 :

// num1.js
var a = 1;
module.exports = {
  num1:a;
}

// num2.js
module.exports.num2 = 2;

// addNum.js
var addNum1 = require('./num1.js');
var addNum2 = require('./num2.js');

console.log(addNum1, addNum2);//{ num1: 1 } { num2: 2 }
console.log(addNum1.num1+addNum2.num2);/ / 3
Copy the code

Exports = module. Exports; exports = module. Exports = module. Exports. A =… Exports = exports. Exports of module. Exports of module. Well, anyway, if you can’t figure it out, drop the grammar.

CommonJS modular thought has given us great inspiration to think about the front-end modular problem, but also promoted the development of front-end modular. And most importantly, the rules are simple, concise and easy to use. However, the limitation of CommonJS is that it can only be used on Node-based servers because synchronous loading of dependencies on the browser side is a performance penalty. So AMD/CMD followed to address the browser side of the modular specification issues.

AMD

AMD Asynchronous Module Definition AMD Asynchronous Module Definition AMD Asynchronous Module Definition AMD Asynchronous Module Definition AMD Asynchronous Module Definition All statements that depend on this module are defined in a callback function that will not run until all dependencies have been loaded (pre-dependencies). Is also a module specification.

It is the RequireJS modularization tool that has driven the development of the AMD modularization specification. The RequireJS configuration is quite complex, so I won’t give you an example here. After all, people won’t read it

CMD

The CMD specification is based on the CommonJS and AMD specifications. CMD is a modular specification implemented on the browser side through sea-.js. Its features are:

  • The dependencies are resolved through the configured entry file, and the code is inserted sequentially based on the resolved dependencies to<script>In the label.
  • Advocate that a file is a module
  • Advocate dependence on proximity, that is, need to use a module to introduce. (AMD advocates dependency prefixes, which declare dependent modules when defining modules.)
// The main syntax of sea-js is define
// Because of the above recommendation, a file is a module, so can not define the id alone, depending on the nearest, so can not write depsdefine(id? , deps? , factory);Copy the code

An 🌰 :

// add.js
define(function (require) {
	require('./num1');  
 	require('./num2');
  console.log('add');
});
console.log('end-add');

// num1.js
define(function (require.exports.module) {
  console.log('num1');
});
console.log('end1');

// num2.js
define(function (require) {
  console.log('num2');
});
console.log('end2');

<body>
  <script src="/sea.js"></script>
	<script>
    // the use method loads the module
		seajs.use(['./add.js'].function () {
    	console.log('Callback under root');
  	});
	</script>
</body>
/** sea-.js /** sea-.js /** sea-.js /** sea-.js /** sea-.js 2. Dynamic script tag download dependency, output: end-add end1 end2; Add depends on num1 and num2. Num1 num2 5 is displayed in sequence. After all dependencies are loaded, execute the factory output at the root: callback */ at the root
Copy the code

Because CMD integrates CommonJS and AMD characteristics, in general, Sea-js is a highly compatible modular specification implementation, which contains the characteristics of two module specifications:

  • It can rely on the front, as AMD does, or it can rely on proximity.
  • Caches all dependencies just like CommonJS.

If you want to use it together, there is a new specification called UMD to unify the two specifications. In short, it was an endless brawl.

ESM Module

ES6 finally has an official set of modularity specifications, after a period of chaos in the previous community over unofficial module specifications. ES6 implements module functions directly on the language standard level and is very simple to use, so it can directly unify the browser and server side as a solution to pass. This means that an official set of ES6 modularity specifications can eliminate AMD/CMD and do not require UMD.

// num1.js
var a = 1;
export {
  a as num1
};

// num2.js
export const num2 = 2

// add.js
import { num1 } from '/test111'
import { num2 } from './test'
console.log(num1 + num2); / / 3

// To apply the ES6 module to the browser also requires a small change to the script tag type="module"
<script type="module" src="add.js"></script>
Copy the code

The import and export of ES6 modules are mainly the keywords import and export. Export exports interfaces, so import imports interfaces (read-only attributes) and cannot be changed.

Export default = export default

/ / export export
export function a () {}// We must know the name of a
import { a } from '... '


// export default Exports the default module
export default function () {}// Introduce custom names
import AAA from '... '

Copy the code

Export default Since the default output is exported, there can only be one default in a module, so most of the time we use import _ from ‘lodash’ to import easily. The ES6 module is designed to be as static as possible, so that the module dependencies, as well as the input and output variables, can be determined at compile time. Both CommonJS and AMD modules can only determine these things at runtime. See Ruan Yifeng ECMScript 6 for more ES6 Modules.

Vite is the next generation of Web tools! ?

Much of the history of front-end modularization has been devoted to this discussion. Of course, it’s important to explain what Vite is and how it differs from Webpack before discussing it.

Have to say Vite with Webpack

A lot of people compare Vite to Webpack, but rollup is a better comparison. Strictly speaking, Vite is not a packaging tool, but rather a dev Server based on the Rollup packaging tool. Because the amount of JavaScript code required to build large projects is very high, the current JavaScript development tools take a long time to start the server, and the most inefficient development is that it takes at least a few seconds to update the file in the browser, even with hot update (HMR). The main reasons for this are (using webpack as an example) :

  1. Starting the server slowly

How WebPack works and how Vite works are shown below.

For WebPack, the bottom line is pack first and then start the server. The packaging goes through a process of identifying module dependencies layer by layer (identifying various modular specifications AMD/CommonJS/ES6, etc.), building an AST abstract syntax tree, and converting it into browser-aware code packaging. This results in a longer startup time.

Vite initially divides application modules into dependency and source modules. Dependencies Are pre-built with the ESBuild tool, which also converts the ESM dependencies of many internal modules into a single module to improve subsequent page loading performance. According to the EsBuild website, it is written in the Go language, which is hundreds of times faster than a typical JavaScript wrapper’s build dependencies. The source code uses the native ESM approach, using the browser’s network request to take over all modules. Specifically, when declaring a script tag of type module, such as:

 <script type="module" src="src/app.js"></script>
Copy the code

The browser will issue a GET request to the server, and if the app.js file continues to have the import module inside it, it will continue to request the module inside… Vite helps with this by hijacking the requests of the browser, doing the corresponding processing on the back end and simply decomposing and integrating the files used in the project and then returning them to the browser. Vite doesn’t package or compile the files and starts the server directly, so it’s much faster than WebPack. However, this relies heavily on the MODULarity mechanism of ESM, and here is how ESM modularity is supported by current browsers.

With the exception of Internet Explorer, Microsoft announced the abandonment of Internet Explorer last year, so Vue3 also announced the abandonment of Internet Explorer. Now it seems that Vite is not compatible with Internet Explorer either.

  1. Update slow

In terms of HMR, webPack recompiles all the related dependency modules of the dependency tree generated by the first cold boot after each file change, resulting in a long HMR refresh time. Vite doesn’t need to be packaged at startup, which means there’s no need to analyze module dependencies, no need to compile, and when the browser requests a module, it can compile its contents as needed. This dynamic compilation on demand greatly reduces the compilation time, and the more complex the project and the more modules, the more obvious the advantages of Vite.

Some packages import their ES module builds to each other as many separate files. For example, Lodash-es has over 600 built-in modules! When we executed import {debounce} from ‘lodash-es’, the browser made over 600 HTTP requests at the same time! Although the server has no problem handling these requests, the large number of requests can cause network congestion on the browser side, causing pages to load very slowly. By pre-building LoDash-es as a module, we only need one HTTP request!

Some people on the web have summarized the following points to illustrate vite’s advantages over other JavaScript build tools:

  • Based on the browser’s native ES imports, there are faster cold starts and hot updates, regardless of the number of modules
  • There is no packaging process, the source code is transferred directly to the browser, using nativescript moduleThe syntax is introduced, and the development server intercepts the request and transforms the code that needs to be transformed
  • True on-demand compilation is implemented
  • The production environment provides the Vite build script for packaging, which is based on rollup

The language usage inside the Rollup packaging tool is based on the ESM module specification, and the writing of webPack is based on the CommonJS specification. I suspect that Vite chose rollup not only because rollup is small and beautiful, but also because it is consistent with the ESM module specification so that developers can be more consistent in their development.

Let’s discuss the title

My own opinion: I think the next generation of development tools will definitely benefit the ESM module idea, if not Vite.

The development of front-end tools was born out of a current dilemma:

  1. At the beginning, we used to write code by manipulating DOM. There was no idea of modularity at that time, and solving the problems caused by multiple interdependent JS files was the most urgent thing at the moment, so the birth of JQuery swept the front end world. JQuery attempts to solve the problem of JS dependency by encapsulating the DOM manipulation and enclosing the scope by providing closures. At this point development is in the “I’m getting lazy, but it’s getting better” state.
  2. After the idea of modularization is put forward, gradually we do not need to care about JS file mutual influence and with the development of the Internet interaction has become more and more complex, this time the problem is transferred to how to develop and design decouple. Angular and React, along with Vue that combines the advantages of the two, brought the MVVM model to the front end, and the “I’m getting lazy, but it’s getting better” state of development made JQuery obsolete.
  3. When progressive JavaScript frameworks are used, problems arise, such as.vue file browsers that don’t recognize them, and JavaScript building tools such as Webpack are developed to accommodate progressive frameworks. With Webpack and various plugins in the community, development is much more efficient than before, and development is in the “I’m getting lazy, but it’s getting better” state again, so gulp and other packaging methods are obsolete. But at this point, the modularity process is still in the midst of chaos.
  4. So now with the proposed ESM modular specification, with the advance of front-end development, JS module files split out can reach thousands of times. If there is no better solution, we will endure it, but if there is a better solution, we can waitdev server, HMR refresh in seconds, lower learning cost and so on. At this point, then, the mark of human progress:“I’m getting lazy, but I’m getting better.”It’s going to work.

So, experience let you small right three days ten more Vite’s silky really can’t go back, this is the magic of Vite. Despite its current problems, Vite is not meant to be the next generation of Web development tools. Please refer to the Vite official website for details.