Webpack is the most popular packaging tool at the front end. I believe many friends want to learn Webpack well. The learning here may be to be able to skillfully configure Webpack and configure and optimize their own projects in practical work, or to know the operation principle of Webackp, so as to expand their own project functions. Either way, like me, you’ve probably read a lot about WebPack but have no idea where to start when it comes time to write your own configuration. Therefore, the purpose of this article is to sort out the basic knowledge related to Webpack and deepen my understanding of Webpack.

Back to the body

The core concepts of WebPack

Entry:

  • Entry: An entry starting point that indicates which module WebPack should use as a starting point for building an internal dependency diagram. Recursively resolves all dependencies to generate a dependency graph.

    Usage: entry: string | Array < string >

    webpack.config.js
module.exports = {
  entry: {
	app: './src/app.js' // Entry address}}// Short form
module.exports = {
  entry: './src/app.js'
}
Copy the code

For details, see the official website

Output:

  • Output: Defines the output directory for webpack compilation files. Notice that even though there are multiple entry files, there is only one output file. You can also output multiple files by name.

    Usage:

webpack.config.js

module.exports = {
	output: {
	    filename: 'bundle.js'.// Output file name [name].js
	    path: path.resolve(__dirname, 'dist'), // The absolute path to the output directory of the file
            publicPath: '/'}}Copy the code

PublicPath is the base path of static resources packaged by WebPack. See the official website for details.

When publicPath is set, the static resource path is domain name + publicPath + filename.

Code configuration:

Output. path is where the packed files are stored, and output.publicPath is the HTML import static resource prefix path (required if the file is not in the root directory of the website).

Also in development mode, devServer has a publicPath configuration. As we know, devServer is a Node.js service that puts generated files in memory to speed up packaging, so devServer.publicPath stands for the file path in memory, which is somewhat similar to output.path. Configuration as shown in the figure:

Code configuration:

Browser:

When deveServer. PublicPath = ‘/ testPath, in the browser to localhost: 8080 / testPath/bundle. Js access

Mode:

  • Mode: added attribute of WebPack4. The corresponding mode enables the corresponding plug-in. See [here] (www.webpackjs.com/concepts/mo.)

Loader:

  • Loader: Some documentation says that Loader can let Webpack handle non-javascript files, such as CSS files, image files, etc. But loader does more than that. Loader is used to convert the source code of a module. Loader can obtain the file source code, modify it arbitrarily, and return the result, and can be processed by the next loader.


    The common loaders are listed below:

    (Default install the following loader)

    1. Raw-loader: loads raw file contents

    Configuration:

    module.exports = {
    	entry: ' '.output: {},
    	module: {
    	rules: [{test: /\.txt/.uset: 'raw-loader'}}]Copy the code

    Use:

      import txt from './rawTxtTest.txt';
      console.log(txt) // Print out the contents of the rawTxtTest file
    
    Copy the code

The webpack parses the contents of the TXT file using the raw-loader.

  1. File-loader: can process image resource files

Configuration:

	module.exports = {
    	  entry: ' '.output: {},
    	  module: {
    	  rules: [{
              test: /\.(jpg|png|gif)$/.use: [{
              loader: 'file-loader'.options: {
              name: '[path][name].[ext]'}}}}]]Copy the code

Use:

	import img from './a.jpg';
	console.log(img); // /src/a.jpg
Copy the code

File-loader produces files in the corresponding directory. If name is not specified, hash files are generated.

  1. Url-loader: processing image resource file configuration:
    module.exports = {
        entry: ' '.output: {},
        module: {
        rules: [{
            test: /\.(jpg|png|gif)$/.use: [{
            loader: 'url-loader'.options: {
            	limit: 1000000}}}}]]Copy the code

Url-loader is similar to file-loader, except that when url-loader is used and the file size is smaller than limit(btye), a DataUrl(data: base64 data starting with the file) is returned.

  1. Source-map-loader: Loads additional source map files for cheap breakpoint debugging
  2. SVG – the inline – loader: parsing SVG
  3. Json-loader/jSON5-loader: Webpack4 parses JSON files by default, and jSON5-loader parses Json5 files
  4. Babel-loader: parse ES6 + syntax for ES5 configuration:
	module.exports = {
          entry: ' ',
          output: {},
          module: {
          rules: [
            {
              test: /\.js$/,
              use: [{
              	loader: 'babel-loader'// This section can be placed in the.babelrc configuration file presets: [["@babel/preset-env", {
                   		targets: {
                   			"chrome": '51',
                   			ie: '9'
                   		},
                   		modules: false,
                   		useBuiltIns: 'entry',
                   		corejs: 2
                   }]],
                   plugins: [
                   		'@babel/plugin-syntax-dynamic-import'.'@babel/plugin-transform-runtime'
                   ]
                	}
              }] 
            	incluede: [path.resolve(__dirname, 'src')]}}]Copy the code

The options configuration tells Babel how to parse JS files. Presets are presets. The most common preset is @babel/preset-env, which can parse ES6 to ES5 based on the preset target. Babel is a large piece of content, including its installation, usage and configuration principles, which are not covered here; there will be a separate article describing Babel.

  1. Eslint-loader: Checks JS syntax from configured rules

Configuration:

module.exports = {
      module: {
        rules: [
          {
            test: /\.js$/,
            enforce: 'pre',
            use: [{
              loader: 'eslint-loader'Rules: {}}], include: path.resolve(__dirname,'./src/**/*.js'),
            exclude: /node_modules/ 
          }
        ]
      }
		}
		
// .eslintrc.js
module.exports = {
    "env": {
        "browser": true."commonjs": true."es6": true
    },
    "extends": ["eslint:recommended"."plugin:react/recommended"], // Inherit all rules"parserOptions": {
        "ecmaVersion": 2015,
        "sourceType": "module"."ecmaFeatures": {
            "experimentalObjectRestSpread": true."jsx": true
          },
    },
    plugins: ['react']."rules": {// Modify the configuration rule"react/display-name": 0."no-unused-vars": [2, {"vars": "all"."args": "after-used"}]."no-console": "off"."indent": [
            "error", 4]."linebreak-style": [
            "error"."unix"]."quotes": [
            "error"."single"]."semi": [
            "error"."always"]}};Copy the code

You can unify the commit code style by setting “pre-commit” in the package.josn file.

  1. Ts-loader: typescript parses into javascript syntax and parses. Ts files

  2. Awesome -typescript-loader: provides the same function as TS-Loader and performs better than TS-Loader

  3. Sass /less-loader: The SASS /less syntax is parsed into CSS. Parse sass/ LESS files

  4. Postcss-loader: automatically completes the CSS3 prefix

  5. Css-loader: loads the CSS and modularizes it

  6. Style-loader: registers CSS to HTML

  7. Vue-loader: parses. Vue files

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'// const VueLoaderPlugin = require('vue-loader/lib/plugin')
	module.exports = {
  	entry: ' ',
  	output: {},
  	module: {
  	rules: [
  		{
      	test: /\.vue$/,
      	use: 'vue-loader'
      }
  	],
  	plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html'
        }),
        new VueLoaderPlugin()
    ]
  }
  
  // main.js
import Vue from 'vue';
import App from './App.vue';

new Vue({
	el: '#app',
	render: h => h(App)
})

// app.vue
<template>
    <div class='c'</div> </template> <script> //import Home from'./Home.vue'
export default {
    //components: {
    //    Home
    //},
    data() {return {
            name: 'panhe'
        }
    }
}
</script>

<style lang="less" scoped>
    @color: blue;
    .c {
        color: @color;
    }
</style>
Copy the code
  1. @ Babel/preset – react: parsing the react
// .babelrc
{
    "presets": [["@babel/preset-env", {
            "targets": {
                "browsers": ["last 2 versions"]."ie": 7}}],"@babel/react"]."plugins": ["@babel/transform-runtime"} // Add JSX file parsing to babel-loader to complete the configurationCopy the code

The Plugin:

Plugin is used to extend webpack functionality. The plugins property is an array that accepts various Plugin instances.

modules.export = {
    plugins: [
          new HtmlWebpackPlugin({
              filename: 'index.html',
              template: 'index.html'
          }),
          new VueLoaderPlugin()
      ]
	}
Copy the code

Webpack has a rich plugin interface. Most of the functionality of WebPack itself uses this plug-in interface. This plug-in interface makes WebPack extremely flexible. – webpack website

Make a list of commonly used Plugins(I will type them once to make them more memorable and pave the way for later Plugins and handwritten Plugins):

  1. HtmlWebpackPlugin

    Function: Generate HTML file and inject static resources packed with Webpack into the generated HTML file.

	new HtmlWebpackPlugin({
  	filename: 'index.html'// Output file name template:'index.html'// Template file location:'title', // Generate file title inject:true|body|head|false, / / js at the bottom of the insert file location body | | at the bottom of the body at the bottom of the heade | doesn't generate the favicon js file:' '// Generate faviconhash: true, // bundle.js? Minify: {// Compress the generated HTML collapseWhitespace:true// Remove Spaces, defaultfalse
			removeComments: true// Remove the comment defaultfalse
			removeEmptyAttributes: true// Delete the null attribute // delete the style attribute,type="text/css" 
    	removeStyleLinkTypeAttributes: true// Remove the type attribute of script under h5typeDefault: text/javascript defaultfalse
    	removeScriptTypeAttributes: true,
    	useShortDoctype: true, // Short document type}}),Copy the code
  1. Function of Webpack-bundle-Analyzer: The components of bundles are clearly visible and can be divided and optimized as needed.

	const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
	plugins: [
          new BundleAnalyzerPlugin(),
       ]
Copy the code

The default configuration meets the requirements. For details, see here

  1. DefinePlugin

    Purpose: Defines global variables to distinguish between development and build environments. The key-value pairs passed into the DefinePlugin constructor can be referenced anywhere in the project.

	new webpack.DefinePlugin({
            PRODUCTION: JSON.stringify(true),
      	    VERSION: JSON.stringify("5fa3b9"),
      	    BROWSER_SUPPORTS_HTML5: true,
      	    TWO: "1 + 1"."typeof window": JSON.stringify("object")})Copy the code

Note that because this plug-in performs text substitution directly, the given value must contain the actual quotes inside the string itself. In general, there are two ways to achieve this effect, using ‘ ‘production’ ‘, or using json.stringify (‘production’). – webpack website

  1. DllPlugin/DllReferencePlugin this plugin with good can improve the speed of our build. That’s what it does. Next look at how to use, actually very simple, according to the format, you only need to modify your public packaging dependencies and file output location, other fixed basically meet the requirements. Prepare a webpack.dll.config.js. Used to output DLL files
// webpack.dll.config.js
const path = require('path')
const DllPlugin = require('webpack/lib/DllPlugin')
module.exports = {
    entry: {
        react: ['react'.'react-dom']
    },
    output: {
        filename: '[name].dll.js',
        path: path.resolve(__dirname, '.. /static'),
        library: '_dll_[name]'
    },
    plugins: [
        new DllPlugin({
            name: '_dll_[name]',
            path: path.join(__dirname, 'dist'.'[name].manifest.json')
        })
    ]
}

// package.json
script: {
	'dll': 'webpack --config build/webpack.dll.config.js'
}
Copy the code

Library === dllPlugin. Name (dllPlugin is an instance of dllPlugin) React and react-dom are fixed dependencies packed into DLL files. In the future, you can only find builds in DLLS. The other file is the manifest.json file output by DllPlugin, which is used by its sibling plugin DllReferencePlugin to tell it how to find static resources. Use in the webpack.config.js file

// const DllReferencePlugin = require('webpack/lib/DllReferencePlugin')
plugins: [
        new DllReferencePlugin({
            manifest: require('./dist/react.manifest.json')})]Copy the code

Run the NPM run DLL and then run the NPM run build

  1. UglifyjsWebpackPlugin
// webpack.config.js
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

module.exports = {
  plugins: [
    new UglifyJsPlugin()
  ]
}
Copy the code

See the official website for detailed configuration

  1. SplitChunkPlugin starting with WebPack V4, CommonsChunkPlugin was removed and changed to Optimization.splitchunks. Sometimes, after loading on demand, the file will still be large because of the spiltChunks rule. In this case, you need to reset the splitChunks rule. There are many rules that can be divided if you want to sacrifice server stress for user experience.

Default configuration:

	optimization: {
    splitChunks: {
      chunks: 'async',
      minSize: 30000,
      minRemainingSize: 0,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 6,
      maxInitialRequests: 4,
      automaticNameDelimiter: '~',
      cacheGroups: {
        defaultVendors: {
          test: /(react|react-dom)/,
          priority: -10,
          name: 'Packaged file name'
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true}}}}Copy the code

The main attribute is the splitchunk. cacheGroups property, where each key will be a partition rule from which a chunk file will be packaged. Properties outside of cacheGroups can be inherited.

chunks: All | async | inital all file | | asynchronous file synchronization test: priority rules matching file: MaxAsyncRequests and maxInitialRequests maximum synchronous/asynchronous requests will also affect the resulting packaging.

The detailed rules can be found here, and I think the series is very clear.

  1. MinCssExtractPlugin

    This plug-in extracts CSS styles into a separate file.

resovle

The Resovle module can change the rules to find files according to its needs

  • Alias Alias finds files
	resolve{
		alias: {
			@: './src/components'}} this can be done according to importThe '@'Looking for'./src/components'The fileCopy the code
  • MainFields mainFields can set which code to use

  • Extensions are automatically suffixed. Extensions: [‘.ts’, ‘.js’, ‘json’]. Import ‘./data’ to ts, js, json format, error if not found

  • modules

    When importing third-party modules, webpack will look for node_modules by default, but some modules can be set to modules if they are frequently used.

    For example, import ‘.. / SRC /components/button’ will be used in many places, so you can set modules: [‘./ SRC /components’, ‘node_modules’], just import ‘button’ in the project

  • enforceExtension/enforceModuleExtension

    When setting enforceExtension: True, when the import ‘./data’ fails, the.js suffix must be added, or whatever

    EnforceModuleExtension is a third-party module for node_modules