1. What is Webpack

Webpack is a static module wrapper for modern Javascript applications. It means that webpack can only handle Javascript without special configuration. Packaging means that multiple JS files can be combined into a single file without the need to manually sort out their dependencies.

Why pack? Because the front-end project in the logic more, more files, increased complexity (such as a project depends on multiple modules), so put forward a variety of modular standards, Webpack is such an excellent modular solution. Webpack is not only powerful, but also flexible (each feature is pluggable).

What does Webpack do besides pack?

  • The translation! joinloader, translate the code into code that the browser can understand.
  • Let’s do something else,Capability extension classIn webpackpluginIn the water.

Loaders and plugins are explained below.

2. Key people in the Webpack

  • loader: refers to a file loader that executes a fileCompile and translate functions, for example, es6 to ES5babel-loader, the introduction of CSS files in the file is requiredcss-loader.style-loader.
  • plugin: Used to enhance a projectwebpackThe mechanism is to emphasize the ability of an event listener to listen for events in a project and change the output of some file package. Like using a name calledUglifyJSPluginPlug-ins to compress JS files, thereby reducingjsFile size to speed up load.

Loader is responsible for file conversion, Plugin is responsible for function extension. Loader and Plugin, as two important parts of Webpack, assume two different responsibilities.

3. Front-end modularization

What is a module? For example, if a company needs to run properly, it has Marketing Department, technology department, human resource department and so on. Each department is equivalent to a module. In the front-end project, there are modules dedicated to network request, error handling and rendering.

Before we get to modularity, let’s look at the concept of scope.

The traditional approach is to introduce multiple JS scripts, which are all in the global scope, so it is easy to cause global scope variable conflicts (such as variable conflicts with the same name), and some unpredictable things happen. Such as:

/* modulea.js */ var a=10; /* moduleb.js */ var a=11; * / / * index in HTML<body>
    <script src="./moduleA.js"></script>
    <script src="./moduleB.js"></script>
    <script src="./moduleC.js"></script>
</body>
Copy the code

Can the value of A be determined after the above conflict occurs? – can’t!

Then someone came up with the idea of using an object wrapped around each JS script to form a local scope.

// Define a local scope within a module, for example, moduleA
    var Susan = {
    	name: "susan".sex: "female".tell: function(){
        	console.log("im susan")}}Copy the code

However, there are serious problems, that is, we can change the value of the object, cannot guarantee the internal security of the module attributes, for example, the user name password and other data situation is very serious.

This led to improvements in the form of immediate functions and closures.

// Define the closure scope (module scope) within a module, for example moduleA
    var SusanModule = (function(){
    	var name = "susan"
        var sex = "female"
        functioon tell(){// So you can't change the data in it
        	console.log("I'm ".this.name)
        }
    })()
Copy the code

Let’s rewrite this by writing window for the immediate function.

// Define the closure scope (module scope) within a module, for example moduleA
    (function(window){
    	var name = "susan"
        var sex = "female"
        functioon tell(){
        	console.log("I'm ".this.name)
        }
        window.susanModule = {tell}
    })(window)// window is passed as an argument
//////////////////////
/ / test
window.susanModule.tell(); //im susan
Copy the code

This is probably an early form of modularity.

Current modular solutions include:

  • AMD(Asynchronous Module Definition)
// The general form is as follows
/ / define
define("mymodule"["dep1"."dep2"].function(d1, d2) {});/ / load
require(["module".".. /file"].function(module, file) {});Copy the code
  • CommonJs: node.js only. The core idea of this solution is to allow modules to synchronously load dependent modules through the require solution, exposing the required interface through exports or module.exports.
// referenced by the require function
const math = require("./math");

// Exports through exports
exports.getSum = function(a,b){
    return a + b;
}
Copy the code
  • ES6 Module: The biggest feature of this scheme is statically. The advantage of statically is that Module dependencies and input and output variables can be determined during compilation. Both CommonJs and AMD mentioned above can only determine these things at run time.
// referenced by the import function
import math from "./math";

// Export it by export
export function sum(a, b){
    return a + b;
}
Copy the code

ES6 modularity vs. CommonJs modularity

  • The CommonJS module prints a copy of the value, the ES6 module prints a reference to the value.

    Note: The CommonJS module outputs a copy of the value, meaning that once a value is output, changes within the module do not affect that value

    ES6 modules are referenced dynamically and do not cache values. Variables in modules are bound to their modules.

  • The CommonJS module is run time loaded, and the ES6 module is compile time output interface.

    Reason: CommonJS loads an object (the module.exports property) that is generated only after the script runs. An ES6 module is not an object, and its external interface is a static definition that is generated during the code static parsing phase.

  • The CommonJS module require() is a synchronously loaded module, while the ES6 module import command is asynchronously loaded, with a separate module-dependent parsing phase.

Front-end modularization mainly solves two problems: “namespace conflict” and “file dependency management”.

What does it have to do with introducing Webpack? In Webpack, everything is a module. In modular development, we usually use ES Module or CommonJS specification to export or introduce dependent modules. When webpack is compiled, it will be replaced with its own __webpack_require__ to realize the introduction and export of modules, so as to realize the Module caching mechanism. And smoothing out some of the differences between different module specifications.

4. The core idea of Webpack packaging

  • Initialization: start build, read and merge configuration parameters, load Plugin, instantiate Compiler
  • compileFrom:Entry Entry fileStarting, the corresponding Loader is successively called for each Module to translate the content of the file, and then the Module that the Module depends on is found and compiled recursively
  • Output: Combine compiled modules into chunks, convert chunks into files, and output them to the file system

5. A simple webPack configuration example

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry: path.resolve(__dirname, '.. /src/index.js'), // specify the entry file from which the program is compiled, the current __dirname directory,.. / indicates the directory at the upper level,./ directory at the same level
    output: {
        path: path.resolve(__dirname, '.. /dist'), // Output path
        filename: 'app/[name]_[hash:8].js'  // Pack the file
    },
    module: {
        rules: [{test: /\.(js|jsx)$/,
                use: {
                    loader: 'babel-loader'.options: {
                        presets: ['es2015'.'react'],}},exclude: /node_modules/}},plugins: [// Plugins under plugin
     newHtmlWebpackPlugin({template: path.resolve(__dirname, '.. /src/index.template.html'),inject: true})]Copy the code

Loader:

  • Babel-loader: indicates the Babel loader

  • Babel – preset – es2015: support es2015

  • Babel-preset -react: JSX is converted to JS

Loader supports multiple configurations in the form of arrays. When Webpack converts the file type, it will call each loader in sequence and the content returned by the previous loader will be used as the input parameter of the next loader.

Under the plugin:

The htML-webapck-plugin has two main functions:

  • Dynamically add hash after each compile for external resources such as script and link introduced in HTML files to prevent the problem of referencing external files in the cache

  • Create HTML entry files can be generated, such as a single page can generate an HTML file entry, configure N HTML-webpack-plugin can generate N page entry

Webpack is based on the publish and subscribe mode. During its life cycle, webPack will broadcast many events. By listening to these events, the plugin can perform its own plug-in tasks at a specific stage, so as to achieve the desired functions.

Some common loaders and plugins can be seen here, and it is best to have a general understanding and memory of these.

6. Summary

A simple definition of Webpack is as follows: Webpack is used for module packaging, packaging files from different modules together, and ensuring that they are referenced correctly and executed in an orderly manner. And through its loader mechanism, WebPack can handle other types of files and convert them into valid modules for use by applications and to be added to dependency diagrams. And through the Plugin mechanism of Webpack, we can further achieve a series of extended functions such as on-demand loading, code compression and so on.

Reference article:

What does Webpack want to know when the interviewer asks him

A dozen more Webpack interview questions