• Webpack 4.X Combat (1) : Have a comprehensive understanding of Webpack and core concepts

  • Build a simple front-end project from scratch

  • Webpack4.x Actual combat (3) : 24 points summary of enterprise SPA (1)

  • Webpack4.x actual combat (IV) : 24 points summary of enterprise SPA (ii)

1. Differentiate development/production environment Webpack-merge

  • Follow the Principle of Non-repetition (DRY)

    Webpack configuration requires a common configuration, a dev configuration, and a PROd configuration

    This is integrated through the Webpack-Merge package

  • There are some tools that don’t make sense when developing the environment, such as compressed code, filename hashing, split code, etc.

  • The installation and configuration are as follows

    NPM [email protected] - I DCopy the code
    // webpack/webpack.common.js
    
    
    const path = require('path');
    const CleanWebpackPlugin = require('clean-webpack-plugin');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
      entry: {
        app: './src/index.js'
      },
      plugins: [
        new CleanWebpackPlugin(['dist']),
        new HtmlWebpackPlugin({
          title: 'Production'
        })
      ],
      output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')}};Copy the code
    // webpack/webpack.dev.js
    
    
    const merge = require('webpack-merge');
    const common = require('./webpack.common.js');
    
    module.exports = merge(common, {
      devtool: 'inline-source-map',
      devServer: {
        contentBase: './dist'}});Copy the code
    // webpack/webpack.prod.js
    
    
    const merge = require('webpack-merge');
    const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
    const common = require('./webpack.common.js');
    
    module.exports = merge(common, {
      plugins: [
        new UglifyJSPlugin()
      ]
    });
    Copy the code
    // package.json configures NPM script {"scripts": {
        "start": "webpack-dev-server --open --config webpack/webpack.dev.js"."build": "webpack --config webpack/webpack.prod.js"}}Copy the code

2. Configure source Map

  • The source map represents a mapping of resources and is used to locate errors in code

  • Recommended in the development environment

    {
        devtool: "cheap-module-eval-source-map"
    }
    Copy the code
  • Recommended in the production environment

    {
        devtool: false
    }
    Copy the code
  • For details, see official

Tree Shaking

  • Function:

    • Clean up useless code in JS
  • Tree Shaking is automatically enabled if the following conditions are met:

    • In webPack 4.X production mode

    • When coding, follow ES6 modular syntax (require is invalid)

    • Do not compile ES6 modules at compile time

    //.babelrc is configured as follows {"presets": [["@babel/preset-env",
                {
                    "modules": false}}]]Copy the code
  • ES6 modular syntax practices in production mode:

    • Practice one:

      // a.js file const dict ='dict';
      const dictMedia = 'dictMedia';
      
      export default {
          dict,
          dictMedia
      };
      Copy the code
      // import the a.js file import dicts from'/a'; console.log(dicts); // a.js file dict and dictMedia are packedCopy the code
    • Practice 2:

      // a.js file const dict ='dict';
      const dictMedia = 'dictMedia';
      
      export default {
          dict,
          dictMedia
      };
      Copy the code
      // import the a.js file import dicts from'/a'; console.log(dicts.dict); // Dict in the a.js file is packaged; DictMedia is not packagedCopy the code
    • Practice 3:

      // a.js file const dict ='dict';
      const dictMedia = 'dictMedia';
         
      export {
          dict,
          dictMedia
      };
      Copy the code
      // import {dict, dictMedia} from'/a'; console.log(dict, dictMedia); // Dict in the a.js file is packaged; DictMedia is not packagedCopy the code
    • Practice the four:

      // a.js file const dict ='dict';
      const dictMedia = 'dictMedia';
      
      export {
          dict,
          dictMedia
      };
      Copy the code
      // Import the a.js file import {dict} from'/a'; console.log(dict); // Dict in the a.js file is packaged; DictMedia is not packagedCopy the code

4. Increase the Scope as of 1997

  • An overview of the

    • Scope collieries make webPack code files smaller and faster

    • In production mode of Webpack4, Scope is enabled by default

    • Webpack3 launched features that need to be manually opened for a rough explanation here

  • Principle:

    • Analyze the dependencies between modules and merge the separated modules into a function as much as possible

    • As long as there is no code redundancy

  • Whether to enable Scope contrast

    / / util. Js fileexport default 'Hello,Webpack';
    Copy the code
    // import STR from main.js'./util.js';
    console.log(str);
    Copy the code
    // If the Scope is not enabled, the repackage will be as follows:function (module, __webpack_exports__, __webpack_require__) {
        var __WEBPACK_IMPORTED_MODULE_0__util_js__ = __webpack_require__(1);
        console.log(__WEBPACK_IMPORTED_MODULE_0__util_js__["a"]); }),function (module, __webpack_exports__, __webpack_require__) {
        __webpack_exports__["a"] = ('Hello,Webpack'); })]Copy the code
    // Start the Scope as follows [(function (module, __webpack_exports__, __webpack_require__) {
        var util = ('Hello,Webpack'); console.log(util); })]Copy the code

5. Start the development service hot replacement HMR

  • Full name: Hot Module Replacement

  • Application scenario: In a development environment

  • What it does: Hot replace HMR, where the partial load page is modified when the development service is started; Speed up development and compilation

    Preserve application state that is lost when the page is fully reloaded

    Update only the changes to save valuable development time

    Styling is faster: it’s almost like changing styles in the browser debugger

  • Limitation: HMR is optional (only affects modules that contain HMR code)

    For example, using style-loader to append patches to style styles. Style-loader implements the HMR interface in order to run the add-on patch. When it receives updates through HMR, it replaces the old style with the new one

    If a module does not have an HMR handler, updates will bubble up. This means that a simple handler can update the complete Module tree

  • Configuration HMR

    // webpack configuration file const webpack = require('webpack');
    
    
    module.exports = {
        devServer: {
          contentBase: path.resolve(__dirname,'dist'),
          compress: true,
          host: 'localhost',   
          port:3000,
          hot: true// Enable hot replacement}, plugins: [new webpack NamedModulesPlugin (), / / necessary configuration new webpack HotModuleReplacementPlugin () / / necessary configuration]}.Copy the code

6. Make good use of on-demand loading in project development

  • Mode 1: Use ES6 modularity syntax to dynamically load module import()

    The import(“) syntax is currently only in the ECMAScript proposal phase and has not been officially released

    See import API for details

    //.babelrc // Babel 7 {"plugins": [
            "@babel/plugin-syntax-dynamic-import"]}Copy the code
  • Method 2: Use Webpack to split the code and load it on demand (Require. Ensure syntax of Webpack)

    • Require. Ensure is a webpack syntax:

      • Parameter 1: the module to depend on; Array of type string; The general is empty

      • Parameter 2: The callback function that is automatically executed after the dependency is loaded

      • Parameter 3: Output path of js file and JS file name (chunk name) after package

      Const router = new VueRouter({routes: [// routes: {path: string, name?: string, component: (resolve) => { require.ensure([], () => { resolve(require('.. /.. /view/demo/index.vue'))},'demo'}}]});Copy the code

7. Configure the loader validity range

  • Effect: Configure the validity range of the Loader to improve compilation speed

  • The following uses babel-loader as an example

    // webpack configuration file const path = require('path');
    
    module: {
        rules: [{
            test: /\.js$/,
            use: ['babel-loader']]}}Copy the code
    // webpack configuration file const path = require('path');
    
    module: {
        rules: [{
            test: /\.js$/,
            use: ['babel-loader'],
            exclude: ' '// Include: [path.resolve(__dirname,'src'), /node_modules/] // Specify the folder to load}]}Copy the code
  • Exclude and include values:

    • Values can be individual items or arrays

    • It can be a path or a re

  • Actual project:

    In the project development, targeted at the main lodaer such as Babel-loader, style-loader, sas-Lodaer and so on

    In addition to converting project code, you need to convert node_modules code. Otherwise, an error will be reported for node packages that are not fully converted to JS

8. Configure how to resolve modulesresolve

  • Alias the module: resolve.alias

    Exports = {// webpack config.module.exports = {//... resolve: {alias: {
            '@components': '/src/common'}}};Copy the code
    // Project code import a from'@components/utils'; // Equivalent to import a from'/src/common/utils';
    Copy the code
    • Resolve path alias path prompt
  • Automatic suffixes rule: resolve.extensions

    When modules are introduced without file suffixes, WebPack adds suffixes in order to find files based on the configuration

    Exports = {// webpack config.module.exports = {//... resolve: { extensions: ['.vue'.'.js'.'.scss'.'.css'.'.json']}};Copy the code
  • The file name to use when parsing the directory: resolve.mainfiles

    The default is to look for files named index

    Exports = {// webpack config.module.exports = {//... resolve: { mainFiles: ["index"]}};Copy the code
  • Indicate where third-party modules are stored to reduce search steps

    • Default: [node modules]

    • The default search procedure is to go to the /node modules directory of the current directory to find the module we are looking for. If not, go to the directory one level up.. /node modules, if there is no more, go to.. /.. Find/node modules

    Exports = {// webpack config.module.exports = {//... resolve: { modules: [path.resolve(__dirname,'node_modules')]}};Copy the code
  • Introduction of modules to find rules:

    It is not recommended to write file suffix, which means the module path introduced, the last layer of the path may be a file; It could be a folder

    By default, the last layer of the path is regarded as the file name, matching the configured suffix in turn

    If the file is not found, the last layer of the path is regarded as a folder, and the file name is matched in turn. If the file is found, the file name suffix is matched in turn

    If none is found, an error is reported

  • Resolve For details, see the official website

9. Configure noParse to ignore some files during Webpack compilation

  • Scene:

    • For files that are not modularized, there is no need for WebPack to handle compilation

    • By configuring modules.noparse, webpack can be ignored to speed up compilation

  • Configuration:

    Module. exports = merge(common, {modules: {// use the regular expression noParse: / jquery | chartjs / / / or / / using the function, from Webpack 3.0.0 began supporting noParse: (content) = > {/ / content on behalf of a module file path / / returntrue or false
              return/jquery|chartjs/.test(content); }}});Copy the code

10. Configure Performance to remove performance warnings in the production environment

  • After WebPack is packaged, a warning is printed if the file size exceeds the default (250KB) size

  • This is a good tip in a development environment, but is not necessary in a production environment and can be configured through Performance

  • Configuration is as follows

    See the official website for detailed configuration

    // WebPack config module.exports = merge(common, {performance: {hints:false, // Close warning maxEntrypointSize: 400000 // Set warning value to 40KB}});Copy the code

11. Configure the project environment variable webpack.definePlugin

  • Scenario: During project development, configure the JS variables that can be used in each file

  • Get the development environment variable process.env.node_env directly

    With webpack4.x, Webpack sets the value of the environment variable process.env.node_env to the value of mode in the Webpack configuration

    You can use process.env.node_env directly in your project code

    // Console. log(process.env.node_env); // developmentCopy the code
  • Sets/gets a new environment variable

    Using DefinePlugin, webPack’s built-in plug-in, you can define environment variables for project code

    Limitation: Environment variables set by DefinePlugin can only be retrieved in the project code, not in the webpack configuration file

    // webpack configuration const webpack = require('webpack');
       
    module.exports = merge(common, {
        plugins: [
            new webpack.DefinePlugin({
                'process.env.NODE_ENV': JSON.stringify('ddd'), // override process.env.node_env'process.env.globalName': JSON.stringify('globalName'),
                'globalName': JSON.stringify('eeee')]}}));Copy the code
    // Console. log(process.env.node_env); // ddd console.log(process.env.globalName); // globalName console.log(globalName); // eeeeCopy the code

12. NPM Script instruction parameter passing (three ways)

  • Scenarios: When configuring WebPack, you may need to pass parameters through NPM Script to handle different requirements in different scenarios

  • Method 1: Different systems have compatibility problems

    • Pass parameters (window) in script command configuration (package.json script)

      // In Windows, the parameter is passed"scripts": {
          "server": "webpack-dev-server --open"."build:dev":"set type=dev&webapck"."build:prod": "set type=prod&webpack"
      },
      Copy the code
    • Passing parameters in script command configuration (package.json script) (MAC)

      // In the MAC system: pass the parameter"scripts": {
          "server": "webpack-dev-server --open"."build:dev":"export type=dev&&webpack"."build:prod": "export type=prod&&webpack"
      },
      Copy the code
    • Receive parameters

      // Node syntax to readtypeAnd then according totypeThe value of the useif-elsejudgeif(process.env.type== "build"){// Production environment var website={publicPath:"http://192.168.0.104:1717/"}}elseVar website={publicPath:"http://cdn.jspang.com/"}}Copy the code
  • Mode 2: Require webPack configuration item input function (no system compatibility issues)

    • Pass parameters in script command configuration (package.json script)

      // package.json {"scripts": {
              "build": "webpack --env.NODE_ENV=local --env.production --progress"}},Copy the code
    • Get the environment variables from the WebPack configuration file

      One change must be made to the WebPack configuration. Module.exports normally points to configuration objects; To use the env variable, you must convert module.exports to a function

      module.exports = env => {
        console.log('NODE_ENV: ', env.NODE_ENV) // 'local'
        console.log('Production: ', env.production) // true
      
        return {
          entry: './src/index.js',
          output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist')}}};Copy the code
    • Execute the command NPM run build to see the value of the output environment variable in the console

      This allows you to configure different Webpacks in webPack by differentiating between different environment variables

  • Mode 3: No system compatibility problems, no excessive requirements

    • Pass parameters in script command configuration (package.json script)

      // package.json {"scripts": {
              "build": "webpack --prod"}},Copy the code
    • The parameters obtained from the Webpack configuration file are as follows

      // console.log(process.argv) in webpack configuration file; // output [node path, webpack path,'--prod']
      Copy the code
    • If you just want to pass a Boolean, get the following arguments

      // Install minimist NPM I [email protected] -dCopy the code
      // const processArgv = require('minimist')(process.argv.slice(2));
      
      
      console.log(processArgv.prod);      // true
      Copy the code

P.S.

  • Friends, have any questions can leave a message, exchange together

  • Next, I will also publish a few webpack4.X actual combat articles, please pay attention to

  • I am a front-end developer keen on programming, WX: ZXvictory66