Webpack

The five modules
  • EntryThe entry, webPack entry, defaults to index.js in the SRC folder
  • OutputExit, the location and naming of the output after it is packaged
  • LoaderTranslator, Webpack can only recognize JS and JSON files, so it is necessary to use Loader to convert CSS, less, IMG and other contents into contents that WebPack can recognize
  • PluginsPlug-ins, packaging things according to their own ideas, such as compression and so on
  • ModeThe modes are divided into development mode and production mode, which respectively target at packaging and online optimization during development and online optimization
Summary: The execution sequence is as follows:
1.Let's see what mode is2.Then Entry finds the Entry, and then finds the corresponding content3.If there is something that CSS or other webpack can't recognize, use loader to convert it4.It is then compressed according to plugins5.Finally, the packaged file will be output exportCopy the code
Basic configuration
  • The premise: Node version 10 or later
  • NPM init-y generates package.json
  • npm install webpack webpack-cli
  • Create a SRC folder and create index.js as the entry point
  • Create the build folder and create index.html as the place to import the package file ==(because originally if not configured, the packaged file is generated in the build by default and Webpack needs to import main.js manually)==
  • Run the webpack. / SRC /index.js -o./build/build.js –mode=development
Summary:
Webpack./ SRC /index.js -o./build/build.js --mode=development directive meaning webpack uses./ SRC /index.js as an entry Exports to. / build/build js as export, the default is the main, js packaging environment for development (development environment) initialization file directory build | - build. After js packaging have this build. Js file node. The modules SRC | - index. Js package - lock. Json package. The json: example: index. Jsimport $ from 'jquery'Originally used directlyimportThe browser will get an error, but after webpack, using main.js will not get an error, and we can do what we want, but we can't pack anything else at this point, just JS and JSON, because it's not configured yetCopy the code

Webpack configuration file,webpack.config.js

  • What it does: is a custom configuration file for Webpack that specifies what webpack does
  • File location: same as SRC
  • All build tools run on Node.js, so weIn webpack. Config. JssurfaceImport and export using the CommonJS specification
const path =require('path');
const htmlPlugin=require('html-webpack-plugin');
module.exports={
    entry:'./src/index.js'./ / the entry
    output: {filename:'bb.js'.// Export name
        path:path.resolve(__dirname,'build')// Exit address
    },
    module: {},plugins: [// Automatically generates HTML, and automatically imports packaged files
        new htmlPlugin()
    ],
    mode:'develpoment'
}
Copy the code

Loader translation officer

  • Lodaer configurationIn the Rules array of the Module object, each configuration is an object
  • An object includes test and use,
    • Test is a match file, using the re.
      • testYou can also change it toexclude, test stands for processingAll that matches, exclude indicates processingAll but matched
      • Test and exclude can exist together
    • Use is a conversion rule and an array. Use is executed from the back to the front and is dependent on loaderIf only one item can be written as a string
  • Enforce: true/false True indicates the priority
  • optionsIs the object, (Of pictures alone) do some configuration items, default no, you can not write
    module: {rules: [//use is executed from back to front, with dependencies
// Loader for CSS configurationNPM I CSs-loader style-loader -d {test:/\.css$/,use:['style-loader'.'css-loader']},
// Loader for less configurationPrerequisite NPM I style-loader less-loader CSS-loader -d {test:/\.css$/,use:['style-loader'.'css-loader'.'less-loader']},
// Configure the loader for images
// Although two loaders need to be downloaded, you only need to configure url-loader. If the limit in options is greater than 8KB, convert it to Base64NPM I url-loader file-loader -d {test:/\.(jpg|png|gif)$/,loader:'url-loader'.options: {limit:8*1024
            }},
// Handle files other than CSS, JS and HTMLCan be used with icon {exclude:/.(css|js|html)$/,loader:'file-loader'}},Copy the code
Some optional configuration items for options in image packaging
limit : 8*1024The image smaller than 8kb is converted to base64name : hash[10[ext] compressed image name used10Ext is his original suffix, the default compressed image name is very longesModule : true/falseEnable or disable es6Module modeoutputPath: address Outputs the packaged file to the specified folder. The address is a string, relative to the build root directoryCopy the code
Q&A
  • There is a conflict between url-loader and html-loader
  • The reason is that url-loader uses es6 module by default, while HTMl-Module uses CommonJS to import images. Es6Module uses commonJS to import images
  • Solution: Disable ES6 modularity in urL-loader and let it parse using commonJS specification
module.exports = {
    module: {
        rules: [{
                test: '/\.(png|jpg|jpeg)$/'.use: 'url-loader'.options: {limit:8*1024.esModule:false}},// Process img resources in HTML
            {
                test: '/\.html$/'.use: 'html-loader'}}}]Copy the code
eslint
  • Function: Syntax detection
  • Scope of detection: only detect their own code, third-party library is not checked
  • Download the dependency yarn add eslint-config-airbnb-base eslint-plugin-import eslint eslint-loader -d
  • Set the check rule:
    • Set the desired syntax specification in eslintConfig in package.json
  • When packing, red is error and yellow is warning
> package.json extends after the syntax specification to inherit"eslintConfig": {
    "extends":"airbnb-base"
  }
Copy the code
modules.exports={
rules:[
            {
                test:/\.js$/,
                exclude:/node_modules/,
                loader:'eslint-loader'.options: {// Automatically fix syntax specifications
                    fix:true}}}]Copy the code
Js Compatibility processing
  • Handling JS compatibility
  • yarn add -D babel-loader @babel/core @babel/preset-env webpack
Version conflict
  • Babel-loader8 corresponds to Babel 7
  • Babel – loader7 corresponding babel6
By default, only basic syntax can be converted, not all ES6 to ES5 or lower
  • yarn add @babel/polyfill -D
  • Import from index.js instead of loader
  • The defects, although we’re going to deal with all of them, there are some that we don’t use, and he’s going to package the methods together, and it’s going to be huge
// Import all defects in index.js
import '@babel/polyfill';

// Import on demandYarn add babel-loader @babel/preset- env@babel /preset- env@babel /polyfill core-js -d Yarn add babel-loader @babel/preset-env @babel/polyfill core-js -d yarn add babel-loader @babel/preset-env @babel/polyfill core-js -dmodule.exports={
	module: {rules:[
	            {
                test: /\.js$/,
                exclude: /node-modules/,
                loader: 'babel-loader'.options: {
                    presets: [['@babel/preset-env', {
                            // Load as needed
                            useBuiltIns:'usage'.// Specify the core-js version
                            corejs: {version:3
                            },
                            // Specify which version is compatible
                            targets: {chrome:'60'.firefox:'60'.ie:'9'.safari:'10'}}]]},}]}}Copy the code

plugins

  • role: There are several plugins that handle things, and different plugins serve different purposes
  • usageThis is done by requiring the import and then new in the plugins array
– webpack – plugins plugin = = = = HTML
  • Purpose: to achieve automatic HTML generation, and the introduction of packaged files
    • Optional configuration item,Pay attention toIf new is used, an object must be passed inside ()
    • Template :’ file address ‘generates new HTML from the template of the HTML in the file address
Prerequisite: NPM I html-webpack-plugin-dconst htmlPlugin=require('html-wenpack-plugin');
module.exports={
	plugins: [new htmlPlugin()
	    ],
//	plugins:[
// new htmlPlugin({
// template:'./ SRC /index.html'// Configuration item
/ /})
/ /,
}
    
Copy the code
= = the mini – CSS – extract – the plugin plugin = =
  • role:The extraction of CSS, separate the CSS into a file and import it with the link tag
  • benefits: Normal loader uses style-loader package in JS and then add style label through JS to achieve the effect of white screen
  • Pay attention to: Special in that,Not only do you need new in plugins, but alsoTo use the name in loader. LoaderAnd note that,Cannot be used together with style-loader
  • Configuration items can be passed when new
//style-loader is used to add style tags to js
module.exports = {
    module: {
        rules: [{
            test: /\.css$/,
            use: ['style-loader'.'css-loader']]}}}// Use the plugin to extract the CSS and import it with the link tagPrerequisite: NPM install mini-css-extract-plugin -dconst miniPlugin = require('mini-css-extract-plugin');
module.exports = {
    module: {
        rules: [{
            test: /\.css$/,
            use: [miniPlugin.loader, 'css-loader']]}},plugins: [
        new miniPlugin({
        // Pack the CSS into the built-in folder in the built-in file
		filename:'css/built.css'}})]Copy the code
= = optimize – CSS – assets – webpack – plugin compress CSS = =
  • Effect: Compress the CSS
  • NPM I optimize- csS-assets -webpack-plugin -d yarn add -D optimize- CSs-assets -webpack-plugin -d yarn add -D optimize- CSs-assets -webpack-plugin -d yarn add -D optimize- CSs-assets -webpack-plugin -d yarn add -D optimize- CSs-assets -webpack-plugin -d yarn add -D optimize- CSs-assets -webpack-plugin -d yarn add -D optimize- CSs-assets -webpack-plugin
const OptimePlugin=require('optimize-css-assets-webpack-plugin');
module.exports={
plugins: [new OptimePlugin()]
}
Copy the code
CSS Compatibility
  • What it does: Automatically prefixes styles to accommodate browser compatibility
  • Prerequisite: NPM install postCSS postCSs-loader postCSs-env -d
  • It does compatible CSS processing according to browserslist in package.json
// Old syntax, higher version use error
  / / {
      // loader:'postcss-loader',
      // options:{
      // ident:'postcss',
      // plugins:()=>{
      // require('postcss-preset-env')()
      / /}
      / /}
      // }New syntaxmodule: {
        rules: [{
                test: /\.css$/,
                use:[
                    miniPlugin.loader,
                    'css-loader'.// 'postcss-loader',
                    {
                        loader:'postcss-loader'.options: {postcssOptions: {plugins:[
                                   [
                                       "postcss-preset-env",]]}}}],}, {test: /\.(jpg|png|gif)$/,
                loader: 'url-loader'.options: {
                    limit: 8 * 1024.outputPath: 'image'}}},Copy the code

DevServer service, to achieve automation

  • Every time we update the code, we need NPM run build, obviously very troublesome, this time can use devServer to help us deal with
  • npm install webpack-dev-server -D
  • To start, use NPX webpack-dev-server or configure it yourself in package.json scripts to use NPM run
  • It is important to understand that NPX webpack does not have a visible update file, it does the update itself in memory, while NPX Webpack outputs the file, which is the difference between them
module.export={
   devServer: {// Project path
        contentBase:path.resolve(__dirname,'build'),
        // Start gzip compression
        compress:true./ / the port number
        port:3000.// Automatically opens the default browser
        open:true}}Copy the code
Have a problem
Version Information:"webpack": "^ 5.36.0"."webpack-cli": "^ 4.6.0"."webpack-dev-server": "^ 3.11.2"An errorError: Cannot find module 'webpack-cli/bin/config-yargs'The webpack-dev-server version does not support Wepack5 and Webpack4"start": "webpack serve --mode development --env development"The command is successfully executed: NPM run startCopy the code

Webpack performance optimization

HMR hot update

  • Scenario: As soon as one file is modified, WebPack repackages the entire file, consuming performance and slowing down
  • Action: When a module changes, only the changed ones are packaged
  • Update scope:
    1. Style files can use the HMR function, because style-loader is implemented internally, so we will use style-loader during development
    2. Js files cannot use HMR function by default. If modified, they will all be repackaged, refreshed, and configured in SRC /index.js. You can implement a single module update
    3. HTML files. The HMR function is disabled by default. After modification, the page cannot be hot updated and the page will not be refreshed
    + solution: Modify the entry entry, change to an array, put HTML files also, generally is not usedCopy the code
//webpack.config.js
const webpack=require('webpack');
module.exports={
	//entry:'./src/index.js'
	entry: ['./src/index.js'.'./index.html'].plugins: [
	// Use webpack's own hot update plugin
	    new webpack.HotModuleReplacementPlugin()
	],
	devServer: {// Enable hot update, also known as HMR
	hot:true}}Copy the code
//index.js/aa.js is the js address to be updatedif(module.hot){
    module.hot.accept('./aa.js'.function(){
        print();
    })
Copy the code
Hot update failure
  • If the websocket is not loaded, delete “browserslist” from package.json

Source-map is displayed

  • Source-map is a technique that provides a mapping of the source code to the built code. The simple explanation is that the packaged code has errors, and the error location in the source code is pointed out for easy modification, because the packaged code is a JS, which is difficult to observe
  • When used, devtool:’ value ‘
  • There are seven values with different characteristics that can be used in pairs
Hidden-source-map does not track source code errors. Nosource-source-map does not track source code errors. Nosource-source-map does not track source code errors. Cheap -map does not indicate the exact number of lines in the source code and the location of the source code error, but it does indicate the error by line. Simply put, if two lines of code do not have a newline, it will mark the preceding line as cheap-module- Map displays error messages and source code error locations,moduleThe loader and source map will be added, that is, third-party library errors will be thrown inline inline-source-map error message and source code error locationeval-source-map error message and source code error location difference between inline and outbound:1.Inlining is to generate JS files externally, inlining is to write in HTML,2.Faster inline build speed The development environment requires: fast speed, easy debugging speed (eval>inline>cheap)
            eval-cheap-souce-map
            eval-source-map debugging friendly souce-map cheap-module- Souce-map cheap- Souce-map combines the optimal schemeeval-source-map / eval-cheap-module-source-map production environment: source code should be hidden, debugging should be convenient inline is embedded in HTML, so the volume will be larger, Hidden-source-map only hides the source code, which prompts the optimal solution source-map/cheap- after the buildmodule-source-map
Copy the code
oneOf
  • Application scenario: For example, CSS, less we are equipped with loader, but when packaging, each of them should be matched once, but we do not need to match each loader once, only one match
  • Purpose: Make some loaders match only one in this range
  • Note: Do not use some suffixes that are the same and associated, such as js going from ES6 to ES5
module.exports = {
    module: {
        rules: [
            // Note that an object has been added
            {
                oneOf: [{test: /\.css$/,
                        use: ['style-loader'.'css-loader'] {},test: /\.less$/,
                        use: ['style-loader'.'css-loader'.'less-loader']}]}}Copy the code
Three hash
  • Hash is usually applied to the file name to prevent cache flushing
hash
  • Each Webpack generates a unique hash, which can be interpreted as the number of the pack action
  • Problem: With this, once repackaged, all caches are invalidated because the hash has changed, meaning that the file name used for the hash has also changed, and the request is rerequested
chunkhash
  • Based on the hash generated by chunk, if the package comes from the same Chuank, the hash value will be the same
  • Problem: JS and CSS hash the same, because normal projects import CSS in JS,Chunk is created based on entry (which may not be standard)Can be understood asOne chuank for each entrySo repackaging the cache will still fail
How chuank came about
  • Entry entrance.
    1. If it isArrays or stringsIt will onlyTo produce achunk
    2. If it isobjectIn that objectA couple of key-value pairs,Have a fewchunk
  • Asynchronous loading module
  • The code segment
contenthash
  • The hash generated based on the content of the file can also be understood as a unique hash for each person, and a new unique hash will be generated only when the person changes the hash

The cache

Js go cache
  • Add cacheDirectory: true to options
  • Avoid repeating Babel compilation of JS files, only modified JS files should go
  • Caching is not performed until after the first time
    module: {
        rules: [{
                test: /\.css$/,
                use: ['style-loader'.'css-loader'] {},test: /\.js$/,
                exclude: /node-modules/,
                loader: 'babel-loader'.options: {
                // Add this
                    cacheDirectory: true}}}],Copy the code
The file cache
  • Using hash names
    output: {
        filename: 'bb.[contenthash].js'.path: path.resolve(__dirname, 'build')},plugins: [
        new miniPlugin({
            filename:'css/build.[contenthash:10].css'})].Copy the code

Tree shaking the tree

  • role: English literal translationA tree shookTo put it simply, we downloaded a lot of third-party libraries, but some of them were useless. If we compare the whole project to a tree, what we used were green leaves, and what we did not use were grey leaves. Then we need to shake the tree to remove grey branches and leaves to achieve the effect of building branches and leaves, that is, to remove useless codes
  • Premise:
    1. You must use ES6 modularity
    2. The mode of production
CSS loss problem
  • “SideEffects” is configured in package.json :false means all code is tree shaking
  • Then he might remove CSS and other files that he doesn’t use
  • Solution: Configure “sideEffects”
// Exclude CSS when tree shaking
"sideEffects": ["*.css"]
Copy the code

Multi-entry/multi-page

  • Name is the entry key
  • Will be packaged into two JS
module.exports={
    entry: {index:'./src/js/index.js'.login:'./src/js/login.js'
    },
    output: {filename:'js/[name].[contenthash:10].js'.path:resolve(__dirname,'build')}}Copy the code

Code split Code split

  • Description: If webpack is packaged, js will be merged by default, one entry will be merged into one JS, and the code splitting can be used to separate the imported third-party modules. In case of multiple entry, the same third-party library will be imported in multiple places, and js will be merged in each entry once by default, because they belong to different modules. However, after code splitting, js will be pulled out. The public third-party module is only removed once, and the entry JS is automatically introduced
//webpack.confing.js
module.exports = {
    // Code split
    optimization: {
        splitChunks: {
            chunks: 'all'}}},Copy the code
  • If you want to package one of your js files separately and give it a name, you can use import “.
  • /webpackChunkName:’aa’The aa in /’ is a custom name and can be omitted
import (/*webpackChunkName:'aa'*/'./aa');
Copy the code

Lazy loading and preloading

  • Lazy loading is when a condition is triggered. Lazy loading can place an import inside an asynchronous function
  • Preloading means that the resource is loaded in advance, waiting for the trigger condition, directly out of the cache. This method is implemented by adding webpackPrefetch:true to the import of the asynchronous function
  • The difference between preloading and normal import loading is that normal loading is parallel loading, while preloading is asynchronous loading. It can be understood that preloaded resources are not loaded until all other resources are loaded
btn.onclick=function (){
    import (/*webpackChunkName:'test',webpackPrefetch:true*/'./test')}Copy the code

Q&A

NPM I babel@7 can’t be installed
An error occurs after the dev command is set to webpack-dev-serverCannot find module 'webpack-cli/bin/config-yargs'
  • Solution: Change the dev command to webpack Server