Make writing a habit together! This is my first day to participate in the “Gold Digging Day New Plan · April More text challenge”, click to see the details of the activity.

Webpack, as the most popular build tool at present, has almost become one of the necessary tools in front end development. If you want to advance the front end, knowing webPack configuration is also an essential part. However, it is also due to the configuration diversity of Webpack that many children who want to learn how to start Webpack are discouraged. Writing this article is mainly to share some experience and experience of using Webpack to everyone, but also to consolidate their own knowledge.

By default, you already have some knowledge of Node.js and WebPack when you watch this article.

Basic dependence

Want to build webpack scaffolding, we need to install webpack, webpack-serve, webpack-CLI, these three are essential.

We use PNPM for all of the following dependencies by default, with Node version 16.0.0

pnpm i webpack webpack-cli webpack-serve -D
Copy the code

After the installation, you can view the corresponding version on the console. If no corresponding version is added to the installation command, the latest stable version is used by default.

DevDependencies: + webpack 5.70.0 + webpack-cli 4.9.2 + webpack-serve 4.7.4Copy the code
Rely on version role
webpack 5.70.0 Core libraries offer a lotAPI
webpack-cli 4.9.2 Webpack command line tool to use Webpack by entering commands from the command line
webpack-serve 4.7.4 Webpack provides a server for development and debugging, which can be done by opening a page through a URL

Common configuration

Generally speaking, a complete project construction needs to distinguish the development environment from the production environment. There must be some common parts in these two environments, such as the common loader and plugin. Therefore, we will separate the configuration according to the actual situation.

Start by creating a build directory in the root directory and create a webpack.base.config.js file in it for some common configuration items.

Install the following dependencies

pnpm i copy-webpack-plugin -D
Copy the code
Rely on version role
copy-webpack-plugin 10.2.4 Use to copy static resource files such as public, otherwise introducing favicon.ico in HTML would be 404

Once created, add the following configuration to webpack.base.config.js.

// Introduce the path module
const path = require('path')

// Introduce static resource replication plug-in
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
  // Package entry address
  entry: {
    // Since it can be multiple pages, use the form of an object
    index: ['./src/views/index/index.js']},// Rule of module resolve
  resolve: {
    // Automatic extension suffixes, such as a js file, do not write.js when referencing
    extensions: ['.js'.'.json'.'.css'.'.less'].// Path alias
    alias: {
      The '@': path.join(__dirname, '.. /src')}},// Build target
  target: ['web'.'es5'].// Context is the context of webpack Entry and the absolute path to the directory where the entry file is located, which by default is the current root directory.
  // Since our webpack configuration file is in the build directory, we need to reset the context to point to the root directory.
  context: path.resolve(__dirname, '.. / '),
  
  plugins: [
    // Copy public static files to the specified location, excluding HTML files
    new CopyWebpackPlugin({
      patterns: [{from: path.resolve(__dirname, '.. /public'),
          globOptions: {
            dot: true.gitignore: true.ignore: ['**/*.html']}}]})]}Copy the code

The path module comes with Node.js and is mainly used to help us conveniently solve the problem of setting the path

Development Environment Configuration

The common configuration is over. Next, we need to configure the development environment to get the project running.

First, create the webpack.dev.config.js file in the build directory.

Then install the following dependencies

pnpm i webpack-merge html-webpack-plugin -D
Copy the code
Rely on version role
webpack-merge 5.8.0 Used to merge WebPack configuration items
html-webpack-plugin 5.5.0 The entry configuration entry is js file. Webpack uses JS file as the entry, encounters import, loads the import file with the configured loader, but the entry HTML opened as a browser is a file referencing entry JS. It is outside the whole compilation process, so we need the HTML-webpack-plugin to package the HTML file as an entry point

After the installation is complete, add the following configuration to webpack.dev.config.js.

// Introduce merge object plug-in
const { merge } = require('webpack-merge')

// Introduce the path module
const path = require('path')

// Introduce a packaged HTML plug-in
const HtmlWebpackPlugin = require('html-webpack-plugin')

// Import the base configuration file
const baseWebpackConfig = require('./webpack.base.config')

const devWebpackConfig = merge(baseWebpackConfig, {
  // Mode, mandatory
  mode: 'development'.// Enable persistent caching
  cache: {
    type: 'filesystem'.buildDependencies: {
      config: [__filename]
    }
  },

  output: {
    // Output file directory
    path: path.resolve(__dirname, '.. /dist'),
    // Output the file name
    filename: 'js/[name].js',},// Source mapping
  devtool: 'eval-cheap-module-source-map'.// Develop the service configuration
  devServer: {
    // Server host, default localhost
    host: '0.0.0.0'.// Server port number, default 8080
    port: 7001.// Static resource properties
    static: {
      // An accessible virtual address mounted to the server middleware
      // For example, if set to /static, the /static prefix is required when accessing server static files
      // Equivalent to the contentBasePublicPath property of [email protected]
      publicPath: '/'.// Tell the server where to supply the content
      directory: path.join(__dirname, '.. /public')},// The file that needs to be monitored can only be refreshed because it is a multi-page application and cannot be hot updated
    watchFiles: ['src/**/*']},/ / the plugin
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/views/index/index.html'.favicon: path.resolve(__dirname, '.. /public/favicon.ico')})]})module.exports = devWebpackConfig

Copy the code

Then create a public directory under the root directory for static resources such as favicon.ico

Then create a SRC /views/index directory in the root directory to store relevant service codes, and create index.html and index.js in the index directory

index.html

<! DOCTYPEhtml>
<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">
    <title></title>
  </head>
  <body>
    <div>index test</div>
  </body>
</html>

Copy the code

index.js

console.log('index.js')

Copy the code

The development environment is here, once the simple configuration is complete, then we add the run command to scripts in package.json

"serve": "webpack serve --progress --no-stats --config build/webpack.dev.config.js".Copy the code

Console run command

pnpm run serve
Copy the code

When there is the following information represents the console launched successfully, open a browser enter http://localhost:7001/index.html, found that the corresponding page and console in the information, so that one of the most simple development environment configuration.

Configure the loader

Webpack can only recognize.js files, so we need to configure some loaders to make the scaffolding function more complete.

Since loader configuration, whether in development or production, needs to be configured, we put these configuration items in webpack.base.config.js.

Style resource configuration

Start by installing the following plug-ins

pnpm i style-loader css-loader less-loader postcss-loader postcss autoprefixer mini-css-extract-plugin cross-env -D
Copy the code
Rely on version role
css-loader 6.7.1 Parsing CSS files
style-loader 3.3.1 Add the style tag parsed by CSS-Loader to the page. You are advised to use it in the development environment
less 4.1.2 Less core library
less-loader 10.2.0 Parsing less files
postcss 8.4.12 Postcss core library
postcss-loader 6.2.1 To use Autoprefixer, you need to use postCSS-Loader
postcss-preset-env 7.4.3 Find the configuration in Browserslist for PostCSS and load the specified CSS compatibility styles through the configuration
mini-css-extract-plugin server Separate style files, which do not coexist with style-loader. Recommended for production environment
cross-env server Run scripts that use cross-platform Settings and environment variables mainly to distinguish between the current environment and use style-loader or mini-CSs-extract-plugin

Once the installation is complete, add the following code to webpack.base.config.js


// ...

+ // Check whether the current environment is production
+ const isProduction = process.env.NODE_ENV === 'production'

+ // Separate styles into a single file
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  // ...
  context: path.resolve(__dirname, '.. / '),

  // Processing rules for different types of modules
+  module: {
+    rules: [
+      // Handle CSS, less files
+      {
+        test: /\.(css|less)$/,
+        use: [
+          isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
+          {
+            loader: 'css-loader',
+            options: {
+              // Whether to use source-map+ sourceMap: ! isProduction, +/ / compatible IE11
+              esModule: false
+            }
+          },
+          {
+            loader: 'postcss-loader',
+            options: {
+              // Whether to use source-map+ sourceMap: ! isProduction + } + }, +'less-loader'+} +] +}// ...
}
Copy the code

Then create.browserslistrc and postcss.config.js files in the root directory

.browserslistrc is used to tell the browser scope of PostCSS

defaults
not ie < 11
last 2 versions
> 1%
iOS 7
last 3 iOS versions

Copy the code

Postcss.config. js Configures postCSS configuration items

module.exports = {
  plugins: [
    'postcss-preset-env']}Copy the code

And modify the package again. Serve in a json command, then re-run, you will find both in js. Introduced in CSS. | less documents, can be applied to HTML, and also to the style and the corresponding browser compatible prefix.

- "serve": "webpack serve --progress --no-stats --config ./build/webpack.dev.config.js",
+ "serve": "cross-env NODE_ENV=development webpack serve --progress --no-stats --config ./build/webpack.dev.config.js",
Copy the code

Image Resource Configuration

Install html-loader to parse the image path in HTML

pnpm i html-loader -D
Copy the code

Then add the following configuration to webpack.base.config.js


// ...
module.exports = {
  // ...
  
  // Processing rules for different types of modules
  module: {
    rules: [
      // ...
+      // Parse the SRC path in HTML
+      {
+        test: /\.html$/,
+        use: 'html-loader'+ +}Webpack5 has deprecated url-loader and changed it to type
+      {
+        test: /\.(png|jpe? g|gif|svg)(\? . *)? $/,
+        type: 'asset',
+        exclude: [path.resolve(__dirname, 'src/assets/imgs')],
+        generator: {
+          filename: 'imgs/[name].[contenthash][ext]'+ +}},// ...]}// ...
}
Copy the code

After the configuration is complete, re-run the project and we will see that no matter how the image is used, it will be displayed correctly on the page.

Configuring font ICONS

To make the directory structure clearer and more elegant, let’s extract the font ICONS into a separate directory and add the following code to webpack.base.config.js


// ...
module.exports = {
  // ...
  
  // Processing rules for different types of modules
  module: {
    rules: [
      // ...
+      Webpack5 has deprecated url-loader and changed it to type
+      {
+        test: /\.(woff2? |eot|ttf|otf)(\? . *)? $/,
+        type: 'asset',
+        generator: {
+          filename: 'fonts/[name].[contenthash][ext]'+ +}},// ...]}// ...
}
Copy the code

In this way, our font icon can be exported to the fonts directory when packaging.

Configuring Audio Resources

Similarly, for audio processing, we also adopt the above way, add the following code in webpack.base.config.js


// ...
module.exports = {
  // ...
  
  // Processing rules for different types of modules
  module: {
    rules: [
      // ...
+      Webpack5 has deprecated url-loader and changed it to type
+      {
+        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\? . *)? $/,
+        type: 'asset',
+        exclude: [path.resolve(__dirname, 'src/assets/medias')],
+        generator: {
+          filename: 'medias/[name].[contenthash][ext]'+ +}},// ...]}// ...
}
Copy the code

Audio resources are introduced in HTML the same way images are introduced.

Configure javaScript syntax conversions

When we can use ES6 syntax, in IE11, we will find that the console error, this is due to syntax incompatibility, so we have a syntax conversion.

Due to the large number of browsers on the market, the syntax support degree of each browser is different. Therefore, in order to make the browser compatible with our javaScript code, we need to conduct compatibility processing for the syntax above ES6, that is, downgrade to ES5, to ensure the syntax compatibility of each browser. Take Internet Explorer 11 as an example.

Install the following plug-ins

pnpm i babel-loader @babel/core @babel/preset-env core-js -D
Copy the code
Rely on version role
babel-loader 8.2.4 Convert ES2015+ code to ES5
@babel/core 7.17.8 Babel core packages
@babel/preset-env 7.16.11 Presets for Babel compilation
core-js 3.21.1 The new es’ API ‘conversion feature is supported by most modern browsers
A collection of ‘API’ fixpacks to run

Add the following code to webpack.base.config.js


// ...
module.exports = {
  // ...
  
  // Processing rules for different types of modules
  module: {
    rules: [
      // ...
 +    {
 +       test: /\.(m|j)s$/,
 +       exclude: /node_modules/,
 +       use: [
 +         {
 +           loader: 'babel-loader',
 +           options: {
 +             cacheDirectory: true+} +} +] +}// ...]}// ...
}
Copy the code

Create the babel.config.json file in the root directory and add the following

{
  "presets": [["@babel/preset-env",
      {
        // useBuiltIns: false default, regardless of browser compatibility configuration, to introduce all polyfills
        // useBuiltIns: Entry introduces browser-incompatible polyfills based on configured browser compatibility
        // useBuiltIns: Usage polyfills according to the browser compatibility configured and the API used in your code to implement on-demand additions
        "useBuiltIns": "usage"."corejs": {
          "version": 3
        },
        "modules": false}}]]Copy the code

Once configured, re-project and you can happily use the ES5 syntax and display it perfectly on IE11.

With webpack.base.config.js and webpack.dev.config.js configured at this point, we finally need to package the project into a static project that can be easily deployed to the production server.

Production Environment Configuration

In the production environment, we will carry out some targeted project optimization, so as to facilitate the follow-up if the project is huge, there will not be too much time difference in construction speed.

Create webpack.pro.config.js in the root directory and add the following code

// Introduce merge object plug-in
const { merge } = require('webpack-merge')

// Introduce the path module
const path = require('path')

// Introduce a packaged HTML plug-in
const HtmlWebpackPlugin = require('html-webpack-plugin')

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

// Import the base configuration file
const baseWebpackConfig = require('./webpack.base.config')

const proWebpackConfig = merge(baseWebpackConfig, {
  // Mode, mandatory
  mode: 'production'.output: {
    // Output file directory
    path: path.resolve(__dirname, '.. /dist'),
    // Output the file name
    filename: 'js/[name].[contenthash].js'.// Clear the directory
    clean: true
  },

  // Source mapping
  devtool: false./ / the plugin
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/views/index/index.html'.filename: 'html/index.html'.favicon: path.resolve(__dirname, '.. /public/favicon.ico')}),new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash].css'})]})module.exports = proWebpackConfig

Copy the code

Add a package command to package.json

"build": "cross-env NODE_ENV=production webpack --config ./build/webpack.pro.config.js",
Copy the code

This is a basic packaging configuration, you can run PNPM run build to see the effect, you can see that the mainstream browser and IE11 with the development environment display is consistent.

Next, let’s do some packaging optimization

Install csS-minimizer-webpack-plugin to optimize CSS

pnpm i css-minimizer-webpack-plugin -D
Copy the code

Then add the new code to webpack.pro.config.js

// ...

+ / / compress CSS
+ const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')

+ const TerserPlugin = require('terser-webpack-plugin')

const proWebpackConfig = merge(baseWebpackConfig, {
  // ...
+  optimization: {
+    minimize: true,
+    minimizer: [
+      new CssMinimizerPlugin(),
+      new TerserPlugin({
+        terserOptions: {
+          // The production environment automatically deletes the console
+          compress: {
+            drop_debugger: true,
+            drop_console: true,
+            pure_funcs: ['console.log']
+          }
+        },
+        parallel: true,
+        exclude: /[\\/]node_modules[\\/]/
+      })
+    ],
+    splitChunks: {
+      cacheGroups: {
+        // Configure the extraction module scheme
+        default: false,
+        styles: {
+          name: 'styles',
+          test: /\.(css|less)$/,
+          chunks: 'all',
+          enforce: true,
+          priority: 10
+        },
+        vendors: {
+          name: 'chunk-vendors',
+          test: /[\\/]node_modules[\\/]/,
+          chunks: 'all',
+          priority: 2,
+          enforce: true,
+          reuseExistingChunk: true+} +} +}})module.exports = proWebpackConfig

Copy the code

Here, the optimization of our production environment is basically completed.

conclusion

Because the project is relatively small, too much optimization will increase the burden of construction, so this article will do some basic optimization, but also to consolidate the configuration of Webpack, after all, webpack configuration is many and complicated, it is inevitable that there will be forgotten.

Article Project Demo

Interested can pull code to run a look at ~