Five core concepts of Webpack

  • Entry

    The entry indicates which file webPack starts packing as the entry point, analyzing and building the internal dependency diagram

  • Output

    The output indicates where the resource bundles packaged by WebPack are exported, and how they are named

  • Loader

    Loader allows Webpack to handle non-javascript files

  • Plugins

    Plug-ins can be used to perform a wider range of tasks. Plug-ins range from packaging optimization and compression to redefining environment variables

  • Mode

    The pattern instructs WebPack to use the configuration of the corresponding pattern

    options describe The characteristics of
    development Process.env.node_env is set to development to enable NamedChunkPlugin and namedModulesPlugin Enables code to be debugged locally in the runtime environment
    production Will process. The env. NODE_ENV value is set to production enabled FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccuerrenceOrderPlugin, SideEffectsFlagPlugin and UglifyJsPlugin An environment that optimizes code to run online

Second, the webpack5

  1. Install webpack

    npm i webpack webpack-cli -D

  2. Package files using NPX webpack

    Modify and package the webpack entry and exit paths using commands

npx webpack –entry ./src/main.js –output-path ./build

  1. Or configure the command to package.json
{
   "scripts": {
        "test": "echo "Error: no test specified" && exit 1",
        "build": "npx webpack --entry ./src/main.js --output-path ./build"
     },
}
Copy the code

Then use the command NPM run build to package

  1. Or create a webpack.config.js file in the root directory for more configuration

    const path = require("path"); Module.exports = {entry: './ SRC /index.js', // Export files can be relative paths output: {filename: 'build.js', path: Path. resolve(__dirname, 'dist') // absolute path}}Copy the code

    Then, configure it in package.json

    ​
      "scripts": {
        "test": "echo "Error: no test specified" && exit 1",
        "build": "webpack"
      },
    Copy the code

    You can customize the file name of webpack.config.js, for example, to lg.webpack.js, which needs to be configured in package.json:

      "scripts": {
        "test": "echo "Error: no test specified" && exit 1",
        "build": "webpack --config lg.webpack.js"
      },
    Copy the code

loader

CSS packaging

  1. Install the CSS – loader style – loader

    npm i css-loader -D

  2. Using the loader

    1. Webpack5 uses an inline loader
    import 'css-loader! . /css/login.css' import 'style-loader! css-loader! . /css/login.css'Copy the code
    1. Use a configuration file to configure the CSS

      Import the CSS file properly

      import '.. /css/login.css'Copy the code

      Configure the Loader in WebPack

      Module: {rules: [{test: /.css$/, // is a regular expression that matches the type of file we need to process. "Style-loader ", options:{}}, {loader:" CSS-loader ", options:{}}]}, // Use: ["style-loader","css-loader"]}]} use: ["style-loader","css-loader"]}Copy the code

      The loader is executed from bottom to top or from right to left

Less file packaging

  1. The installation

    npm i less less-loader -D

  2. Use less – loader

    Use: ["style-loader", "css-loader", "less-loader"]} use: ["style-loader", "css-loader", "less-loader"]}Copy the code

CSS, js compatible

CSS JS is compatible with different browser platforms

  1. Which browser platforms are compatible?

    By https://caniuse.com/usage-table different platforms to share.

  2. View the default compatible version

    If browserslist is installed by default in the node_modules folder,

    We can run NPX Browserslist directly to see the default compatible browser versions.

  3. How to configure

    • The first option is to configure it in package.json, which can be viewed via NPX browserslist

      {
           "browserslist": [
              ">1%",
              "last 2 version",
              "not dead"
            ]
      }
      Copy the code
    • The second:

      • Create a new configuration file in the root directory. Browserslistrc

        >1%
        last 2 version
        not dead
        Copy the code
      • View the configuration result by NPX browserslist

postcss

Postcss is a tool that uses JS plug-ins to transform styles. Postcss plug-ins check your CSS.

PostCSS is a tool that uses plug-ins to transform CSS. There are many great plug-ins such as Autoprefixer, CssNext, and CSS Modules. All the features listed above are implemented by the corresponding PostCSS plug-in. With PostCSS you need to combine it with a Webpack or parcel.

  1. The installation

    npm i postcss postcss-cli autoprefixer postcss-loader -D

  2. Use of the Autoprefixer plug-in

    autoprefixer

    This plugin prefixes CSS with browser prefixes in JAVASCRIPT based on browserslistrc compatibility conditions, eliminating the need to constantly write webKit code for compatibility.

  3. Use of postCSS-PRESET – ENV plugin set

    Such as: color: # 12345678; There are some browsers that are not compatible with the color value and cannot be prefixed by Autoprefixer, so you need to use other plug-ins to handle it.

    Install NPM I postCSs-env -d

  4. Configuration postcss

    • Method 1: Configure the PostCSS
    Use: ["style-loader", "css-loader", {loader: ["style-loader", "css-loader", {loader: "postcss-loader", options: { postcssOptions:{ plugins: [ //require("autoprefixer"), //require(' postCSs-preset -env') // postCSs-preset -env is a set of presets so can be simply 'postCSs-preset -env']}}}]}Copy the code

    Autoprefixer results:

    . The title {color: rgba (18,52,86,0.47059); transition: all .5s; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background: linear-gradient(to bottom, white, black); }Copy the code
    • Method 2: The use of PostCSS can be directly configured in the webpack configuration file
    Use: ["style-loader", "css-loader", {loader: {test: /. Less $/, // is a regular expression that matches the type of file we need to process. "postcss-loader", options: { postcssOptions:{ plugins: [ 'postcss-preset-env' ] } } }, "less-loader" ] }Copy the code

    If both CSS files and LESS files need to use PostCSS, the configuration needs to be repeated twice, resulting in code redundancy.

    Therefore, the following configuration can also be performed:

    • Method 3: PostCSS configuration file

      • Create files in the root directorypostcss.config.jsThe file name cannot be modified
      module.exports={
          plugins: [
              // require('postcss-preset-env')
              require('autoprefixer')
          ]
      }
      Copy the code
      • Webpack configuration file
        {
            test: /.css$/,
                use: ["style-loader","css-loader", "postcss-loader"]
        },
        {
            test: /.less$/,
                use: ["style-loader","css-loader","postcss-loader","less-loader" ]
        }
      Copy the code
  5. scenario

    • The code in the postcssTest. CSS file is intended to be processed by postCSs-loader, but after referencing postcssTest. CSS in login. CSS with @import, PostcssTest. CSS is not compatible.

      Page login <– import– login. CSS <– import– postcssTest. CSS

      /*login.css*/ @import './postcssTest.css'; .title{ color: #12345678; } /*postcssTest.css*/ .title { transition: all .5s; user-select: none; background: linear-gradient(to bottom, white, black); } /* 1, after login. CSS code, postcss-loader Login. CSS is not required to be processed by csS-loader. CSS is not required to be processed by CSS-loader. However, the postCSS-loader processing time has passed, so it will not be handed to postCSs-loader for processing 4, so the final result is not to do compatibility processing CSS file */Copy the code
    • Solution:

      { test: /.css$/, use: [ "style-loader", { loader: "Css-loader ", options:{importLoaders:1}}," postCSs-loader ",]},Copy the code

The image of packaging

Scene:

  • The image is referenced via the SRC attribute of the IMG tag
  • References images via THE URL attribute of CSS background
  1. The installation

    npm i file-loader -D

  2. The SRC attribute of the img tag references the use of the image

    • The first way

      // SRC /js/image.js function packImg(params) {// Create a container element const oElI = document.createElement('div') Const oImg = document.createElement('img') oimg.width = 400 // oimg.src = require('.. /image/01.jpg').default oElI.appendChild(oImg) return oElI } document.body.appendChild(packImg()) // src/index.js import  './js/image.js' // src/index.html <script src="./dist/build.js"></script>Copy the code

      Webpack configuration

      { test: /.(png|jpe? g|svg|gif)$/, use: [ "file-loader"] }Copy the code

      In Webpack 5, when an image is introduced through require, webpack returns an object when it is packaged. So require(‘.. /image/01.jpg’).default Gets the image address.

    • The second way

    If you don’t want to pass require(‘.. /image/01.jpg’).default Gets the image address and can add configuration options in webpack

    { test: /.(png|jpe? G | SVG | GIF) $/, use: {loader: file - "loader", the options: {esModule: false / / not to esModule}}}Copy the code
    • The third way

      If you don’t want to pass require(‘.. /image/01.jpg’).default Gets the image address. You can import image resources by using import

      // src/js/image.js import oImgSrc from '.. /image/02.jpg' function packImg(params) {// Create a container element const oElI = document.createElement('div') Const oImg = document.createElement('img') oimg.width = 400 // oimg.src = oImgSrc oeli.appendChild (oImg) return oElI } document.body.appendChild(packImg())Copy the code
    1. Setting the background image

      // src/js/image.js import oImgSrc from '.. /image/02.jpg' import '.. / CSS /img. CSS 'function packImg(params) {// Create a container element const oElI = document.createElement('div') Const oImg = document.createElement('img') oimg.width = 400 // oimg.src = require('.. /image/01.jpg').default // oImg.src = require('.. /image/01.jpg') oimg.src = oImgSrc oeli.appendChild (oImg) const oBgImg = document.createElement('div') oBgImg.className = 'bgBox' oElI.appendChild(oBgImg) return oElI } document.body.appendChild(packImg())Copy the code
      /* src/css/img.css */ .bgBox{ width: 240px; height: 310px; border: 1px solid #000; background-image: url('.. /image/03.jpg'); }Copy the code

      Webpack configuration file

      { test: /.css$/, use: [ "style-loader", { loader: "css-loader", options:{ importLoaders:1, esModule: false } }, "postcss-loader", ] }, { test: /.(png|jpe? g|svg|gif)$/, use: ["file-loader"] },Copy the code

      In Webpack5, whether file-loader is used to process image resources imported by SRC or CSS-loader is used to process background-image resources imported by URL, image resources are packaged into an esModule resource. The specific image address must be obtained via.default.

      So: to package the image address in CSS-Loader, add the options configuration item **esModule: false**

    2. Process the path and file name of the image after it is packaged

      { test: /.(png|jpe? g|svg|gif)$/, use: { loader: "file-loader", options: { name: '[name].[hash:6].[ext]', outputPath:'img' } } }Copy the code

      [name] indicates that the original file name is used for packaging

      [hash:6] Concatenates 6-bit hash characters to ensure that the address of the image is unique

      [ext] preserves the extension

      OutputPath The packed path dist/img/*.jpg

      Options can also be abbreviated as:

      { test: /.(png|jpe? g|svg|gif)$/, use: { loader: "file-loader", options: { name: 'img/[name].[hash:6].[ext]' } } }Copy the code
    3. url-loader

      1. Url-loader will directly package image resources into files in the format of Base64 URI, which will reduce the number of file requests, but increase the volume of files and affect the speed of first-screen rendering

      2. File-loader copies resources to a specified directory and requests resources separately to increase the number of requests

      3. File-loadeer can be called in url-loader

      { test: /.(png|jpe? g|svg|gif)$/, use: { loader: "url-loader", options: { name: 'img/[name].[hash:6].[ext]', limit: 25 * 1024 } } },Copy the code

      Limit: 25 * 1024 Files larger than 25K are copied in file-loader format and packed separately to the dist directory

      For files smaller than 25K, use url-loader to package images directly into main.js.

    4. Asset Image package

      In WebPack 5, images can be packaged directly using the built-in asset, without downloading file-loader or url-loader

      Asset packaging:

      • Asset/Resource is equivalent to file-loader’s packaging process

        The generator configures the address and filename after packaging and does not need to add them before [ext].[ext] Webpack5 adds them by default

        { test: /.(png|jpe? g|svg|gif)$/, type: 'asset/resource', generator: { filename: "img/[name].[hash:4][ext]" } },Copy the code
      • Asset /inline corresponds to the urL-loader packaging process

        { test: /.(png|jpe? g|svg|gif)$/, type: 'asset/inline' },Copy the code
      • Asset/Source is equivalent to the raw-loader packaging process

      • asset

        { test: /.(png|jpe? g|svg|gif)$/, type: 'asset', generator: { filename: "img/[name].[hash:4][ext]" }, parser: { dataUrlCondition: { maxSize: 25 * 1024 } } },Copy the code
    5. Asset packs font ICONS

      { test: /.(ttf|woff? 2|eot)$/, type: 'asset/resource', generator: { filename: "font/[name].[hash:4][ext]" }, }Copy the code

Configure plug-ins in WebPack

  1. The clean – webpack – plugins plugin

    • Install NPM I clean-webpack-plugin -d

    • The clean-webpack-plugin can clean up the last packing result each time you pack

    • Use: WebPack to configure the plug-in

      const { CleanWebpackPlugin } = require('clean-webpack-plugin')
      ​
      module.exports = {
          ...
           plugins: [
               new CleanWebpackPlugin()
           ]
       }
      Copy the code
  2. HTML – webpck – plugin plug-in

    • Install NPM I html-webpck-plugin-d

    • Html-webpck-plugin can automatically generate the index.html file, but the body tag in the automatically generated index.html file is an empty tag. When we use vue or React framework for development, The developed page is mounted to the

      tag under the body tag of the index.html page. Therefore, we can manually create an index.html page as a template for htML-webpck-plugin to package HTML files.

      <! -- /public/index.html borrow vue scaffolding to create project generated index.html code --> <! DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta Name ="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="<%= BASE_URL %> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <noscript> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <div id="app"></div> <! -- built files will be auto injected --> </body> </html>Copy the code
    • configuration

      1. Use htmlWebpackPlugin to pass the template parameter to generate the master file for the HTML file.

      2. Use webPack’s DefinePlugin to pass the constant parameter BASE_URL to the generated index.html file.

        <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <! <link rel="icon" href="./favicon.ico">Copy the code
      3. Specific configuration

      const htmlWebpackPlugin = require('html-webpack-plugin'); Const {DefinePlugin} = require("webpack") // copy public static resources favicon. Icon const CopyPlugin = require('copy-webpack-plugin'); { plugins: [ new CleanWebpackPlugin(), new htmlWebpackPlugin({ title: "html-webpack-plugin", template: './public/index.html' }), new DefinePlugin({ BASE_URL: '"./"' }), new CopyPlugin({ patterns: [ { from: ". / public, "globOptions: {ignore: [' * * / index in HTML '] / / * * / said in the current public directory lookup}},]]}})Copy the code

babel

JSX TS ES6+ syntax is not supported by the browser, we can use Babel to handle the syntax is not supported by the browser, to achieve JS compatibility

  1. Install Babel

    npm i @babel/core -D

  2. The test code

    // SRC /index.js const title = "front" const fn = () => {console.log('title: ', title); } fn()Copy the code
  3. To use Babel on the command line, install @babel/ CLI

    npm i @babel/cli -D

    npx babel src/index.js --out-dir build
    Copy the code

    SRC /index.js is the same file generated under build, so @babel/core converts the source code, not the JS syntax.

  4. Install the concrete conversion kit

    • @babel/plugin-transform-arrow-functions Handle arrow functions

      npm i @babel/plugin-transform-arrow-functions -D

    npx babel src/index.js --out-dir build --plugins=@babel/plugin-transform-arrow-functions
    Copy the code

    Found that the arrow function was converted to a normal function

    Const title = "front "; const fn = function () { console.log('title: ', title); }; fn();Copy the code
    • Babel /plugin-transform-block-scoping transform block scope

      npm i @babel/plugin-transform-block-scoping -D

      npx babel src/index.js --out-dir build --plugins=@babel/plugin-transform-block-scoping 
      Copy the code

      You can see that const is converted to var

      Var title = "front-end "; var fn = () => { console.log('title: ', title); }; fn();Copy the code
    • Configuration webpack

      {
          test: /.js$/,
              use: {
                  loader: "babel-loader",
                      options: {
                          plugins: [
                              '@babel/plugin-transform-arrow-functions',
                              '@babel/plugin-transform-block-scoping'
                          ]
                      }
              }
      }
      Copy the code
  5. The default @ Babel/preset – env

    It can be found that if we need many toolkits to convert different grammers, development can be very troublesome, so we can use @babel/preset-env to convert grammers, which contains many toolkits and doesn’t need to be installed separately.

    • The installation

      npm i @babel/preset-env -D

      npx babel src/index.js --out-dir build --presets=@babel/preset-env 
      Copy the code

      It can also help us transform successfully:

      "use strict"; Var title = "front-end "; var fn = function fn() { console.log('title: ', title); }; fn();Copy the code
  6. Configuration webpack

    • Install Babel – loader

      npm i babel-loader -D

      {test: /.js$/, use: {loader: "babel-loader", options: {presets: [// Preset can be multiple '@babel/ env']}}}Copy the code
    • @babel/preset-env will process JS code based on the browser version configured in.browserlistrc

    • You can also configure the browser version to handle compatibility issues in the following ways

      {
          test: /.js$/,
              use: {
                  loader: "babel-loader",
                      options: {
                          presets: [
                              [
                                  '@babel/preset-env',
                                  { targets: 'chrome 91' }
                              ]
                          ]
                      }
              }
      }
      Copy the code

      At this point, Chrome 91 supports const and arrow functions, so the syntax for const and arrow functions is not converted when packaged.

  7. ** The common Babel configuration mode **

    • Create a new file babel.config.js in the root directory

      module.exports = {
          presets: [
              '@babel/preset-env'
          ]
      }
      Copy the code
    • Wepback configuration

        {
            test: /.js$/,
            use: ["babel-loader"]
        }
      Copy the code

polyfill

It’s not enough to just use Babel for ES5 conversion when a web page needs to be compatible with a lower version, such as when IE doesn’t support new features like Promise

Babel contains a polyfill library. This library contains regenerator and Core-js.

This library will simulate a complete ES2015+ environment.

This means you can use new built-in syntaxes like Promise or WeakMap, Static methods such as array. from or Object.assign and instance methods such as array.prototype. includes and generator functions.

Before WebPack 5, Webpack integrated Ployfill, but if ployfill is not used, the packaging speed will be affected, so In WebPack 5, WebPack separately extracted Ployfill. So ployFill needs to be configured manually.

  1. Install NPM i@babel /polyfill –save

    It is not recommended to install @babel/polyfill after Babel7.

    npm i core-js regenerator-runtime

  2. configuration

    • babel.config.js
    Module. exports = {presets: [['@babel/preset-env', {// false: default, not to use ployfill for current JS processing // preset: Ployfill according to the new syntax used in the user source code. The default is corejs 2, and the installed version is corejs 3, so corejs: 3 is required to specify // entry: UseBuiltIns: 'usage', corejs: 3}]]}Copy the code
    • Webpack configuration

       {
           test: /.js$/,
           use: ["babel-loader"],
           exclude: /node_modules/
       }
      Copy the code

Webpack hot update

  1. Hot updates are implemented by configuring –watch in package.json

    "scripts": {
        "test": "echo "Error: no test specified" && exit 1",
        "build": "webpack --config lg.webpack.js --watch"
      },
    Copy the code
  2. Hot update is configured in the wepback configuration file

    Module. exports = {mode: 'development', watch: true... }Copy the code
  3. Dev-server implements hot updates

    Disadvantages of the first two methods:

    • All source code is recompiled with each update
    • File reads and writes are required for each successful compilation (package to generate dist directory)
    • Need to use VScode plug-in Live Server real-time update, cannot achieve local update
    1. The installation

      npm i webpack-dev-server -D

    2. configuration

      • package.json

          "scripts": {
            "test": "echo "Error: no test specified" && exit 1",
            "build": "webpack --config lg.webpack.js",
            "serve": "webpack serve --config lg.webpack.js"
          },
        Copy the code
      • Webpack configuration

        Module. exports = {mode: 'development', watch: false, // set devtool: false,}Copy the code

webpack middleware

Webpack-dev-middleware is a wrapper that can pass Webpack-processed files to a server. Webpack-dev-server uses it internally, but it can also be used as a separate package for more customization to meet more requirements.

Module hot replacement – HMR

Hot Module Replacement (or HMR) is one of the most useful features webPack provides. It allows various modules to be updated at run time without a complete refresh.

  1. Configuration webpack

    {
        devServer: {
            hot: true
        },
            
    }
    Copy the code
  2. The title. Js module

    Module. exports = 'front-end development' console.log('title.js module request ');Copy the code
  3. In the index.js entry file

    Import './js/title.js' if (module.hot) {module.hot.accept(['./js/title.js'], () => {console.log('title.js module updated! '); })}Copy the code

The react project

Use Webpack to build react project and implement hot update HMR

  1. Install JSX build presets

    npm i @babel/preset-react react react-dom -D

  2. Install the React hot update plug-in

    npm i @pmmmwh/react-refresh-webpack-plugin react-refresh -D

  1. configuration

    • Webpack configuration

      const ReactRefreshPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); {module: {rules: [{// configure JSX loader test: /. JSX?$/, use: ["babel-loader"], exclude: /node_modules/}}, plugins: [ new ReactRefreshPlugin(), ] }Copy the code
    • Configure the Babel. Config. Js
    Module.exports = {presets: [['@babel/preset-env',], ['@babel/preset-react' // preset]], plugins: ['react-refresh/babel'], }Copy the code

Vue project

  1. The installation

    npm install vue-template-compiler -D

    npm install vue

  2. Use vue-loader@15 version

    npm i vue-loader@15 -D

  3. The test code

    <! -- src/App.vue --> <template> <div class="example">{{ msg }}</div> </template> <script> export default { data () { return { msg: 'Hello world! ' } } } </script> <style> .example { color: #00ff22; } </style>Copy the code
    // src/index.js import './js/title.js' import Vue from 'vue' import App from './App.vue' if (module.hot) { Module.hot.accept (['./js/title.js'], () => {console.log('title.js module updated! '); }) } new Vue({ render: h => h(App) }).$mount('#app')Copy the code
  4. configuration

    Webpack configuration vue – loader

    Const VueLoaderPlugin = require('vue-loader/lib/plugin') // Module: {rules: [{test: /.vue$/, use: ["vue-loader"], exclude: /node_modules/ } ] }, plugins: [ new VueLoaderPlugin() ]Copy the code

Some configurations in WebPack

  1. output.publicPath

    • PublicPath refers to the reference path of the script tag SRC in index.html after packaging.
    • If devServer is enabled, publicPath: domain name + publicPath + filename
  2. devserver

    • Devserver. publicPath Indicates the path in which the local service is enabled

      Such as: Local services can normally be accessed through http://localhost:8080. If devServer.publicPath is set to /lg, local services need to be accessed through http://localhost:8080/lg. PublicPath and devServer.publicPath must be set to the same value.

    • Devserver. contentBase: if our packaged resource depends on another resource, tell us where to find it.

      Path.resolve (__dirname, ‘public’)

    • DevServer. WatchContentBase: monitoring the change of the public file, the default is false

    • Devserver. hotOnly: If an error is reported in one component, the display of other components will be affected. The default value is false

    • Devserver. port: indicates the port number of the local server

    • Devserver. open: indicates whether the page is automatically opened. The default value is false

    • DevServer.com press: whether the main.js loaded by the browser needs to be compressed. The default value is false

    • DevServer. HistoryApiFallback: when a browser display a page loading failure time, by default, false to true, shows that the index after loading failure. HTML

    • Devserver. proxy: sets the proxy

      Proxy: {/ / axios sends a request path for/API user / / http://localhost:4000/api/user / / https://api.github.com/api/user '/ API: { target: 'https://api.github.com', pathRewrite: { '^/api': "" }, changeOrigin: true } }Copy the code
  3. resolve

    The components/index. Js, components/Home. JSX

    When importing a file:

    • Import Home from ‘./components’, which by default looks for index.js under components

    • If you import Home from ‘./components/Home’,wepback will look for home.js or home.json by default

      Resolve: ['js', 'json', '.ts', 'JSX '], // Alias: {"@": path.resolve(__dirname, 'src') } }Copy the code