To understand what Webpack solves, start by understanding the problem it solves.

Answer me first: Why are modules important?

A: Because modules make it easier for us to use other people’s code and load whatever functionality we want. However, there is a premise to do this, that is, everyone must write modules in the same way, otherwise you have your way of writing, I have my way of writing, is not a mess!

1. Modularity evolution process

Phase 1: File partitioning

Each function and its data state are stored in a separate JS file, and a file is agreed to represent a module. Using script tags to introduce these modules in HTML, you can directly use the members of these modules globally. Disadvantages:

  • Modules work directly globally, and a large number of module members pollute the global scope
  • There is no private space, and all module members can be accessed or modified outside the module
  • Once the number of modules increases, naming conflicts tend to occur
  • Unable to manage dependencies between modules
  • It is also difficult to identify which module each member belongs to during maintenance

Namespace mode

Specify that only one global object can be exposed per module, such as window.modulea = {… }, all module members must be mounted to this object. Only the naming conflicts are resolved, but other problems remain.

Stage 2: IIFE (Execute function now)

; (function(){
	method1 = function(){... }window.moduleA = {
		m1: method1
	}
})()
Copy the code

Executing functions immediately enables each module to have its own private space, exposing external members to be mounted on global objects, eliminating global scope contamination and naming conflicts. Executing functions immediately introduced the concept of private members, which can only be accessed through closures within a module.

Phase 3: IIFE dependency parameters

; (function($){ // The dependency of the module is clearly indicated by the parameter, and the dependency between modules is known without looking at the internal code of the module
	method1 = function(){... }window.moduleA = {
		m1: method1
	}
})(jQuery)
Copy the code

The above method solves the problem of module organization, but does not solve the problem of module loading. Js files are imported via the script tag and are not controlled by the code. If a script still imports a deleted JS file, or if a script does not import your JS, it may cause unnecessary problems. The ideal approach is to have a JS entry file in the page, and the rest of the modules used are controlled by code and loaded on demand.

Second, the emergence of modular specifications

Two requirements:

  • A unified modular standard specification
  • A base library that automatically loads modules

1, CommonJS specification

Node.js is a module specification that is followed in Node.js. A file is a module, each module has its own scope, exports its members through module.exports, loads modules with require functions, loads modules at startup, uses modules during code execution, This synchronous mode has no problem on the server side, because all modules are stored in the local hard disk, can be synchronized to complete, wait time is the hard disk read time, but in the browser side using this mode will cause a large number of synchronous loading requests, resulting in slow page loading, hence the AMD specification.

2, AMD(asynchronous module definition) specification

The require.js library, in addition to implementing the AMD modularity specification, is a very powerful module loader in its own right. Preexecute, when the current module is defined, the dependent module is also executed.

// The AMD specification defines a module (can also be used to import a module)
// module1 The module name of the current module, ['jquery', './module2.js'] defines two dependent paths for the current module, and the third argument is a function that creates a private space for the current module as if it were executed immediately
// return exposes some members outward
define('module1'['jquery'.'./module2.js'].function($, module2){
	return {
		start: function() {$('body').animate({ margin: '200px'}); module2(); }}})Copy the code
// The AMD specification loads a module
// Automatically creates a script tag that requests and executes the corresponding module's code
require(['./modules/module1.js'].function(module1) {
	module1.start();
})
Copy the code

If the module division of the project is relatively fine, many JS files will be loaded in the same page, resulting in low application operation efficiency.

CMD(General module definition) specification

Ali’s Yubo came up with this. He wrote a library called seaJS, which is lazy and only executes MODULE A when it needs to be used.

// All modules are defined with define
define(function (require.exports.module){
	var$=require('jquery');
	Exports or module.exports exposes members
	module.exports = function({$('body').append('<p>module2</p>');
	})});
Copy the code

The best practices of the front-end modular specification are basically unified:

  • inNode.jsIn the environment, followCommonJSSpecification to organize modules
  • In the browser environment, followES Modulesspecification

Third, the emergence of module packaging tools

Modular development will divide a lot of module files. The front-end application runs in the browser, and all files need to be requested back from the server. Therefore, the browser will inevitably send network requests frequently, affecting the efficiency of the application. HTML CSS in the front-end project these resource files also need to be modularized.

Capabilities required by the tool:

  • theES6The code is compiled to be parsed by the browserES5code
  • Put all kinds of documentsHTML CSS JSImages and so on are packaged separately so that network requests are not sent frequently

Modularity is only required during the development phase to better organize our code

Webpack solves the problem of efficiently managing and maintaining every resource in a front-end project