Update dec 7, 2017, added clean-webpack-plugin, babel-enV-preset, added examples of all the code covered in this article, for reference here if you make mistakes during learning

The words written in the front

Before reading this article, take a look at the webPack configuration file below. If you know everything, this article may be of limited benefit to you. You can scan it quickly or skip it. If you’re like me 10 days ago and you’re wondering about a lot of options, take some time to read this article, and one by one your doubts will disappear. If you haven’t had much experience with Webpack before and you’re interested in Webpack, follow the example throughout this article and you’ll find that you’re definitely in Webpack.

// a common 'webpack' configuration file const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); Module.exports = {entry: __dirname + "/app/main.js", // exports = {entry: __dirname + "/app/main.js", // exports: {path: __dirname + "/build", filename: "Bundle -[hash].js"}, devtool: 'None ', devServer: {contentBase: "./public", // historyApiFallback: True, / / don't jump the inline: true, hot: true}, the module: {rules: [{test: / (\. JSX | \. Js) $/, use: {loader: "babel-loader" }, exclude: /node_modules/ }, { test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: [{ loader: "css-loader", options: { modules: true, localIdentName: '[name]__[local]--[hash:base64:5]' } }, { loader: "postcss-loader" }], }) } } ] }, plugins: [new webpack.bannerPlugin (' copyright '), new HtmlWebpackPlugin({template: __dirname + "/app/ index.tdpl. HTML "/ /new an instance of this plugin, }) and passed the relevant parameters, the new webpack. Optimize the OccurrenceOrderPlugin (), new webpack. Optimize. UglifyJsPlugin (), new ExtractTextPlugin("style.css") ] };Copy the code

What is WebPack and why should you use it?

Why use WebPack

Many web pages today can be thought of as feature-rich applications with complex JavaScript code and a lot of dependency packages. Many good practices have emerged in the front-end community to simplify development

  • Modularity allows us to break down complex programs into smaller files.
  • Development languages like TypeScript, which extend JavaScript, allow us to implement features that are not directly available in current versions of JavaScript, and then convert them to JavaScript files for browsers to recognize.
  • CSS preprocessors such as Scss and LESS
  • .

These improvements made development much more efficient, but files developed with them often required additional processing to be recognized by the browser, and manual processing was cumbersome, which provided the need for webPack-like tools.

What is a Webpack

WebPack can be viewed as a module baler: It analyzes the structure of your project, finds JavaScript modules and other extension languages that browsers don’t run directly (Scss, TypeScript, etc.), and converts and packages them into appropriate formats for browsers to use.

How does WebPack compare to Grunt and Gulp

There is not much comparison between Webpack and the other two. Gulp/Grunt is a tool to optimize the development process of the front end, while Webpack is a modular solution, but the advantages of Webpack make Webpack a substitute for Gulp/Grunt class tools in many scenarios.

Grunt and Gulp work like this: in a configuration file, specify specific steps to perform tasks such as compiling, combining, and compressing certain files, and the tool then automatically performs these tasks for you.

Webpack works by treating your project as a whole through a given master file (e.g. Index.js), Webpack will start with this file to find all of your project’s dependent files, process them with loaders, and finally package them into one (or more) browser-aware JavaScript files.

If you really want to compare the two, Webpack is faster and more straightforward, and can package more different types of files.

Start using Webpack

After a preliminary understanding of how Webpack works, we began to learn how to use Webpack step by step.

The installation

Webpack can be installed using NPM. Create an empty exercise folder (named Webpack Sample Project here) and execute the following command after the terminal is transferred to this folder to complete the installation.

NPM install --save-dev webpack // Install to your project directoryCopy the code

Preparations for the official use of Webpack

  1. Create a package.json file in the above exercise folder. This is a standard NPM specification file that contains a wealth of information, including dependencies for the current project, custom script tasks, and so on. Used on terminalsnpm initThe package.json file is automatically created by the package.json command
npm initCopy the code

After entering this command, the terminal will ask you a series of information such as project name, project description, author, etc., but don’t worry, if you are not going to publish your module in NPM, the answers to these questions are not important.

  1. With the package.json file in place, we install Webpack as a dependency package in this project
// install Webpack NPM install --save-dev WebpackCopy the code
  1. Go back to the empty folder and create two folders inside,app and public,app to hold the raw data and the JavaScript module that we’re going to write, The public folder is used to store files that are later read by the browser (including js files generated using webpack packaging and oneindex.htmlFile). Next we create three more files:
  • index.htmlPut it in the public folder.
  • Greeter.js— Put it in app folder;
  • main.js— Put it in app folder;

The project structure is shown in the figure below

We write the basic HTML code in the index.html file, which is used to import the packaged JS file (we’ll name the packaged JS file bundle.js, which we’ll cover in more detail later).

<! -- index.html --> <! DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Webpack Sample Project</title> </head> <body> <div id='root'> </div> <script src="bundle.js"></script> </body> </html>Copy the code

We define a function in greeter.js that returns an HTML element containing a greeting and export the function as a module according to the CommonJS specification: greeter.js

// Greeter.js module.exports = function() { var greet = document.createElement('div'); greet.textContent = "Hi there and greetings!" ; return greet; };Copy the code

In the main.js file, we write the following code to insert a node returned by the Greeter module into the page.

//main.js 
const greeter = require('./Greeter.js');
document.querySelector("#root").appendChild(greeter());Copy the code

Official use of Webpack

Webpack can be used in the terminal, in the basic use of the following:

# {extry file} specifies the path to the entry file. {} webpack {entry file} {destination for bundled file}Copy the code

When you specify the entry file, WebPack will automatically recognize other files that your project depends on, but note that if your webPack is not globally installed, then when you use this command on a terminal, you will need to specify an additional address in node_modules. Continuing with the example above, enter the following command on the terminal

Node_modules /.bin/webpack app/main.js public/bundle.jsCopy the code

The results are as follows

It can be seen thatwebpackIt’s compiled at the same timemain.jsGreeter,jsOpen it nowindex.html, you can see the following results

Are you excited to have successfully packaged a file using Webpack? While complex operations in a terminal can be inconvenient and error-prone, let’s look at another, more common use of Webpack.

Use it through a configuration fileWebpack

Webpack has many other more advanced features (loaders and plugins, for example, described later in this article) that can be implemented using the command line mode, but as mentioned earlier, this is inconvenient and error-prone. A better way is to define a configuration file, This configuration file is actually a simple JavaScript module where we can put all the packaging-related information.

To continue the example above, create a new file called webpack.config.js in the root directory of the current exercise folder and write the simple configuration code shown below. The current configuration mainly involves the entry file path and the packaged file storage path.

Module.exports = {entry: __dirname + "/app/main.js",// exports = {entry: __dirname + "/app/main.js",// exports: {path: Filename: "bundle.js"// output filename}}Copy the code

Note: “__dirname” is a global variable in Node.js that points to the directory where the script is currently executing.

Once you have this configuration, to pack the file, simply run the webpack command from your terminal (node_modules/.bin/webpack for non-global installation), which automatically references the configuration options in the webpack.config.js file, as shown in the following example:

It’s nice to learn another way to use Webpack that doesn’t bother with command-line arguments. If you don’t have to use webpack(node_modules/.bin/webpack for non-global installation), it will feel better.

Perform packing tasks more quickly

Typing commands on the command line requires code like node_modules/.bin/webpack, which can be a bit annoying, but thankfully NPM can be bootstrapping. After configuring NPM, you can use the simple NPM start command on the command line instead of the slightly tedious commands above. Set the scripts object in package.json as follows.

{"name": "webpack-sample-project", "version": "1.0.0", "description": "sample webpack project", "scripts": {"start": }, "author": "zhang", "license": "ISC", "devDependencies": {"webpack": "3.10.0}}"Copy the code

Note: The script in package.json installs a certain order to find the command location. The local node_modules/.bin path is included in the find list, so you don’t need to write the specified path for both global and local Webpack installations.

NPM start command is a special script name, its particularity is shown in the command line using NPM start command can execute the corresponding command, if the corresponding script name is not start, want to run on the command line, NPM run {script name} NPM run build: NPM start

Now all you need to do is use NPM start to package files. Webpack is just like that, but don’t take WebPack too seriously. To make the most of its power we need to change other configuration file options, item by item.

The power of Webpack

Generating Source Maps (to make debugging easier)

Debugging is a big part of development, but sometimes it’s hard to find what went wrong and where your code is in a packaged file. Source Maps is here to help solve this problem.

With simple configuration, WebPack can provide our generated Source maps at package time, giving us a way to correspond to compiled files and source files, making compiled code more readable and easier to debug.

To configure Source Maps in the webPack configuration file, you need to configure devTool, which has the following four different configuration options, each with advantages and disadvantages, described as follows:

Devtool options Configure the results
source-map To produce a complete and fully functional file in a separate file. This file has the bestsource map, but it slows down the packaging;
cheap-module-source-map Generates a column mapping without a column mapping in a separate filemap, without column mapping improves the packaging speed, but also makes browser developer tools can only correspond to specific rows, not to specific columns (symbols), which will cause inconvenience to debugging;
eval-source-map useevalPackage the source file module to generate a clean complete in the same filesource map. This option can generate a complete build without slowing down the build speedsourcemap, but the execution of packaged output JS files has performance and security risks. This is a great option during development, and should never be enabled during production;
cheap-module-eval-source-map This is the fastest generation when packaging filessource mapMethod, generated bySource MapIt will be packagedJavaScriptFile line display, no column mapping, andeval-source-mapOptions have similar disadvantages;

As shown in the table above, these options are getting faster and faster from top to bottom, but they also have more and more negative effects. The consequence of faster packaging speed is that it has some impact on the execution of packaged files.

Eval-source-map is a good option for small to medium projects. Again, you should only use it during development. We continue with our new webpack.config.js configuration as follows:

module.exports = {
  devtool: 'eval-source-map',
  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/public",
    filename: "bundle.js"
  }
}Copy the code

The cheap-module-eval-source-map method is faster to build but less conducive to debugging, and is recommended for large projects where time costs are considered.

Build the local server using Webpack

If you want your browser to listen for changes to your code and automatically refresh to display the changes, Webpack provides an optional local development server that is built on Node.js and can do all the things you want, but it is a separate component. You need to install it separately as a project dependency before configuring it in WebPack

npm install --save-dev webpack-dev-serverCopy the code

Devserver is one of the webPack configuration options. Here are some of its configuration options, and more configurations can be found here

Configuration options for DevServer Functional description
contentBase By default, webpack-dev-server provides a local server for the root folder. If you want to provide a local server for files in a different directory, you should set its directory here (in this case, to the “public” directory).
port Set default listening port. If omitted, default to 8080.
inline Set totrue, automatically refreshes the page when the source file changes
historyApiFallback Useful when developing a single page application, which relies on the HTML5 History API if set totrue, all jumps will point to index.html

Add these commands to the webpack configuration file, which is now webpack.config.js as shown below

module.exports = { devtool: 'eval-source-map', entry: __dirname + "/app/main.js", output: { path: __dirname + "/public", filename: "bundle.js" }, devServer: { contentBase: "./public",// historyApiFallback: true,// Don't skip inline: true// refresh in real time}}Copy the code

Add the following command to the scripts object in package.json to start the local server:

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack",
    "server": "webpack-dev-server --open"
  },Copy the code

Enter NPM run server on the terminal to view the result on port 8080

Loaders

Enter the famous Loaders!

Loaders is one of the most exciting features webPack has to offer. By using different loaders, WebPack has the ability to call external scripts or tools to process files in different formats, such as analyzing and converting SCSS to CSS, or converting next-generation JS files (ES6, ES7) to modern browser-compatible JS files. The appropriate Loaders can convert JSX files used in React to JS files.

Loaders needs to be installed separately and configured under the modules keyword in webpack.config.js. Loaders configuration includes the following aspects:

  • test: a regular expression that matches the extension name of the file loaders is handling (must)
  • loader: Loader name (mandatory)
  • include/exclude: Manually add files (folders) that must be processed or mask files (folders) that do not need to be processed (optional).
  • query: Additional setup options for Loaders (optional)

However, before configuring loader, we put the greeting message in Greeter.js into a separate JSON file and make greeter. js read the value of the JSON file through appropriate configuration. The modified code of each file is as follows:

Create a JSON file with the greeting message in the app folder (name it config.json)

{
  "greetText": "Hi there and greetings from JSON!"
}Copy the code

Updated greeter.js

var config = require('./config.json');

module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = config.greetText;
  return greet;
};Copy the code

Note since webpack3.*/webpack2.* has built-in JSON files, we do not need to add the json-loader required by webpack1. Before we look at how to use loader in detail let’s look at what Babel is.

Babel

Babel is actually a platform for compiling JavaScript. It compiles code to help you:

  • Enables you to use the latest JavaScript code (ES6, ES7…) Regardless of whether the new standard is fully supported by current browsers;
  • Allows you to use javascripts based extensions of languages such as React JSX;

Installation and configuration of Babel

Babel is actually a few modular packages, the core function is located in the NPM package called Babel-core, WebPack can use its different packages together, for each function or extension you need, You’ll need to install separate preset packages (the most used are the babel-EnVP-preset package for Es6 and the babel-envp-react package for JSX).

Let’s install these dependencies once and for all

// NPM install --save-dev babel-core babel-loader babel-preset-env babel-preset-react NPM install --save-dev babel-core babel-loader babel-preset- preset-reactCopy the code

Configure Babel in Webpack as follows:

Module.exports = {entry: __dirname + "/app/main.js",// exports = {entry: __dirname + "/app/main.js",// exports: {path: Filename: "bundle.js"// output filename}, devtool: 'eval-source-map', devServer: {contentBase: "./public",// historyApiFallback: true,// No jump inline: true// refresh}, module: {rules: [ { test: /(\.jsx|\.js)$/, use: { loader: "babel-loader", options: { presets: [ "env", "react" ] } }, exclude: /node_modules/ } ] } };Copy the code

Your WebPack configuration now allows you to use ES6 and JSX syntax. Continue the test with the example above, but this time we will use React. Remember to install React and React-DOM first

npm install --save react react-domCopy the code

Next we use ES6 syntax to update greeter.js and return a React component

//Greeter,js
import React, {Component} from 'react'
import config from './config.json';

class Greeter extends Component{
  render() {
    return (
      <div>
        {config.greetText}
      </div>
    );
  }
}

export default GreeterCopy the code

Modify main.js as follows to use ES6’s module definition and render Greeter modules

// main.js
import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';

render(<Greeter />, document.getElementById('root'));Copy the code

If the local server is not closed, you should see the same content under localhost:8080. This indicates that react and ES6 are properly packaged.

Babel’s configuration

Babel can be configured entirely in webpack.config.js, but given the number of configuration options available to Babel, configuring it in a single webpack.config.js file often makes it too complex. Therefore, some developers support placing Babel configuration options in a separate configuration file named “.babelrc”. Our current configuration of Babel is not too complicated, but we will add more things later, so for now we will extract the relevant parts and configure them in two configuration files (the Babel configuration option in. Babelrc is automatically called by Webpack), as follows:

Module.exports = {entry: __dirname + "/app/main.js",// exports = {entry: __dirname + "/app/main.js",// exports: {path: Filename: "bundle.js"// output filename}, devtool: 'eval-source-map', devServer: {contentBase: "./public",// historyApiFallback: true,// No jump inline: true// refresh}, module: {rules: [ { test: /(\.jsx|\.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ } ] } };Copy the code
//.babelrc
{
  "presets": ["react", "env"]
}Copy the code

So far, we’ve seen that Webpack provides very powerful processing capabilities for modules, and those are modules.

Everything is module

Webpack has the unspoken advantage that all files are treated as modules, JavaScript code, CSS and fonts, images, etc. can be handled by the appropriate loader.

CSS

Webpack provides two tools for handling style sheets, CSS-loader and style-loader, which handle different tasks. Css-loader allows you to use things like @import and URL (…). The style-loader method implements require(), and the style-loader adds all computed styles to the page. Together, the style-loader allows you to embed stylesheets in webpack-packed JS files.

Continue with the example above

// install NPM install --save-dev style-loader CSS-loaderCopy the code
Module. exports = {... module: { rules: [ { test: /(\.jsx|\.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ }, { test: /\.css$/, use: [ { loader: "style-loader" }, { loader: "css-loader" } ] } ] } };Copy the code

Note the method of introducing multiple Loaders to the same file.

Next, create a file named “main.css” in the app folder and style some elements

/* main.css */
html {
  box-sizing: border-box;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}

*, *:before, *:after {
  box-sizing: inherit;
}

body {
  margin: 0;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

h1, h2, h3, h4, h5, h6, p, ul {
  margin: 0;
  padding: 0;
}Copy the code

The webpack we use in this example has a single entry, other modules need to be associated with the entry file via import, require, URL, etc. In order for WebPack to find the “main. CSS” file, we import it into “main.js”, as shown below

//main.js import React from 'react'; import {render} from 'react-dom'; import Greeter from './Greeter'; import './main.css'; Render (<Greeter />, document.getelementbyid ('root'));Copy the code

Typically, CSS and JS are packaged in the same file, not as a separate CSS file, but webPack can be packaged as a separate file with the proper configuration.

The above code illustrates how Webpack treats CSS as a module, so let’s move on to a more realistic CSS module practice.

CSS module

Over the past few years, JavaScript has grown rapidly with new language features, better tools, and better practices such as modularity. Modules allow developers to turn complex code into small, clean, dependent-declared units. With optimization tools, dependency management and load management can be done automatically.

The other part of the front end, CSS, is slower to evolve, and most stylesheets are still huge and full of global class names that are difficult to maintain and modify.

A technique called CSS Modules is intended to bring the idea of JS modularity to CSS. With CSS modules, all class names, animation names, by default, only apply to the current module. Webpack provides great support for CSS modularity by simply configuring it in the CSS Loader and then passing the CSS class name directly to the component code, effectively avoiding global contamination. The specific code is as follows

module.exports = { ... module: { rules: [ { test: /(\.jsx|\.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ }, { test: /\.css$/, use: [ { loader: "style-loader" }, { loader: "css-loader", options: { modules: True, // Enable CSS modules localIdentName: '[name]__[local]--[hash:base64:5]' // Specify the CSS class name format}}]}]}};Copy the code

To test this out, create a greeter. CSS file in the app folder

/* Greeter.css */
.root {
  background-color: #eee;
  padding: 10px;
  border: 3px solid #ccc;
}Copy the code

Import. Root into greeter.js

import React, {Component} from 'react'; import config from './config.json'; import styles from './Greeter.css'; // Import class Greeter extends Component{render() {return (<div className={styles.root}> // Use cssModule to add a method to the class name {config.greetText} </div> ); } } export default GreeterCopy the code

Rest assured, the same class name will not pollute different components.

CSS Modules is also a big topic, so you can go to the official documentation to learn more.

CSS preprocessor

Preprocessors like Sass and Less are extensions of native CSS. They allow you to write CSS using features like variables, nesting, mixins, inheritance, etc., that don’t exist in CSS. The CSS preprocessor can turn these special types of statements into browser-aware CSS statements,

Loaders you are probably familiar with by now, and can be configured to use loaders in webpack. Here are some common CSS loaders:

  • Less Loader
  • Sass Loader
  • Stylus Loader

However, there is also a CSS processing platform -PostCSS, it can help your CSS to achieve more functions, in its official documentation can learn more about the relevant knowledge.

As an example of how to use PostCSS, we use PostCSS to automatically prefix CSS code for different browsers.

Install postCSS-Loader and Autoprefixer first.

npm install --save-dev postcss-loader autoprefixerCopy the code

Next, add postcss-loader to the webpack configuration file, create postcss.config.js in the root directory, and add the following code. When repacking with NPM start, your CSS will automatically be prefixed according to the data in Can I Use.

//webpack.config.js
module.exports = {
    ...
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader",
                        options: {
                            modules: true
                        }
                    }, {
                        loader: "postcss-loader"
                    }
                ]
            }
        ]
    }
}Copy the code
// postcss.config.js
module.exports = {
    plugins: [
        require('autoprefixer')
    ]
}Copy the code

So far, this article has talked about the basic uses of Babel for JS and PostCSS for CSS, which are actually two separate platforms that work well with WebPack. Next, Plugins are another very important feature in Webpack

Plugins

Plugins are used to extend Webpack functionality, and they take effect throughout the build process to perform related tasks. Loaders and Plugins are often confused, but they are completely different things, so to speak, Loaders are used to process source files during the packaging build process (JSX, Scss, Less..). One at a time, the plug-in does not directly manipulate individual files, it directly affects the entire build process.

Webpack has many built-in plugins, as well as a number of third-party plugins that allow us to achieve richer functionality.

The method of using plug-ins

To use a plug-in, we need to install it via NPM, and all we need to do is add an instance of the plug-in in the plugins keyword section of the WebPack configuration (plugins are an array). Continuing with the previous example, we added a plug-in that adds a copyright notice to the packaged code.

const webpack = require('webpack');

module.exports = {
...
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader",
                        options: {
                            modules: true
                        }
                    }, {
                        loader: "postcss-loader"
                    }
                ]
            }
        ]
    },
    plugins: [
        new webpack.BannerPlugin('版权所有,翻版必究')
    ],
};Copy the code

With this plug-in, the packaged JS file appears as follows

This is the basic use of webpack plugins, and here are some common plugins to recommend

HtmlWebpackPlugin

This plugin creates a new index.html file that automatically references your packed JS file based on a simple index.html template. This is useful if the js file name is different each time it is generated (such as adding hash values).

The installation

npm install --save-dev html-webpack-pluginCopy the code

This plugin automates some of the things we did manually, and requires some changes to the project structure before it can be used:

  1. Remove the public folder, use this plugin,index.htmlThe files are automatically generated, and CSS is already packaged into JS by the previous steps.
  2. In the app directory, create oneindex.tmpl.htmlFile template, which containstitleDuring the compilation process, the plug-in will generate the final HTML page based on this template, and will automatically add the CSS, JS, Favicon and other files that depend on it.index.tmpl.htmlThe template source code is as follows:
<! DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Webpack Sample Project</title> </head> <body> <div id='root'> </div> </body> </html>Copy the code

3. Update the webPack configuration file by creating a build folder to store the final output file

const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); Module.exports = {entry: __dirname + "/app/main.js",// exports = {entry: __dirname + "/app/main.js",// exports: {path: __dirname + "/build", filename: }, devtool: 'eval-source-map', devServer: {contentBase: "./public", True, / / don't jump the inline: true / / real-time refresh}, the module: {rules: [{test: / (\. JSX | \. Js) $/, use: {loader: "Babel - loader"}, exclude: /node_modules/ }, { test: /\.css$/, use: [ { loader: "style-loader" }, { loader: "css-loader", options: { modules: true } }, { loader: "postcss-loader" } ] } ] }, plugins: [new webpack.bannerPlugin (' copyright '), new HtmlWebpackPlugin({template: __dirname + "/app/ index.tdpl.html "//new an instance of this plugin and pass in the relevant arguments})],};Copy the code

Run NPM start again and you’ll see bundle.js and index.html generated under the build folder.

Hot Module Replacement

Hot Module Replacement (HMR) is also a useful plug-in in WebPack that allows you to automatically refresh your component code to see what the changes will look like in real time.

Implementing HMR in WebPack is also simple, requiring only two configurations

  1. Add the HMR plug-in to the WebPack configuration file;
  2. Add “hot” parameter to Webpack Dev Server;

You need to implement the Webpack API in your JAVASCRIPT module to implement hot loading. This API is not difficult to use, but if you use the React module, you can use the familiar Babel to implement hot loading.

Sorting out our ideas, the specific implementation method is as follows

  • BabelandwebpackIt’s a separate tool
  • The two can work together
  • Both can be extended through plug-ins
  • HMR is a Webpack plug-in that allows you to see how modules are modified in real time in your browser, but requires an additional module quota if you want it to work;
  • Babel has one calledreact-transform-hrmThe React plugin allows HMR to work without additional configuration for the React module.

Or should WE continue with the example to see how to actually configure it

const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); Module.exports = {entry: __dirname + "/app/main.js",// exports = {entry: __dirname + "/app/main.js",// exports: {path: __dirname + "/build", filename: }, devtool: 'eval-source-map', devServer: {contentBase: "./public", True, / / don't jump the inline: true, hot: true}, the module: {rules: [{test: / (\. JSX | \. Js) $/, use: {loader: "babel-loader" }, exclude: /node_modules/ }, { test: /\.css$/, use: [ { loader: "style-loader" }, { loader: "css-loader", options: { modules: true } }, { loader: "postcss-loader" } ] } ] }, plugins: [new webpack.bannerPlugin (' copyright '), new HtmlWebpackPlugin({template: __dirname + "/ app/index. TMPL. HTML" / / new an instance of the plug-in, and passed the relevant parameter}), new webpack. HotModuleReplacementPlugin () / / hot load plugins],};Copy the code

Install the react – transform – HMR

npm install --save-dev babel-plugin-react-transform react-transform-hmrCopy the code

Configure the Babel

// .babelrc
{
  "presets": ["react", "env"],
  "env": {
    "development": {
    "plugins": [["react-transform", {
       "transforms": [{
         "transform": "react-transform-hmr",
         
         "imports": ["react"],
         
         "locals": ["module"]
       }]
     }]]
    }
  }
}Copy the code

Now when you use React, you can hot-load modules and see updates in your browser every time you save.

Production phase construction

So far, we have built a complete development environment using WebPack. However, during the production phase, additional processing of packaged files may be required, such as optimization, compression, caching, and separation of CSS and JS.

For complex projects, the need to complex configuration, then decompose the configuration file into multiple small files can make things in good order, the above example, we create a webpack. Production. Config. Js file, Add the basic configuration inside, which is similar to the original webpack.config.js, as follows

// webpack.production.config.js const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); Module.exports = {entry: __dirname + "/app/main.js", // exports = {entry: __dirname + "/app/main.js", // exports: {path: __dirname + "/build", filename: "Bundle. js"}, devtool: 'null', // Notice the change here, this can greatly compress our packaging code devServer: {contentBase: HistoryApiFallback: true, // Don't skip inline: true, hot: true}, module: {rules: [{test: /(\.jsx|\.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ }, { test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: [{ loader: "css-loader", options: { modules: true } }, { loader: "postcss-loader" }], }) }] }, plugins: [new webpack.bannerPlugin (' copyright '), new HtmlWebpackPlugin({template: __dirname + "/ app/index. TMPL. HTML" / / new an instance of the plug-in, and passed the relevant parameter}), new webpack. HotModuleReplacementPlugin () / / hot load plugins],};Copy the code
/ / package. Json {" name ":" test ", "version" : "1.0.0", "description" : ""," main ":" index. Js ", "scripts" : {" test ": "echo \"Error: no test specified\" && exit 1", "start": "webpack", "server": "webpack-dev-server --open", "build": "NODE_ENV=production webpack --config ./webpack.production.config.js --progress" }, "author": "", "license": "ISC", "devDependencies": { ... }, "dependencies" : {" react ":" ^ 15.6.1 ", "the react - dom" : "^ 15.6.1"}}Copy the code

Note: For Windows, build should be set to “Build “: “set NODE_ENV=production && webpack –config ./webpack.production.config.js –progress”. Thank you for reminding me in the comments section.

Optimize the plug-in

Webpack provides several optimization plug-ins that are useful during the release phase, most of which come from the WebPack community and can be installed via NPM. The following plug-ins can be used to complete the functionality required during the product release phase

  • OccurenceOrderPlugin: Assigns ids to components, using the plug-in WebPack to analyze and prioritize the most used modules and assign them the smallest ids
  • UglifyJsPlugin: Compressed JS code;
  • ExtractTextPlugin: Separate CSS and JS files

OccurenceOrder and UglifyJS plugins are built-in plugins. All you need to do is install other non-built-in plugins

npm install --save-dev extract-text-webpack-pluginCopy the code

Refer to them after plugins in the configuration file

// webpack.production.config.js const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); Module.exports = {entry: __dirname + "/app/main.js",// exports = {entry: __dirname + "/app/main.js",// exports: {path: __dirname + "/build", filename: }, devtool: 'None ', devServer: {contentBase: "./public",// historyApiFallback: True, / / don't jump the inline: true, hot: true}, the module: {rules: [{test: / (\. JSX | \. Js) $/, use: {loader: "babel-loader" }, exclude: /node_modules/ }, { test: /\.css$/, use: [ { loader: "style-loader" }, { loader: "css-loader", options: { modules: true } }, { loader: "postcss-loader" } ] } ] }, plugins: [new webpack.bannerPlugin (' copyright '), new HtmlWebpackPlugin({template: __dirname + "/app/index.tmpl.html" }), new webpack.optimize.OccurrenceOrderPlugin(), new webpack.optimize.UglifyJsPlugin(), new ExtractTextPlugin("style.css") ], };Copy the code

When you run NPM run build, you can see that the code is compressed

The cache

Caches are everywhere, and the best way to use them is to make sure that your file name matches the content of the file (the content changes, the name changes accordingly).

Webpack can add a hash to the packaged file name by adding a special string mixture ([name], [id] and [hash]) to the output file name

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
..
    output: {
        path: __dirname + "/build",
        filename: "bundle-[hash].js"
    },
   ...
};Copy the code

Now the user will have a reasonable cache.

Get rid ofbuildResidual files in files

The clean-webpack-plugin is another useful plugin for repackaging files with different names after adding hash.

Install: CNPM install clean-webpack-plugin –save-dev

Use:

Add the clean-webpack-plugin to the plugins in the configuration file and do the following:

const CleanWebpackPlugin = require("clean-webpack-plugin"); New CleanWebpackPlugin('build/*.*', {root: __dirname, verbose: true, dry: false})]Copy the code

Detailed usage of the clean-webpack-plugin can be found here

conclusion

In fact, this is an article from a year ago, I ran it again and modified it over the weekend, now all the code can run normally, using webPack based on the latest Webpack 3.5.3. I hope it still helps.

This is a long article, thank you for your patience, you can read it carefully. About half a month ago, I first configured the Webpack required by the project step by step, and I always wanted to write a note to make a summary, but I couldn’t satisfy myself for several times. I always felt that I couldn’t write clearly. In fact, this article about Webpack is still not complete, but I believe that you have entered the door of Webpack after reading, can better explore other knowledge about Webpack.

You are welcome to post your views in the post.

Updated instructions

2017-12-11 update, modify the CSS Module part of the code and sample pictures, CSS Module is really good, I hope you can use it.

Update 18 September 2017 added a demo for configuring multi-page applications using WebPack, which can be viewed here

Updated on August 13, 2017, this article has been completely rewritten according to webpack3.5.3, and all of the code runs properly on Mac. I hope it is still helpful for you to learn Webpack.

Updated on August 16, 2017:

Gitchat recently launched a webpack sharing, the purpose is to spend the shortest time together to understand and learn webpack, interested children can scan wechat registration.