preface

This paper is the second time for the author to carry out in-depth and practice of Webpack knowledge points, according to the results of understanding and practice are summarized;

The content of this article refers to the book “Simple To Understand Webpack”. Since this book is based on Webpack 3.4.0 and the practice of this paper is based on Webpack 4.28.2, many pits occurred due to module version problems have been summarized in chapter 6. Remember to avoid pits; Also confirmed that philosophy: paper come zhongjue shallow, must know this to practice…

Blog github address: github.com/fengshi123/… , a summary of all the author’s blogs, also welcome to follow and star ~

This article practices the Github address of demo

First, Webpack principle

1. Construction role

Build tools convert source code into executable JavaScript, CSS, AND HTML code, including the following:

  • Code conversion: compile TypeScript to JavaScript, SCSS to CSS, etc.

  • File optimization: compress JavaScript, CSS, HTML code, compress and merge images, etc.

  • Code segmentation: extract the common code of multiple pages, extract the code that does not need to be executed on the first screen, and let it load asynchronously;

  • Module merge: there will be many modules and files in a modular project. It is necessary to merge modules into one file by building functions.

  • Automatic refresh: monitor local source code changes, automatically rebuild, refresh the browser;

  • Code verification: verify code compliance and pass unit tests before it is submitted to the repository;

  • Automatic release: after updating the code, the code will be automatically built and transmitted to the release system.

2. Core concepts

Webpack has the following core concepts:

  • Entry: Entry, the first step in the Webpack implementation of the build will start with Entry, which can be abstracted into input;

  • Module: configures rules for handling modules. In Webpack everything is a module, a module for a file; Webpack recursively finds all dependent modules starting from the configured Entry;

  • Loader: module converter, used to convert the original content of a module into new content as required;

  • Resolve: Configures the rule for finding modules.

  • Plugin: Extension plug-in, in the Webpack construction process at a specific time to broadcast the corresponding events, plug-ins can monitor the occurrence of these things, in a specific time to do the corresponding things;

  • Output: Output the result after Webpack has gone through a series of processes and produced the final desired code;

  • Chunk: a Chunk is a code block. A Chunk is composed of multiple modules for code merging and splitting.

3. Process Overview

(1) Initialization parameters: read and merge parameters from configuration files and Shell statements to get the final parameters;

(2) Start compiling: initialize the Compiler object using the parameters obtained in the previous step, load all the configured plug-ins, and start compiling by executing the run method of the object;

(3) Determine entry: find out all entry files according to the entry in the configuration;

(4) Module compilation: Starting from the entry file, call all configured Loader to translate the module, find out the module that the module depends on, and then recurse this step until all the entry dependent files have gone through this step;

(5) Complete module compilation: After using Loader to translate all modules in Step 4, obtain the final content of each module after translation and the dependency between them;

(6) Output resources: according to the dependency relationship between the entry and modules, it is assembled into chunks containing multiple modules one by one, and then each Chunk is converted into a separate file and added into the output list. This is the last chance to modify the output content;

(7) Output completion: After determining the output content, determine the output path and file name according to the configuration, and write the content of the file into the file system;

In the above process, Webpack will broadcast a specific event at a specific time point, the plug-in will execute a specific logic after listening to the event of interest, and the plug-in can call the API provided by Webpack to change the running result of Webpack;

Webpack configuration

1. Initialize the Webpack project

1. Create a Web project

Create a new directory, then go to the project root directory and execute NPM init to initialize the simplest modular development project; Finally generate package.json file;

$ npm init
Copy the code

2. Install Webpack into this project

(1) View the Webpack version

Run the following command to view the version number of Webpack

$ npm view webpack versions
Copy the code

(2) Install Webpack

You can choose the Webpack version listed in step (1), or you can install the latest stable version and the latest experience version. Related commands are shown below. I choose to install 4.28.2 (for no reason, I just want to install 4.x version).

// Install the specified version
npm i -D webpack@4.282.

// Install the latest stable version
npm i -D webpack

// Install the latest experience version
npm i -D webpack@beta
Copy the code

(3) Installation of Webpack scaffolding

Webpack scaffolding needs to be installed in order to execute the Webpack command from the command window, run the following command to install Webpack scaffolding;

$ npm i -D webpack-cli
Copy the code

3. Use Webpack

Use Webpack to build a project written in CommonJS modularity;

(1) Create the page entry file index.html


      
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Webpack</title>
</head>
<body>
<! Import Webpack output JavaScript file -->
<script src="./dist/bundle.js"></script>  
</body>
</html>
Copy the code

(2) Create the JS file to be used

Show the js file

// Manipulate the DOM element to display content on the web page
function show(content) {
  window.document.getElementById('app').innerText = 'Hello,' + content;
}

// Export the show function from the CommonJS specification
module.exports = show;
Copy the code

The main js file

// Import the show function via the CommonJS specification
const show = require('./show.js');
// Execute show
show('Webpack');
Copy the code

(3) Create the Webpack configuration file webpack.config.js

const path = require('path');

module.exports = {
  // JavaScript executes the entry file
  entry: './main.js'.output: {
    // Merge all dependent modules into a bundle.js file
    filename: 'bundle.js'.// Put the output files in the dist directory
    path: path.resolve(__dirname, './dist'),}};Copy the code

(4) Execute webpack command to build

Configure the compile command in the package.json file as follows:

  "scripts": {
    "build": "webpack --config webpack.config.js",},Copy the code

Run the following command to compile the Webpack of the project, and the compile directory dist will be generated in the root directory of the project.

$ npm run build
Copy the code

(5) Run index.html

After compiling successfully, open the index.html file in a browser and see “Hello Webpack” successfully displayed on the page.

2. Loader configuration

This section tries using the Loader by adding styles to the previous example;

(1) Create a new style file main.css

#app{
  text-align: center;
  color:'# 999';
}
Copy the code

(2) Add the main. CSS file to the entry file main.js, as shown below:

// Import CSS modules through the CommonJS specification
require('./main.css');

// Import the show function via the CommonJS specification
const show = require('./show.js');
// Execute show
show('Webpack');
Copy the code

(3) Loader configuration

Performing a Webpack build after the above changes will cause an error because Webpack does not natively support parsing CSS files. To support non-javascript files, you need to use the Loader mechanism of Webpack;

(3.1) Run the following command to install style-loader and CSS-loader:

  • Css-loader is used to read CSS files.
  • Style-loader injects CSS content into JavaScript;
$ npm i -D style-loader css-loader
Copy the code

(3.2) Perform the following configuration

module: {rules:[
  {
	// Use the re to match the CSS file to be converted with the loader
	test:/\.css$/.use: ['style-loader'.'css-loader']]}}Copy the code

(4) View the results

After compiling, refresh the index.html to see that the style loader is in effect.

3. Plugin configuration

(1) Install the extract-text-webpack-plugin

$ npm i -D extract-text-webpack-plugin@next
Copy the code

(2) Plugin file configuration is as follows

  module: {rules:[
      {
        // Use the re to match the CSS file to be converted with the loader
        test:/\.css$/.use:ExtractTextPlugin.extract({
          use: ['css-loader']}),}]}plugins: [new ExtractTextPlugin({
       // The name of the.css file extracted from the.js file
       filename:`[name]_[hash:8].css`}),]Copy the code

(3) View the results

After the above configuration, run the Webapack command and find that the corresponding CSS file is generated in the dist directory. Existing pit points:

  • We need to manually import the generated CSS file into index.html;
  • After a CSS file is modified, a new CSS file is generated and the original CSS file is not deleted.

4. Use DevServer

(1) Run the following command to install webpack-dev-server

$ npm i -D  webpack-dev-server
Copy the code

Configure the startup command in package.json

  "scripts": {
    "build": "webpack --config webpack.config.js"."dev": "webpack-dev-server",},Copy the code

After running the command, you can start the HTTP service

$ npm run dev
Copy the code

The startup results are shown below, and we can access our index.html demo at http://localhost:8080/

(2) Real-time preview

We added the parameter –watch after the running command to realize the real-time preview, and the configuration is as follows:

  "scripts": {
    "dev": "webpack-dev-server --watch"
  },
Copy the code

Then we modify the parameters passed to main.js and find that it does not preview in real time and does not report an error!! why?

Hit the pit:

In index.html you need to change the js path to:

<script src="bundle.js"></script>  
Copy the code

It can’t be the previous one (because this is compiled and not put in memory via devServer generation)

<script src="./dist/bundle.js"></script> 
Copy the code

(3) Module hot replacement

You can configure — HOT for module hot replacement.

Webpack optimization

The practice of optimization has been carried out before, and it is no longer mentioned here. Interested children can check another article written by the author “Webpack optimization practice of Vue project, Construction efficiency increased by 50%”.

4. Write Loader

1. Summary of Loader key points

(1) Loader is a module converter, used to convert the original content of the module into new content as required;

(2) Loader’s responsibility is single, only one transformation needs to be completed, and the principle of single responsibility should be observed;

(3) Webpack provides a series of apis for Loader to call, such as:

  • Loader-utils.getoptions (this) gets the options passed in by the user,
  • This.callback () returns a custom result,
  • This.async () supports asynchronous operations;
  • This. context The directory where the current file resides;
  • This. resource The full request path to the file currently being processed;
  • Other, etc.

2. Write loader source code

Write a loader source code, its function is to convert /hello/gi into Hello, of course, this loader actually has no practical significance, pure is to write loader and write loader; Of course, if your actual business needs to write loader requirements, you need to reflect on the rationality of this business, because the huge community, generally reasonable needs can find corresponding Loader.

(1) Source code writing

Under the original project, create a directory custom-loader as the name of our loader, execute NPM init command, create a new modular project, and then create a new index.js file, the relevant source code is as follows:

function convert(source){
  return source && source.replace(/hello/gi.'HELLO');
}

module.exports = function(content){
  return convert(content);
}
Copy the code

(2) Npm Link module registration

Normally, we install Loader from the Npm public repository, and release Loader to the Npm repository, and then install Loader to local use. However, we can use Npm link to link the source code of a local module under development to the node_modules directory of the project, so that the project can directly use the local Npm module without publishing the module.

In the custom-loader directory, run the following command to register the local module globally:

$ npm link
Copy the code

The successful results are as follows:

Then run the following command in the project root directory to link the local Npm modules registered globally to the node_modules of the project:

$ npm link custom-loader
Copy the code

The result is as follows, and the loader can be found in the node_modules directory.

3. Configure loader written in Webpack

This configuration is no different from the Webpack configuration in Section 1 and will not be detailed here. The configuration reference is as follows:

  module: {rules:[
      {
        test:/\.js/.use: ['custom-loader'].include:path.resolve(__dirname,'show')}}]Copy the code

Execute the run or compile command to see our loader in action.

5. Write Plugin

Webpack is like a production line. It takes a series of processes to convert source files into output results. Each process on this production line has a single responsibility, and there is a dependency between multiple processes. A plug-in is like a function in a production line that processes resources on the production line at a specific time.

Webpack organizes this complex production line through Tapable. Webpack broadcasts events as it runs, and the plug-in only needs to listen for the events it cares about to join the production line and change how the production line works. Webpack’s event flow mechanism ensures the orderliness of plug-ins and makes the whole system very extensible.

1. Summary of Plugin points

  • Webpack broadcasts many events during compilation, such as run, compile, done, fail, etc. You can check the official website.
  • The Webpack event flow mechanism applies the observer mode. The plug-in we write can listen to Webpack events to trigger the corresponding processing logic.
  • Plugins can use many of Webpack’s apis, such as reading output resources, code blocks, modules, and dependencies.

2. Write Plugin source code

Write a plugin source code, its function is to output when Webpack compilation success or failure prompt; Of course, this plugin actually has no practical meaning. It is just a plugin for plugin’s sake. Of course, if your actual business needs to write plugin requirements, it is necessary to reflect on the reasonableness of this business, because the large community, generally reasonable needs can find the corresponding plugin.

(1) Source code writing

Under the original project, new directory custom-plugin as we write plugin name, execute NPM init command, create a new modular project, and then create a new index.js file, the relevant source code is as follows:

class CustomPlugin{
  constructor(doneCallback, failCallback){
     // Save the callback function passed in when creating the plug-in instance
     this.doneCallback = doneCallback;
     this.failCallback = failCallback;
  }
  apply(compiler){
    // The done event is emitted when a complete compilation and output process is successfully completed
    compiler.plugin('done',(stats)=>{
      this.doneCallback(stats);
    })
    // The failed event is emitted when an exception is encountered in the compilation and output process
    compiler.plugin('failed',(err)=>{
      this.failCallback(err); }}})module.exports = CustomPlugin;
Copy the code

(2) Npm Link module registration

As with Loader registration, we use NPM link for registration;

In the custom-plugin directory, run the following command to register the local module globally:

$ npm link
Copy the code

Then run the following command in the project root directory to link the local Npm modules registered globally to the node_modules of the project:

$ npm link custom-plugin
Copy the code

If all goes well, the plugin can be found in the node_modules directory.

3. Configure the plugin written in Webpack

This configuration is no different from the Webpack configuration in Section 1 and will not be detailed here. The configuration reference is as follows:

  plugins:[
    new CustomPlugin(
     stats= > {console.info('Compiled successfully! ')},
     err => {console.error('Compilation failed! ')})],Copy the code

Execute the run or compile command to see our plugin in action.

Six, step pit summary

1. Configure csS-loader as follows

rules:[
  {
	// Use the re to match the CSS file to be converted with the loader
	test:/\.css$/.use: ['style-loader'.'css-loader? minimize']}]Copy the code

The following error is reported:

 - options has an unknown property 'minimize'. These properties are valid: object { url? .import? , modules? , sourceMap? , importLoaders? , localsConventio n? , onlyLocals? , esModule? }Copy the code

The reason:

The minimize property has been removed in the new version,

Solution:

Take out the minimize option;

2, ExtractTextPlugin compiles the following error:

The reason:

Extract -text-webpack-plugin version number problem

Reference link: github.com/webpack/web…

Solution:

Re-install the extract-text-webpack-plugin

$ npm i -D extract-text-webpack-plugin@next
Copy the code

3, after fixing the second pit, ExtractTextPlugin compilation continues to report the following error:

The reason:

The contenthash variable does not exist

Solution:

Change the extract-text-webpack-plugin configuration:

  plugins:[
    new ExtractTextPlugin({
       // The name of the.css file extracted from the.js file
       filename:`[name]_[hash:8].css`}),]Copy the code

4, Add the HappyPack, compile the CSS file and report the following error:

The reason:

The CSS-Loader version is faulty

Solution:

Reinstall [email protected]

Seven,

This article is mainly based on the role of Webpack, core concepts, processes, basic configuration of Webpack, Webpack optimization, Loader writing, Plugin writing, from theory to practice, from the basic to difficult, Webpack summary master, I hope it is also helpful to you. Or that sentence: the paper come zhongjue shallow, must know this to practice… If you haven’t done it before, do it more often!

Blog github address: github.com/fengshi123/… , a summary of all the author’s blogs, also welcome to follow and star ~

This article practices the Github address of demo