preface

This article sorted out the webpack front-end resource building tools and static module packer knowledge summary, if you have different views on the answer to the students welcome to add discussion in the comment section, of course, there are questions, also welcome to point out in the comment section.

Refer to the silicon Valley Webpack tutorial video for documentation

Introduction to WebPack

1. What is Webpack?

(a) WebPack is a front-end resource building tool.

  • Some resource files like the front end (ES6, LESS, Sass, Vue, etc.) need to be parsed and escaped by various gadgets before they can be used, and then webPack, a large build tool containing these gadgets, is used to process these files.

(2) Webpack is a static module packer.

//index.js file (module)
import $ from 'jquery'; (Small module)import './index.less'; (Small module) $('#title').click(() = >{$('body').css('backgroundColor'.'deepPink');
})
Copy the code
  1. Index.js imports jquery and less files (called modules) and forms a chunk.
  2. Then the chunk is processed, such as less compiled into CSS, jquery compiled into JS (syntax recognized by the browser), these processing processes are called packaging
  3. The packaged output file is called bundle.js

2. Five core concepts of Webpack

(1) Entry

Indicates which file webpack starts packing for the entry

(2) Output

Indicate where and how to name the output of webpack-packed resources

(3) Loader (escape)

Enable WebPack to process and parse non-JS files (WebPack only understands JS)

(4) Plugin

Let WebPack support more functionality, equivalent to extending functionality, such as packaging optimization and compression, redefining variables in the environment, and so on

  • Clear the contents of the original dist file ——clean-webpack-plugin before packaging
  • Can automatically package generated HTML files and automatically import the packaged results —-html-webpack-plugin
  • Etc.

(5) Mode

  • Development mode: Enables code to run locally
  • Production: Gets code production up and running

Initialize the project

Initial Configuration

NPM init -y for initialization

NPM install webpack webpack-cli -d Install Webpack on the local PC

Compile operation

Operation instruction:

  • Webpack. / SRC /index.js -o./build/ build.js –mode=development

Webpack will start packing with a./ SRC /index.js entry file and output it to the./build/ built-in environment, which is the development environment

  • Production environment: webpack. / SRC /index.js -o./build/ build.js –mode=production

The packaged resources are compressed and smaller than the development environment

conclusion
  • Webpack can handle JS/JSON resources, not CSS/IMG
  • Production and development environments modularize ES6 into modules that browsers recognize
  • The production environment has one more compressed JS code than the development environment.

4. Package resources

(1) Package style resources
/* Webpack.config. js Webpack configuration file: tells webpack what to do (when you run the webpack directive, the configuration inside will be loaded) all build tools run on the NodeJS platform. * /// resolve the method used to concatenate absolute paths
const { resolve } = require('path');
​
module.exports = {
  / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- webpack configuration
  entry: './src/index.js'.// Import file
  output: {  / / output
    filename: 'built.js'.// Output the file name
    path: resolve(__dirname, 'build')  // The output path __dirname nodejs variable, representing the absolute directory path of the current file
  },
  // Loader configuration
  module: {
    rules: [
      // Different files must be processed by different Loaders
      {
        test: /.css$/,
        use: [
          'style-loader'.'css-loader'] {},test: /.less$/.// Which files to match
        use: [      Loaders in use are executed in the following order: from back to front (less-> CSS ->style)
          'style-loader'.// Create a style tag, insert the js style resource, add it to the head to take effect
          'css-loader'.// Turn the CSS file into a common module and load the js file with the style string
          'less-loader']]}},// Plugins are configured
  plugins: []./ / mode model
  mode: 'development'.// Development mode
  // mode: 'production'
}
Copy the code
(2) Package HTML resources
/* loader: 1. Plugins: 1. Download 2. Introduce plug-in (constructor) 3. Use (call function) */
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
​
module.exports = {
  entry: './src/index.js'.output: {
    filename: 'built.js'.path: resolve(__dirname, 'build')},module: {
    rules: []},plugins: [
    // html-webpack-plugin
    // Function: creates an empty HTML by default, automatically importing all the resources (JS/CSS) that are packaged as output.
    // Requirements: Need a structured HTML file
    new HtmlWebpackPlugin({
      // Copy the file './ SRC /index.html' and automatically import all the resources (JS/CSS) that are packaged as output.
      template: './src/index.html'})].mode: 'development'
};
Copy the code
(3) Package picture resources
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
​
module.exports = {
  entry: './src/index.js'.output: {
    filename: 'built.js'.path: resolve(__dirname, 'build')},module: {
    rules: [{test: /.less$/.// To use multiple loaders, use use
        use: ['style-loader'.'css-loader'.'less-loader'] {},test: /.(jpg|png|gif)$/.// To use a loader, you must download url-loader file-loader
        loader: 'url-loader'.// Image resource problem: img images in HTML cannot be processed by default
        options: {
          // Images smaller than 8KB will be base64 processed
          // Advantages: reduce the number of requests (reduce server stress)
          // Disadvantages: Larger image size (slower file request)
          limit: 8 * 1024.// Problem: Because url-loader uses ES6 modular parsing by default, htMl-loader imports images by commonJS.
          [object Module]
          // Resolve: Disable ES6 modularization of urL-loader and use CommonJS parsing
          esModule: false.// Rename the image,[hash:10] takes the first 10 bits of the hash of the image, and [ext] takes the original extension of the file
          name: '[hash:10].[ext]'}}, {test: /.html$/.// Handle the IMG image of the HTML file (responsible for importing img so that it can be processed by urL-loader)
        loader: 'html-loader'}},plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'})].mode: 'development'
};
Copy the code
(4) Pack other resources
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
​
module.exports = {
  entry: './src/index.js'.output: {
    filename: 'built.js'.path: resolve(__dirname, 'build')},module: {
    rules: [{test: /.css$/,
        use: ['style-loader'.'css-loader']},// Package other resources such as iconfont ICONS (resources other than HTML/JS/CSS resources)
      {
        // Exclude CSS /js/ HTML resources
        exclude: /.(css|js|html|less)$/,
        loader: 'file-loader'.options: {
          name: '[hash:10].[ext]'}}},plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'})].mode: 'development'
};
Copy the code
(v) Other common Loaders

Script conversion compilation:

  • Babel-loader: ES6+ code is loaded and escaped to ES5 using Babel before being parsed by the browser

  • Typescript-loader: loads typescript script files

Framework:

  • Vue-loader: load and escape vue components, extract the logic code Script, style code style, and HTML template, and then hand them to the corresponding loader for processing
(6) devServer hot update
  • Webpack-dev-server starts a service

  • The browser connects to the server through websocket

  • Webpack listens for changes to the source file, triggering a webPack recompile when the developer saves the file. Each compilation generates hash values, JSON files that have changed the module, and JS files that have changed the module code. After compiling, push the current compiled hash stamp to the client through the socket

  • The websocket on the client listens for the hash stamp pushed by a file change and compares it with the last one. If they are consistent, the cache is removed. In case of inconsistency, the server obtains the latest resources through Ajax and JSONP

const { resolve } = require('path');
​
module.exports = {
  entry: './src/index.js'.output: {
    filename: 'built.js'.path: resolve(__dirname, 'build')},module: {}
  plugins: [].mode: 'development'.// devServer: to automate (automatically compile, automatically open browser, automatically refresh browser ~~)
  // Features: only packages are compiled in memory, with no output
  // Start devServer with NPX webpack-dev-server
  devServer: {
    contentBase: resolve(__dirname, 'build'),   // Project build path
    compress: true.// Start gzip compression
    port: 3000./ / the port number
    open: true  // Automatically opens the local default browser}};Copy the code
Development Environment Configuration
NPX webpack-dev-server will only compile the package in memory, no output */const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
​
module.exports = {
  entry: './src/js/index.js'.output: {
    filename: 'js/built.js'.path: resolve(__dirname, 'build')},module: {
    rules: [
      // Loader configuration
      {
        // Process less resources
        test: /.less$/,
        use: ['style-loader'.'css-loader'.'less-loader'] {},// Process CSS resources
        test: /.css$/,
        use: ['style-loader'.'css-loader'] {},// Process image resources
        test: /.(jpg|png|gif)$/,
        loader: 'url-loader'.options: {
          limit: 8 * 1024.name: '[hash:10].[ext]'.// Disable es6 modularization
          esModule: false.outputPath: 'imgs'}}, {// Process img resources in HTML
        test: /.html$/,
        loader: 'html-loader'
      },
      {
        // Process other resources
        exclude: /.(html|js|css|less|jpg|png|gif)/,
        loader: 'file-loader'.options: {
          name: '[hash:10].[ext]'.outputPath: 'media'}}},plugins: [
    // Plugins are configured
    new HtmlWebpackPlugin({
      template: './src/index.html'})].mode: 'development'.devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true.port: 3000.open: true}};Copy the code

5. Basic configuration of webpack production environment

With CSS
  • Extract CSS into a separate file

Mini-css-extract-plugin combines a.css and B.css extracts into a separate file main.js

  • CSS compatibility handling (some styles cannot be resolved in browsers)

Postcss-loader and PostCSs-PRESET -env plug-ins

  • Compress CSS

optimize-css-assets-webpack-plugin

Deal with js
  • Js syntax check

    • Eslint-loader eslint eslint-config-airbnb-base (syntax style) eslint-plugin-import
    • Exclude: /node_modules/ exclude: /node_modules/
    • Options: {fix:true}
  • Js Compatibility processing

babel-loader @babel/core @babel/preset-env @babel/polyfill core-js

  • Js and HTML code compression
plugins: [
    new HtmlwebpackPlugin({
        template: './ src /index.html'.minify: {  // set minify to compress htM1 code
            collapsewhitespace: true.// Remove whitespace
            removeComments: true// Remove comments}})].mode: 'production'  // Webpack production mode, with its own uglilify. js, can achieve JS code compression
Copy the code
Production Environment Configuration
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
​
// Define the nodeJS environment variable: Determines which environment to use browserslist
process.env.NODE_ENV = 'production';
​
/ / reuse loader
const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    // You also need to define browserslist in package.json
    loader: 'postcss-loader'.options: {
      ident: 'postcss'.plugins: () = > [require('postcss-preset-env') (the)]}}];module.exports = {
  entry: './src/js/index.js'.output: {
    filename: 'js/built.js'.path: resolve(__dirname, 'build')},module: {
    rules: [{test: /.css$/,
        use: [...commonCssLoader]
      },
      {
        test: /.less$/,
        use: [...commonCssLoader, 'less-loader']},/* Normally, only one loader can process a file. When a file is to be processed by multiple Loaders, it is important to specify the order in which loader executes: esLint before Babel */
      {
        // In package.json eslintConfig --> Airbnb
        test: /.js$/,
        exclude: /node_modules/.// Priority execution
        enforce: 'pre'.loader: 'eslint-loader'.options: {
          fix: true}}, {test: /.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'.options: {
          presets: [['@babel/preset-env',
              {
                useBuiltIns: 'usage'.corejs: {version: 3},
                targets: {
                  chrome: '60'.firefox: '50'}}]]}}, {test: /.(jpg|png|gif)/,
        loader: 'url-loader'.options: {
          limit: 8 * 1024.name: '[hash:10].[ext]'.outputPath: 'imgs'.esModule: false}}, {test: /.html$/,
        loader: 'html-loader'
      },
      {
        exclude: /.(js|css|less|html|jpg|png|gif)/,
        loader: 'file-loader'.options: {
          outputPath: 'media'}}},plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/built.css'
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html'.minify: {
        collapseWhitespace: true.removeComments: true}})].mode: 'production'
};
Copy the code

6. Webpack performance optimization

Development environment performance optimization
  • Optimize packaging build speed

    When modifying the CSS file, the JS file is repackaged

    • HMR: Hot Module replacement. When a module changes, only this module is packaged

    • Style files: can use HMR function: because style-loader internally implement ~ JS file: can not use HMR function by default --> need to modify js code, add code that supports HMR function note: HMR function can only handle other files that are not entry JS files. HTML files: the HMR function is disabled by default. HTML files cannot be hot updated ~ (don't do HMR, HTML files are the main file and contain all references)'./src/js/index.js'.'./src/index.html'].Copy the code
    • mode: 'development'.devServer: {
        contentBase: resolve(__dirname, 'build'),
        compress: true.port: 3000.open: true.hot: true// Enable the HMR function - when the Webpack configuration is changed, the new configuration must be restarted in order to take effect - resolved the style file
      }
      Copy the code
      if (module.hot) {// Once module.hot is true, HMR is enabled. --> Make the HMR function code work
        module.hot.accept('./print.js'.function() { // ---- solves the js file
          // The print.js method listens for changes in the print.js file, and when changes occur, other modules are not repackaged and built.
          // The following callback functions are executed
          print();
        });
      }
      Copy the code
  • Optimized code debugging

    • Source-map —– can locate code errors

    • devServer: {
        contentBase: resolve(__dirname, 'build'),
        compress: true.port: 3000.open: true.hot: true
      },
      devtool: 'eval-source-map' // Just add this line of code
      //eval-cheap-module-souce-map
      Copy the code
      source-map: A technique that provides source-to-build-after code mapping (if the build-after code goes wrong, By mapping can track source code error) [inline - | hidden - | eval -] [nosources -] [being - [module -]] source - the map source - the map: Precise information outside the error code and error source location inline - source - the map: inline, will cause the file is too large, is not recommended Only generate an inline source - precise information map error code and error source location hidden - source - the map: External error code error cause, but no error location can trace the source code error, only after the built code error location eval-source-map: Nosource-source-map: external error code exact information, but nosource code exact information: The module will add the loader's source map to the inline and external source map. (eval>inline>cheap>...) (eval>inline>cheap>...) Eval-cheap-souce-map Eval-source-map debugging is more friendly souce-map cheap-module-souce-map cheap-source-map Debug more friendly/eval-cheap-module-souce-map performance can be best done Inline makes the code bigger, so in a production environment you don't have to inline nosource-source-map to hide all hidden-source-map to hide only the source code, The post-build code error message is suggested in two ways --> source-map/cheap-module-souce-mapCopy the code
Production environment performance optimization
  • Optimize packaging build speed

    • oneOf

    • Babel cache

    • Multi-process packaging

      Enable multi-process packaging. Process startup takes about 600ms and process communication is also overhead. Multi-process packaging is required only if the work takes a long timeCopy the code
    • externals

      Disallow some modules to be packed in

      Mode: 'production', externals: {// reject jQuery to be packaged in jQuery: 'jQuery'}Copy the code
    • dll

  • Optimize the performance of code execution

    • Cache (hash – chunkhash – contenthash)

    • Tree Shaking —– Remove useless code

      2. Enable production environment effects: Reduce code volume in package.json configure "sideEffects": Problem: it is possible to kill "sideEffects" in CSS / @babel/polyfill files: ["*.css", "*.less"] This will preserve CSS, less filesCopy the code
    • code split

      // Single entry -- single page
      // entry: './src/js/index.js',
      entry: {---- multiple pages// Multiple entries: There is one entry, and the final output has a bundle
        index: './src/js/index.js'.test: './src/js/test.js'
      },
      Copy the code
      /* 1. The node_modules code can be packaged as a separate chunk of the final output 2. Automatic analysis of multi-entry chunks, whether there are public files. If so, it will be packaged into a single chunk */
      optimization: {
        splitChunks: {
          chunks: 'all'}},mode: 'production'
      Copy the code
      //index.js
      /* Dynamic import syntax: can package a file separately (i.e. Test file separately) */
      import(/* webpackChunkName: 'test' */'./test')
        .then(({ mul, count }) = > {
          // The file is successfully loaded ~
          // eslint-disable-next-line
          console.log(mul(2.5));
        })
        .catch(() = > {
          // eslint-disable-next-line
          console.log('File load failed ~');
        });
      Copy the code
    • Lazy loading/preloading

      console.log('index.js file loaded ~');
      ​
      // import { mul } from './test';document.getElementById('btn').onclick = function() {
        // Lazy loading ~ : files are loaded only when they are needed ~ ---- but when a module is used and the module is very large, the loading will be slow
        // Prefetch: js files will be loaded in advance before being used. When used, the cache will be read ---- poor compatibility
        // Normal loading can be considered parallel loading (multiple files are loaded at the same time)
        // Prefetch: Wait until other resources are loaded and the browser is free, then secretly load the resources
        import(/* webpackChunkName: 'test', webpackPrefetch: true */'./test').then(({ mul }) = > {
          console.log(mul(4.5));
        });
      };
      Copy the code
    • PWA Progressive Web development application (accessible offline)

    When offline, resources are obtained from serviceWorker and CacheStorage

    workbox --> workbox-webpack-plugin
    
    plugins: [
        new WorkboxWebpackPlugin.GenerateSW({
            2. Delete the old ServiceWorker and generate a Serviceworker profile ~ */
            clientsClaim: true.skipWaiting: true})].// Register the serviceWorker in index.js
    // Handle compatibility issues
    if ('serviceWorker' in navigator) {
      window.addEventListener('load'.() = > {
        navigator.serviceWorker
          .register('/service-worker.js')
          .then(() = > {
            console.log('Sw registered successfully ~');
          })
          .catch(() = > {
            console.log('SW registration failed ~');
          });
      });
    }
    Copy the code

conclusion

Feel good writing, helpful to you, you can share with people around you, the more you share knowledge, do not be stingy

Follow-up update front-end other knowledge summary, please pay attention to me, tidy up, share with you, we learn front-end together