Combed some webpack entry development experience, share out, welcome to learn.

directory

  1. What is the webpack
  2. Webpack do
  3. Webpack fundamentals
  4. Webpack application
  5. Webpack packaging vue
  6. Webpack packaged the react
  7. Webpack optimizes configuration

What is the webpack

Webpack is a module packer based on node.js static resources. When packaged with WebPack, it looks for individual module dependencies from a starting point and groups the files into one or more packages based on those dependencies.

Webpack do

Webpack can do the following engineering

  1. Default commonJS specification
  2. Code conversion (e.g. ES6 to ES5, SASS and LESS to CSS, etc.)
  3. File optimization (e.g. compression of module contents)
  4. Code segmentation (e.g., multi-page application of common module pulling out, route lazy loading)
  5. Module merging (e.g., combining multiple modules for different functions into one module)
  6. Automatic refresh (e.g., start local service, automatic refresh after code update)
  7. Code validation (e.g., adding ESLint for code specification checking)
  8. Automatic publishing (e.g., automatic publishing after the application is packaged)

Webpack fundamentals

Configure resolution -> Built-in plug-ins & Configure plug-in registration -> Confirm access to obtain dependent resources -> Translate resources using Loader -> identify resource loading statements and recursively traverse all resources -> Encapsulate dependent resources output results

Webpack application

The environment version is based on

Webpack 4.x version Node: 12.x versionCopy the code
npm install webpack-cli -g
npm install webpack@4 -g
Copy the code

1.1 Initializing the Project

Create a new directory and initialize NPM

npm init
npm i -D webpack webpack-cli
Copy the code

Create a new folder SRC, then create a new file main.js, and write some code to test it out

console.log("hello webpack");
Copy the code

packaging

webpack src/main.js
Copy the code

If a dist folder is generated with main.js inside it, it has been successfully packaged

Usually we need to create a webpack.config.js custom WebPack configuration parameter.

1.2 Webpack.config.js configuration file

Create webpack.config.js to configure webpack. A configuration file contains:

Entry entry, Output exit, Mode mode, Module module, resolve resolution, Loader, Plugin, devServer server, NPM command

Let’s go through each of these parameters briefly

1.3 entry portal

The starting point for webPack, which looks for dependencies between modules from this file

## Single entry filemodule.exports = {
  entry: './src/index.js'} ## multiple entry filesmodule.exports = {
  entry: {
    main: __dirname + '/src/index.js'.page: __dirname + '/src/page1.js'}}Copy the code

1.4 the output export

Output directory and file name of a webpack packed file.

  1. path

The path configuration determines the file path of the final packaged output resource, and it must be a system absolute path (this is not the same as the path that was eventually introduced in HTML). If the HTML plugin is used, Webpack will intelligently determine the relative path of the generated HTML and chunk and import it in script mode.

  1. publicPath

Sometimes our HTML and static resources are not distributed to the same place. For example, HTML is rendered for the server or sent to a dedicated HTML output server for easy version control, while static resources such as JS/CSS are exclusively distributed to the CDN. This requires HTML to import resources in a full path. You need to use publicPath.

  1. library

This property determines what webPack builds packages for and how they can be referenced, loaded and executed. But for everyday engineering builds, it can be left out by default.

An output fileoutput: {
    filename: 'bundle.js'}} ## Multiple output filesoutput: {
  path: __dirname + '/dist'
  filename: '[name].js',}Copy the code

1.5 mode pattern

In an engineering project: production environment, we want the output file to be compressed and obfuscated. While developing the environment for debugging purposes, we want files to be uncompressed and obfuscated.

webpack@4+ This operation is implemented by configuring different modes [mode].

The existing modes are production, development, and None. The default mode is production. Both production and development default to process.env.node_env as production or development. When none is set, Webpack does nothing additional.

const path = require("path");
module.exports = {
  mode: "development".// Development mode
  entry: path.resolve(__dirname, ".. /src/main.js"), // Import file
  output: {
    filename: "output.js".// The packaged file name
    path: path.resolve(__dirname, ".. /dist"), // The packaged directory}};Copy the code

Configured to run

"scripts" : {
	"build": "webpack --config build/webpack.config.js"
}
Copy the code

1.6 the module module

Different file types may need to match different Loaders to perform different file conversion. Some modules may need to be handled, others may need to be ignored, and all the related configuration is in the Module.

  1. Rules is an array configuration. Each rule in rules specifies how to handle a module

  2. NoParse configures the noParse field to filter certain packages that you are sure do not need the recursive parsing module to load. NoParse: /jquery/,

1.7 resolve parsing

This configuration determines how modules are parsed. For example: whether to cache this module; Whether to automatically identify the extension file name. The most common configuration, however, is just one alias: create an alias for import or require to abbreviate the path to some module file.

resolve: {
    alias: {
      The '@': path.resolve(process.cwd(), './src'); }}Copy the code

Use in pages

import utils from ‘#/utils’

Configure error information in Webpack via STATS

stats: {
  warnings: false.// Cancel the warning message
  children: false.// Cancel the child information
  modules: false.// Cancel the module building information
  entrypoints: false // Do not display the entry starting point
}
Copy the code

1.8 Loader

Webpack itself can only handle javascript modules and requires a Loader to handle other types of files. Loader can be thought of as a converter of modules and resources. Loader itself is a function that takes different types of source files as parameters and returns the converted result.

Loader features:

  1. You can accept parameters and pass configuration items to loader
  2. It can be published and installed through NPM
  3. Running in a NodeJS environment, synchronous and asynchronous operations can be implemented
  4. This can be added by requiring () a reference module
  5. It can be used from the command line
  6. Can support chain delivery

Loader contains the following attributes:

  1. Test: a regular expression that matches the extension name of the file loaders is handling (required)
  2. Use: Loader name (mandatory)
  3. Include /exclude: Manually add mandatory files (folders) or exclude unnecessary files (folders) (optional).
  4. Query: Provide additional setup options for loaders (optional)
module: {
    loaders: [{test: /\.css$/, loader: 'style-loader! css-loader'}},Copy the code

Commonly used loader:

  1. Babel-loader uses Babel to convert the latest standard code into javascript code that can be executed by the current browser. The configuration of babel-loader is the configuration of Babel, which mainly exists in the project root directory as a.babelrc configuration file. If the configuration has special logic processing, you can override the configuration by referring to babel-loader in module.rules.
  2. Less-loader/Sass-loader: Modern engineering can not do without less/ SASS pretreatment.
  3. Postcss-loader: CSS style post-processing tool. CSS compression, consolidation, and automatic compatibility with browsers
  4. Css-loader: interprets @import and URL () in CSS files; You can enable csS-Module.
  5. Style-loader: inserts the CSS into the DOM with the style label.
  6. Css-hot-loader: CSS hot update loader. Do not add the CSS hot update loader in online environment, which will cause the JS file contentHash to change every time.
  7. File-loader For static resources such as images, we usually import images in their relative paths based on the current file. When we access THE HTML, the relative path is actually based on the path of the HTML, so it will lead to path error. File-loader solves this problem. You can automatically identify webPack configurations, package resource images, and fix import paths to ensure that resources are imported correctly. You can also modify the path and file name of the output file and carry hash values.
  8. Url-loader has the same basic function as file-loader. Based on url-loader, you can set a limit configuration item, meaning the size of the file, in bytes. Files smaller than this size are converted to base64 data instead of url import. For small images and other resources commonly used such operations, the advantage is to reduce the number of requests for resources; Or, in some scenarios, make sure the image is displayed when THE HTML loads or renders, without having to request it again.

1.8.1 style-loader CSS – Loader processes CSS files

Importing CSS files

npm i -D style-loader css-loader
npm i -D less less-loader
npm i -D postcss-loader autoprefixer

Copy the code
// webpack.config.js
module.exports = {
  / /... Omit other configurations
  module: {
    rules: [{test: /\.css$/,
        use: ["style-loader"."css-loader"].// Parse principles from right to left
      },
      {
        test: /\.less$/,
        use: [
          "style-loader"."css-loader",
          {
            loader: "postcss-loader".options: {
              plugins: [require("autoprefixer")],}},"less-loader",].// Parse principles from right to left},],}};Copy the code

Styles can be prefixed automatically by postCSs-loader

Create a postcss.config.js file in the project root directory and configure it as follows:

module.exports = {
  plugins: [require("autoprefixer")].// Just reference the plugin
};
Copy the code

1.8.2 file-loader and URl-loader Package images, fonts, media, and other files

File-loader is used to process the file name and path, and parse the URL of the file, and move the file to the output directory

Url-loader is used together with file-loader. The function is similar to file-loader. If the file size is smaller than the specified size, the url-loader is used together with file-loader. Base64 encoding is returned, otherwise file-loader is used to move the file to the output directory.

// webpack.config.js
module.exports = {
  // Omit other configurations...
  module: {
    rules: [
      // ...
      {
        test: /\.(jpe? g|png|gif)$/i.// Image file
        use: [
          {
            loader: "url-loader".options: {
              limit: 10240.fallback: {
                loader: "file-loader".options: {
                  name: "img/[name].[hash:8].[ext]",},},},},],}, {test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\? . *)? $/.// Media file
        use: [
          {
            loader: "url-loader".options: {
              limit: 10240.fallback: {
                loader: "file-loader".options: {
                  name: "media/[name].[hash:8].[ext]",},},},},],}, {test: /\.(woff2? |eot|ttf|otf)(\? . *)? $/i./ / font
        use: [
          {
            loader: "url-loader".options: {
              limit: 10240.fallback: {
                loader: "file-loader".options: {
                  name: "fonts/[name].[hash:8].[ext]",},},},},],},};Copy the code

1.8.3 Using babel-loader and babel-core to escape JS files

We can use Babel for ES6 compatibility

Version mapping between babel-loader and babel-core:

  1. Babel-loader 8.x corresponds to babel-core 7.x
  2. Babel-loader 7.x corresponds to babel-core 6.x
  3. Babel-loader will only convert es6/7/8 syntax to ES5 syntax
  4. We need babel-Polyfill to help us transform promises, generators, sets, Maps, proxies, etc
npm i -D babel-loader @babel/preset-env @babel/core @babel/polyfill
Copy the code
// webpack.config.js
module.exports = {
  entry: ["@babel/polyfill", path.resolve(__dirname, ".. /src/index.js")].// Omit other configurations...
  module: {
    rules: [{test: /\.js$/,
        use: {
          loader: "babel-loader".options: {
            presets: ["@babel/preset-env"],}},exclude: /node_modules/,},],},};Copy the code

1.9 the plugin plug-in

A plug-in is an extension of a Loader to perform functions that a Loader cannot perform.

The Webpack plug-in is a javascript object with the Apply method. The apply method is called by Webpack Complier.

plugins: [new webpack.BannerPlugin("hello webpack")];
Copy the code

Commonly used the plugin:

1.9.1 clean-webpack-plugin Removes residual packaging files

Each time we execute NPM run build, we will find that the dist folder remains the last packed file. We recommend a plugin to help us clean the folder clean-webpack-plugin before packing the output

npm i -D clean-webpack-plugin
Copy the code
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
  / /... Omit other configurations
  plugins: [new CleanWebpackPlugin()],
};
Copy the code

1.9.2 HTml-webpack-plugin replaces HTML template files

The main function is to generate the DESIRED HTML file according to the HTML template in the project (or not), and insert the JS and CSS resources built by us. Often used to modify HTML titles, inject meta tags, inject custom variables into HTML templates, and so on. For building multi-page applications, for every HTML file required, an HTML-webpack-plugin is added and chunks are introduced.

npm i -D html-webpack-plugin
Copy the code
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  mode: "development".// Development mode
  entry: {
    main: path.resolve(__dirname, ".. /src/main.js"),
    header: path.resolve(__dirname, ".. /src/header.js"),},output: {
    filename: "[name].[hash:8].js".// The packaged file name
    path: path.resolve(__dirname, ".. /dist"), // The packaged directory
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, ".. /public/index.html"),
      filename: "index.html".chunks: ["main"].// The module name corresponding to the entry file
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, ".. /public/header.html"),
      filename: "header.html".chunks: ["header"].// The module name corresponding to the entry file})]};Copy the code

1.9.3 Mini-CSS-extract-plugin Extract CSS files

Example Remove the CSS generation file. If introduced this plug-in, you will need to need to use in the CSS file related loaders MiniCssExtractPlugin. Replace style – loader loader.

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
  / /...
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].[hash].css".chunkFilename: "[id].css",})],modules: {
    rules: [{test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"."less-loader"],},],},};Copy the code

1.9.4 extract-text-webpack-plugin@next Split the CSS File

If you want to split into one-to-one CSS files, we need to use the extract-text-webpack-plugin, which is currently not supported by the Mini-CSS-extract-plugin. We need to install @next version of the extract-text-webpack-plugin.

npm i -D extract-text-webpack-plugin@next
Copy the code
// webpack.config.js
const path = require("path");
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin");
let indexLess = new ExtractTextWebpackPlugin("index.less");
let indexCss = new ExtractTextWebpackPlugin("index.css");
module.exports = {
  module: {
    rules: [{test: /\.css$/,
        use: indexCss.extract({
          use: ["css-loader"],})}, {test: /\.less$/,
        use: indexLess.extract({
          use: ["css-loader"."less-loader"],}),},],}plugins: [indexLess, indexCss],
};
Copy the code

1.9.5 HotModuleReplacementPlugin hot reloading the page

Replace, add, or remove modules while the application is running without reloading the entire page.

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

  2. Update only the changes to save valuable development time.

  3. Styling is faster – almost as fast as changing styles in the browser debugger.

Points to note in development:

  1. In webpack-dev-server, you need to set hot to true.

  2. Style – loader supports hot replacement, but on a section to pull away the CSS file to introduce MiniCssExtractPlugin. Loader temporarily does not support hot replacement, thus in need of the development environment, the style – loader, Or introduce CSS-hot-loader.

  3. To implement hot replacement of components in the React project, react-hot-loader is required. Vue-loader has implemented HMR, so there is no need to add other loaders.

1.9.6 Commons-chunk-plugin Removing common JS (webpack@3)

This plugin is used to extract common code from multiple chunks of entry, which was common before webpack@4. In webpack@4, this functionality is implemented using optimization.splitChunks, with an internal implementation based on the built-in SplitChunksPlugin.

1.9.7 Uglifyjs-webpack-plugin code compression (webpack@3)

Code compression, obfuscation, tree-shaking. So common that WebPack is already built in.

2.0 devServer server

During development we can ask WebPack to start a local server for us, which can:

  1. Let the browser listen to your code changes, and automatically refresh to display the modified results;
  2. Proxies that provide AJAX interfaces to solve cross-domain problems in development environments

Parameters:

  1. host[string]
  2. port[number]
  3. DisableHostCheck [Boolean] Set this parameter to true if bound domain name access is required.
  4. AllowedHosts [array] whitelist of allowedHosts
  5. ContentBase [Boolean | string | array] access server IP/domain name, the corresponding access folder in your project
  6. Index [string] Indicates the home page
  7. Hot [Boolean] Indicates whether the update is hot
  8. ClientLogLevel [string] Log level
  9. Stats Statistics
devServer: {
    contentBase: './public'.// The directory where the page is loaded by the local server
    historyApiFallback: true.// Does not jump to a single page when route switchover is applied
    inline: true.// Refresh in real time
    port: 8080.proxy: {
      '/api': { // If the interface has API flags, you need to start the proxy
        target: 'http://localhost:8001'.changeOrigin: true.// Target is a domain name.
        secure: false  // Set a proxy that supports HTTPS without checking whether it is secure}}}Copy the code

2.1 NPM command

Configure NPM run in package.json

Package webpack -p –progress –mode production –config webpack.config.build.js

Service test webpack-dev-server –open

"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1"."product": "cross-env NODE_ENV=dev webpack-dev-server --progress --mode development --config webpack.config.dev.js"."build": "webpack -p --progress --mode production --config webpack.config.build.js"."testBuild": "webpack-cli --entry ./app/main.js --output ./public/bundle.js"."dev": "webpack-dev-server --open"
},
Copy the code

Webpack packaging vue

  1. Vue-loader parses. Vue files
  2. Vue-template-compiler is used to compile templates
npm i -D vue-loader vue-template-compiler vue-style-loader
npm i -S vue
Copy the code
const vueLoaderPlugin = require("vue-loader/lib/plugin");
module.exports = {
  module: {
    rules: [{test: /\.vue$/,
        use: ["vue-loader"],},],},resolve: {
    alias: {
      vue$: "vue/dist/vue.runtime.esm.js"."@": path.resolve(__dirname, ".. /src"),},extensions: ["*".".js".".json".".vue"],},/ /... Omit other configurations
  devServer: {
    port: 3000.hot: true.contentBase: ".. /dist",},plugins: [new Webpack.HotModuleReplacementPlugin(), new vueLoaderPlugin()],
};
Copy the code

Under the vue webpack. Config. Js

// webpack.config.js
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin");
const vueLoaderPlugin = require("vue-loader/lib/plugin");
const Webpack = require("webpack");
module.exports = {
  mode: "development".// Development mode
  entry: {
    main: path.resolve(__dirname, ".. /src/main.js"),},output: {
    filename: "[name].[hash:8].js".// The packaged file name
    path: path.resolve(__dirname, ".. /dist"), // The packaged directory
  },
  module: {
    rules: [{test: /\.vue$/,
        use: ["vue-loader"],}, {test: /\.js$/,
        use: {
          loader: "babel-loader".options: {
            presets: [["@babel/preset-env"],},},}, {test: /\.css$/,
        use: [
          "vue-style-loader"."css-loader",
          {
            loader: "postcss-loader".options: {
              plugins: [require("autoprefixer"],},},],}, {test: /\.less$/,
        use: [
          "vue-style-loader"."css-loader",
          {
            loader: "postcss-loader".options: {
              plugins: [require("autoprefixer")],}},"less-loader",],},],},resolve: {
    alias: {
      vue$: "vue/dist/vue.runtime.esm.js"."@": path.resolve(__dirname, ".. /src"),},extensions: ["*".".js".".json".".vue"],},devServer: {
    port: 3000.hot: true.contentBase: ".. /dist",},plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, ".. /public/index.html"),
      filename: "index.html",}).new vueLoaderPlugin(),
    new Webpack.HotModuleReplacementPlugin(),
  ],
};
Copy the code

Differences between development and production environments

In the actual application of the project, we need to distinguish the development environment and production environment, we added two files on the basis of the original webpack.config.js

  1. Development environment configuration file webpack.dev.js Development environment mainly implements hot update, do not compress the code, complete sourceMap

  2. Webpack.prod. js Production environment configuration file The production environment is mainly to achieve compression code, extract CSS files, reasonable sourceMap, split code

The following modules need to be installed:

npm i -D  webpack-merge copy-webpack-plugin optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin
Copy the code

Webpack packaged the react

cnpm install babel-loader babel-core babel-preset-react babel-preset-es2015 --save-dev
Copy the code
// webpack.config.js
const path = require("path");
module.exports = {
  entry: path.resolve(__dirname, "./public/main.js"),
  output: {
    path: path.resolve(__dirname, "./public/out"),
    filename: "bundle.js",},module: {
    loaders: [{test: /\.jsx? $/,
        loaders: ["babel-loader? presets[]=es2015,presets[]=react"],},],},};Copy the code

Webpack optimizes configuration

Build speed refers to how quickly we update the code after each change and how quickly we package the files before release.

1.1 Narrowing the file search scope

  1. Alias: When import ‘vue’ appears in our code, Webpack does a recursive upward search to node_modules. To reduce the search area we can simply tell Webpack which path to look for. This is the configuration of aliases.
  2. Include Exclude Also reduces the search conversion time of the WebPack Loader.
  3. NoParse When we import jq from ‘jquery’ in our code, WebPack will parse whether the jQ library is dependent on other packages. However, we generally assume that we don’t refer to other packages (except for special ones, you can judge by yourself) for libraries such as jquery. Add a noParse attribute that tells WebPack not to parse to increase packaging speed.
  4. Extensions WebPack looks for files based on the suffix defined by extensions (more frequent file types go first)

1.2 Enable Multi-process Loader Conversion using HappyPack

Most of the time spent in webPack building is actually spent on loader parsing and conversion and code compression. In daily development, we need to use Loader to convert JS, CSS, pictures, fonts and other files, and the amount of file data to convert is also very large. Due to the single-threaded nature of JS, these conversion operations cannot process files concurrently, but need to process files individually. The basic principle of HappyPack is to reduce the total build time by splitting the task into several sub-processes, which then send the results to the main process

npm i -D happypack
Copy the code

1.3 Remove a third-party Module

Here, we use the DllPlugin DllReferencePlugin built in WebPack to extract it and create webpack.dll.config.js in the same directory as the WebPack configuration file

// webpack.dll.config.js
const path = require("path");
const webpack = require("webpack");
module.exports = {
  // The array of modules you want to pack
  entry: {
    vendor: ["vue"."element-ui"],},output: {
    path: path.resolve(__dirname, "static/js"), // The output location of the packaged file
    filename: "[name].dll.js".library: "[name]_library".// This needs to be consistent with 'name: '[name]_library',' in webpack.dllPlugin.
  },
  plugins: [
    new webpack.DllReferencePlugin({
      context: __dirname,
      manifest: require("./vendor-manifest.json"),}),new CopyWebpackPlugin([
      // copy the generated files to the dist directory so you don't have to go to CV manually each time
      { from: "static".to: "static"},]),new webpack.DllPlugin({
      path: path.resolve(__dirname, "[name]-manifest.json"),
      name: "[name]_library".context: __dirname,
    }),
  ],
};
Copy the code
"dll": "webpack --config build/webpack.dll.config.js"
Copy the code

conclusion

The above summarizes the common operation of Webpack, Webpack is a front-end code integration of a tool, we need to use more in the actual work, to understand his design essence.

reference

  1. Webpack document webpack.js.org/