File listening in WebPack

File listening automatically reconstructs a new output file when it detects changes in the source code. No need to manually rebuild and refresh the browser.

There are two ways to enable listening mode in WebPack:

  • Start the webpack command with the –watch parameter;
  • Set watch: true in configuring webpack.config.js.

Analysis of the principle of file listening

Polling to determine whether the last edit time of the file has changed. When a file changes, the listener is not immediately notified. Instead, the file is cached and wait for aggregateTimeout.

module.export = {
  // The default value is false
  watch: true.// watchOptions is only meaningful if the listening mode is enabled
  wathcOptions: {
    // Default is empty, do not listen to files or folders, support regular match
    ignored: /node_modules/.// Wait 300ms before executing. Default: 300ms
    aggregateTimeout: 300.// The default value is 1000 times per second. // The default value is 1000 times per second
    poll: 1000,}};Copy the code

Bug: You need to manually refresh the browser each time.

Hot update: webpack-dev-server

WDS does not need to refresh the browser, does not output files, but in memory. Webpack used to own HotModuleReplacementPlugin plug-in, you need to install webpack – dev – server.

yarn add webpack-dev-server --dev
Copy the code

Hot update configuration in webpack.config.js:

// Use the HashedModuleIdsPlugin plug-in
plugins: [new webpack.HashedModuleIdsPlugin()],
devServer: {
    // The directory to listen to
    contentBase: "./dist".// Tell DevServer to enable hot replacement mode for modules
    hot: true,},// This can only be configured in development mode
mode: "development".Copy the code

Json, where the –open parameter automatically opens the browser after hot update is enabled:After the configuration is complete, you can run the following shortcut commands:

yarn dev
Copy the code

Principle analysis of thermal renewal

  1. Webpack Compile compiles and packages the initial files according to the configuration of webpack.config.js, and generates the compiled files, such as bundle.js.
  2. Webpack generates both HMR Server and Bundle Server services and injects HMR Rumtime into bundle.js.
    Bundle Server: Provides browser access to files. HMR Server: Outputs hot update files to HMR Rumtime. HMR Rumtime: update file changes.Copy the code
  3. If the local files change, Webpack repackages them and sends them to the HMR Server. The HMR Server knows that the resources have changed and notifies the client HMR Rumtime with JSON data via WebSocket about which files have changed.
  4. HMR Rumtime is incrementally updated in memory.

Thermal update is divided into two stages:

  • In the boot phase, it still relies on disk files to compile (figure 1 -> 2 -> A -> B).
  • The update phase is a direct incremental memory update (figure 1 -> 2 -> 3 -> 4).

File fingerprint

Is the suffix of the file name output after packaging

Different kinds of file fingerprints

  1. Hash: Related to the entire project build. The Hash value of the entire project build changes whenever the project file is modified.
  2. Chunkhash: Relative to the chunk of webpack, different entries generate different Chunkhash values;
  3. Contenthash: Hash is defined according to the file content. If the file content does not change, the Contenthash does not change.

Generally, chunkhash is used to set the js file fingerprint, Contenthash is used to set the CSS file fingerprint, and hash is used to set the image file fingerprint.

Set a placeholder for the name of file-loader:

Need to install the mini – CSS – extract – plugin plug-ins, and use MiniCssExtractPlugin. Replace “style – loader loader.

"use strict";
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: { index: "./src/index.js".search: "./src/search.js" },
  output: {
    path: path.join(__dirname, "dist"),
    filename: "[name][chunkhash].js",},module: {
    rules: [{test: /\.js$/, use: "babel-loader" },
      { test: /\.css$/, use: [MiniCssExtractPlugin.loader, "css-loader"] {},test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"."less-loader"],}, {test: /\.(jpg|png|gif|jpeg)$/,
        use: [
          {
            loader: "url-loader".options: { limit: 10240.name: "[name]_[hash:8].[ext]"},},],},],},plugins: [
    new MiniCssExtractPlugin({
      filename: "[name][contenthash:8].css",})],mode: "production"};Copy the code

Code compression

JS file compression

Uglifyjs-webpack-plugin is built in WebPack 4 to compress JS code

Compression of CSS files

First install the optimize- CSS-assets – Webpack-Plugin and CSsnano.

yarn add optimize-css-assets-webpack-plugin cssnano --dev

// Use OptimizeCSSAssetsPlugin in your plugins.
new OptimizeCSSAssetsPlugin({
  assetNameRegExp: /\.css$/g,
  cssProcessor: require("cssnano"),}),Copy the code

HTML file compression

To modify the html-webpack-plugin and set the compression parameters, install:

yarn add html-webpack-plugin --dev

// Use HtmlWebpackPlugin in plugins
new HtmlWebpackPlugin({
  // Specify the HTML template
  template: path.join(__dirname, "src/search.html"),
  filename: "search.html".// Specify the search file to be imported
  chunks: ["search"].// inject true, js and CSS will be automatically injected into HTML
  inject: true.minify: {
    html5: true.collapseWhitespace: true.preserveLineBreaks: false.minifyCSS: true.minifyJS: true.removeComments: false,}}),Copy the code

Parameters:

  • Title: Generates the titile element of the page;
  • Filename: indicates the name of the GENERATED HTML file. Default index.html, which can be configured directly with subdirectories;
  • Template: path of the template file.
  • Inject: Inject the position of the inserted script. Four optional values:
    • True: the default, with the script tag at the bottom of the body of the HTML file;
    • Body: with true;
    • The head: script tag is inside the HEAD tag of the HTML file;
    • False: do not insert the generated JS file, only the generated HTML file.
  • Minify: Compresses HTML files. The property value is false or the value of the compression option. The default is false and does not compress HTML files.
  • Hash: Adds a hash value to the end of the generated JS file. This hash value is the hash value for this WebPack compilation. The default false;
  • Chunks: Which JS files are referenced in the HTML file, when used for multi-entry files. When chunks are not specified, all files reference the chunks.

Automatically clear the build directory

You can clean up the build directory with NPM scripts, which is configured in the package.json file “scripts”

"build": "rm -rf ./dist && webpack --config webpack.prod.js".Copy the code

But this isn’t elegant enough, so you can use the clean-webpack-plugin, which by default removes the output directory specified by output.

Install the clean-webpack-plugin:

yarn add clean-webpack-plugin --dev
Copy the code

Introduce modules in webpack.config.js

const { CleanWebpackPlugin } = require("clean-webpack-plugin");
Copy the code

Add plugins to plugins:

plugins: [
    new CleanWebpackPlugin(),
};
Copy the code

Automatically completes CSS3 prefixes

Why do CSS3 attributes need prefixes?

Because there are so many different kinds of browsers on mobile and PC.

.box {
    -moz-border-radius: 10px;
    -webkit-border-radius: 10px;
    -o-border-radius: 10px;
    border-radius: 10px;
}
Copy the code

Webpack automatically completes CSS3 prefixes using postCSS-Loader and autopreFixer plug-ins

First install both of the above:

yarn add postcss-loader autoprefixer --dev
Copy the code

Use them in CSS, less, and sass files


{
test: /\.less$/,
use: [
  MiniCssExtractPlugin.loader,
  "css-loader"."less-loader",
  {
    loader: "postcss-loader".options: {
      plugins: () = > [
        require("autoprefixer") ({// Adapt to the first two versions of the browser and use more than 1% of users, using ios 7 mobile system browser
          browsers: ["last 2 version"."1%" >."ios 7"],}),],},},],Copy the code

Responsive layout

The responsive layout is realized based on REM. Rem is set based on the value of HTML’s font-size. If the font-size is 16px, then 1REM =16px, so REM is a relative unit.

Use px2REM-Loader to automatically convert PX into REM. You can use the hand-scoured Lib-Flexible library to calculate the font-size value of the root element during page rendering.

Install px2rem – loader:

yarn add postcss-loader autoprefixer --dev
Copy the code

Install the lib – flexible:

yarn add lib-flexible
Copy the code

Webpack configuration:

{test: / \. Less $/, use: [MiniCssExtractPlugin loader, "CSS - loader", "less - loader", / / configure px2rem - loader {loader: "Px2rem-loader ", options: {// set the conversion rate for REM and px remUnit: 14, // set the number of decimal points retained after REM conversion remPrecision: 8,},},],},Copy the code

The effect of the build

Webpack implements inline resources

Resource inlining can load the initialization script of the page frame. CSS inlining avoids page flash and reduces the number of HTTP network requests.

HTML and JS inline

Install the raw – loader:

yarn add raw-loader --dev
Copy the code

Inline Settings:

<! DOCTYPEhtml>
<html lang="en">
  <head><%=require('raw-loader! ./inline.html').default%><title>index</title>
    <script>< % =require('raw-loader! babel-loader! ./inline.js').default %>
    </script>
  </head>
  <body></body>
</html>
Copy the code

If you install the [email protected] version, you do not need to add the “.default” code.

CSS inline

Use the style – loader. Configuration:

{loader: 'style-loader', options: {insertAt: 'top', // insert style into <head> singleton: true, // merge all style tags into one}}Copy the code

Multipage packaging

Use the Glob library to dynamically get the entry and set the number of HTmL-Webpack-plugin.

Install the Glob library first

yarn add glob --dev
Copy the code

Webpack configuration code:

const glob = require("glob");
const setMPA = () = > {
  const entry = {};
  const HtmlWebpackPlugins = [];
  const entryFiles = glob.sync(path.join(__dirname, "./src/*/*.js"));

  entryFiles.forEach((entryFile) = > {
    const match = entryFile.match(/src\/(.*)\/(index|search).js/);
    const pageName = match && match[1];

    pageName && (entry[pageName] = entryFile);
    pageName &&
      HtmlWebpackPlugins.push(
        new HtmlWebpackPlugin({
          template: path.join(__dirname, `src/${pageName}/${pageName}.html`),
          filename: `${pageName}.html`.chunks: [pageName],
          inject: true.minify: {
            html5: true.collapseWhitespace: true.preserveLineBreaks: false.minifyCSS: true.minifyJS: true.removeComments: false,}})); });return {
    entry,
    HtmlWebpackPlugins,
  };
};

const { entry, HtmlWebpackPlugins } = setMPA();

module.exports = {
  entry: entry,
  output: {
    path: path.join(__dirname, "dist"),
    filename: "[name][chunkhash].js",},plugins: [
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: "[name][contenthash:8].css",}).new OptimizeCSSAssetsPlugin({
      assetNameRegExp: /\.css$/g,
      cssProcessor: require("cssnano"),
    }),
  ].concat(HtmlWebpackPlugins),
  mode: "production"};Copy the code

Use the source map

Simply put, a Source map is an information file that stores location information. That is, for every position in the transformed code, there is the position before the transformation.

With it, when something goes wrong, the debugger displays the original code, not the converted code. This is certainly a great convenience for developers. You can upload Sourcemap to the error monitoring system when checking for problems online.

Source map Indicates the keyword

  • Eval: Use eval to wrap module code;
  • Source map: Generates a. Map file.
  • Cheap: does not contain column information.
  • Inline: Embed the. Map as the DataURI and do not generate a separate. Map file.
  • Module: contains the sourcemap of the loader.

The source map type

Webpack configuration is simple:

devtool: "source-map".Copy the code

Basic library separation

Separate some common files, such as the react and React-DOM base packages introduced through CDN, not into the bundle.

Using HTML – webpack – externals – the plugin

Installation:

yarn add html-webpack-externals-plugin --dev
Copy the code

Configuration:

const HtmlWebpackExternalsPlugin = require("html-webpack-externals-plugin");

new HtmlWebpackExternalsPlugin({
  externals: [{module: "react".entry: "https://11.url.cn/now/lib/16.2.0/react.min.js".global: "React"}, {module: "react-dom".entry: "https://11.url.cn/now/lib/16.2.0/react-dom.min.js".global: "ReactDOM",}]}),Copy the code

Use the built-in splitChunks

optimization: {
  splitChunks: {
    minSize: 0.cacheGroups: {
      commons: {
        test: /(react|react-dom)/,
        name: "commons".chunks: "all".minChunks: 1,},hello: {
      	test: /(hello)/,
        name: "hello".chunks: "all".minChunks: 1,},},},},// Import the generated JS file in HtmlWebpackPlugin
chunks: ["hello"."commons", pageName],
Copy the code

Chunks parameters:

  • Async Implements line separation for imported libraries asynchronously (default);
  • Initial synchronizes the incoming library for line separation.
  • All Line separation for all imported libraries (recommended).

Name: The name of the detached package. Test: Matches the packets to be separated. MinChunks: Sets the minimum number of references to two. MinuSize: The size of the separated packet volume.