The Plugin plug-in

Loader enables WebPack to handle more file resources throughout the webpack process. Plugin exists in the entire WebPack packaging process. The content being processed can be processed at the moment a hook is triggered by webpack exposure. So we can use plugin to do all sorts of things with the files we are processing.

Processing of index.html files

Previously we made a copy of index.html to the dist folder. If index.html needs to be changed dynamically, this is not a good process. We can use a plug-in HtmlWebpackPlugin to generate our packed HTML file and process the project file.

project

  webpack-demo
  |- package.json
  |- package-lock.json
  |- /dist
    |- main.js
    |- main.js.LICENSE.txt
-   |- index.html
  |- /src
    |- icon.png
    |- index.less
    |- index.js
  |- webpack.config.js
  |- postcss.config.js
  |- .browserslistrc
+ |- index.html
Copy the code

Install the appropriate plug-in dependencies

npm install --save --dev html-webpack-plugin
Copy the code

webpack.config.js

+ const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  ...
+  plugins: [
+    new HtmlWebpackPlugin({
+      template: path.join(__dirname, "./index.html"),  //./index.html is used as a template to generate dist/index.html+}), +],... };Copy the code

index.html

<! DOCTYPE html><html>
  <head>
    <meta charset="utf-8" />
    <title>Getting Started</title>
  </head>
  <body></body>
</html>

Copy the code

Re-run the NPM run build and view the dist/index.html file.

<! doctype html><html><head><meta charset="utf-8"/><title>Getting Started</title><script defer="defer" src="main.js"></script></head><body></body></html>
Copy the code

You can see that the main.js file is inserted with the script tag. This is what the HtmlWebpackPlugin plugin inserted in dist/index.html. Of course, the plugin also has some interesting ways to dynamically generate index.html, which is left to the reader to explore.

Hot update configuration

Every time we changed the source code, WebPack had to repackage the file and refresh the browser to see the effect, which was a terrible experience for developers. We can use hot updates to improve the development experience. When we make changes to the source code, hot updates allow our changes to show up quickly in the browser. Webpack provides three ways to implement hot updates. In this case, we currently use webpack-dev-server. Other ways can be found here.

Install dependencies

npm install --save --dev webpack-dev-server cross-env
Copy the code

Install dependencies on webpack-dev-server, which is used to provide hot update services, and cross-env, which is used to easily inject variables in the package.json command line.

webpack.config.js

module.exports = {
  output: {... }, + target:"web",
+ mode: "development",
+ devtool: "inline-source-map",
+ devServer: {
+   contentBase: path.resolve(__dirname, "dist"),
+   hot: "localhost",
+   compress: true,
+   port: 3002, +},module: {... }};Copy the code
  • Mode: configuration environment, including development and production modes. If this parameter is not set, the production mode is set by default.
  • Devtool: controls whether the source map is generated. With source Map, we can effectively debug the source map in the browser in the development environment, but in the production environment, it is recommended to disable.
  • DevServer: configuration of the development environment. For details, you can go to the official website.

package.json

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"."build": "webpack",
+   "dev": "cross-env NODE_ENV=development webpack serve --progress --hot --config webpack.config.js"
  },
Copy the code

NODE_ENV= after cross-env can be set to the environment variable when Webpack runs in Node. –config is the webPack configuration file that is specified to execute.

Run the command line NPM run dev in the terminal. The terminal displays after the operation is successful.

Project is running at http://localhost:3002/ℹ "WDS" : Webpack output is servedfrom/ ℹ "WDS" : Content notfrom webpack is served from /Users/liwangping/Desktop/study/webpack-demo/dist
Copy the code

The above lines of output show that the project is running at http://localhost:3002/. Click open. Then try to change the code in the source file.

src/index.js

function component() {...// Lodash, currently included via a script, is required for this line to work
- element.innerHTML = _.join(["Hello"."webpack"]."");
+ element.innerHTML = _.join(["Hello1"."webpack"].""); . }document.body.appendChild(component());
Copy the code

After the change, save the file and then observe the browser.

At this point, the hot update is successful, as is changing the properties in the LESS file.

src/index.less

body {
- background-color: red;
+ background-color: blue;
  transition: background-color .4s;
}
Copy the code

Page shows

Webpack configuration file separation

In the current webpack.config.js configuration, we currently implement the dev environment configuration, but it should not be the same for development and production environments, such as source map should not be present in production environments. Webpack-dev-server should also not be in production. But at the same time, production and development have some of the same configuration, so we can split the WebPack configuration file into three files. A common configuration file is written with two different environment configuration files, and when used, that same configuration file is combined with the development environment configuration file to complete the development environment configuration. The production environment is the same. To do this, we need to use the Webpack-Merge plug-in that merges the WebPack configuration files.

Install dependencies for merging different WebPack configuration files

npm install --save --dev webpack-merge
Copy the code

project

  webpack-demo
  |- package.json
  |- package-lock.json
  |- /dist
    |- main.js
    |- main.js.LICENSE.txt
  |- /src
    |- icon.png
    |- index.less
    |- index.js
  |- postcss.config.js
  |- .browserslistrc
  |- index.html
- |- webpack.config.js
+ |- webpack.common.js
+ |- webpack.dev.js
+ |- webpack.build.js
Copy the code

webpack.common.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/index.js".// The entry to the package file from which WebPack will start to analyze the dependency structure of the entire project
  output: {
    filename: "main.js".// The output file name
    path: path.resolve(__dirname, "dist"), // Output folder
  },
  module: {
    rules: [{test: /\.(css|less)$/i,
        use: [
          {
            loader: "style-loader"}, {loader: "css-loader"}, {loader: "postcss-loader"}, {loader: "less-loader",},],}, {test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: "asset/resource"}, {test: /\.(png|svg|jpg|gif)$/i,
        type: "asset/resource"}, {test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: "asset/resource"}, {test: /\.(csv|tsv)$/i,
        use: ["csv-loader"],}, {test: /\.xml$/i,
        use: ["xml-loader"],},],},plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "./index.html"), //./index.html is used as a template to generate dist/index.html})]};Copy the code

webpack.dev.js

const { merge } = require("webpack-merge");
const path = require("path");
const common = require("./webpack.common");

module.exports = merge(common, {
  target: "web".mode: "development".devtool: "inline-source-map".devServer: {
    contentBase: path.resolve(__dirname, "dist"),
    hot: "localhost".compress: true.port: 3045,}});Copy the code

webpack.build.js

const { merge } = require("webpack-merge");
const common = require("./webpack.common");

module.exports = merge(common, {
  mode: "production"});Copy the code

package.json

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
-   "build": "webpack",
+   "build": "cross-env NODE_ENV=production webpack --progress --config webpack.build.js",
-   "dev": "cross-env NODE_ENV=development webpack serve --progress --hot --config webpack.config.js"
+   "dev": "cross-env NODE_ENV=development webpack serve --progress --hot --config webpack.dev.js"
  },
Copy the code

Run NPM run dev and NPM run build respectively.

Babel configuration

Babel is designed to make the most of the latest JS syntax we write across browsers. Because different browser vendors have different levels of support for the ES syntax standard, Babel smoothen the differences at the bottom, allowing us to use new syntax in projects without worrying about compatibility issues.

Let’s install Babel for the WebPack project.

So far all we need is the smart preset set of the smallest set. So @babel/preset-env is enough for now, and more configurations can be found on Babel’s official website.

project

  webpack-demo
  |- package.json
  |- package-lock.json
  |- /dist
    |- main.js
    |- main.js.LICENSE.txt
  |- /src
    |- icon.png
    |- index.less
    |- index.js
  |- postcss.config.js
  |- .browserslistrc
  |- index.html
  |- webpack.common.js
  |- webpack.dev.js
  |- webpack.build.js
+ |- babel.config.json
Copy the code

Install dependencies

npm install --save-dev babel-loader @babel/core
Copy the code

webpack.common.js

module.exports = {
  ...
  module: {
    rules: [{...test: /\.xml$/i,
        use: ["xml-loader"],
      },
 +    {
 +      test: /\.js$/,
 +      exclude: /node_modules/,
 +      use: {
 +        loader: "babel-loader", +}, +},],},plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "./index.html"), //./index.html is used as a template to generate dist/index.html})]};Copy the code

Install the @babel/preset-env dependency

npm install @babel/preset-env --save-dev
Copy the code

babel.config.json

{
  "presets": ["@babel/preset-env"]}Copy the code

Then run NPM run dev to start writing code for the new syntax.

Support the react

React is easy to configure because Babel has the ability to convert JSX syntax to JS. After installing the React core library, modifying the entry file, and configuring Babel to support JSX syntax, we can write React in our project.

project

  webpack-demo
  |- package.json
  |- package-lock.json
  |- /dist
    |- main.js
    |- main.js.LICENSE.txt
  |- /src
    |- icon.png
    |- index.less
-   |- index.js
+   |- index.jsx
  |- postcss.config.js
  |- .browserslistrc
  |- index.html
  |- webpack.common.js
  |- webpack.dev.js
  |- webpack.build.js
  |- babel.config.json
Copy the code

Install react dependencies

npm install --save react react-dom
Copy the code

src/index.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import './index.less';

const App = () = > {
  return <div>App134</div>;
};

ReactDOM.render(<App />.document.getElementById("root"));

Copy the code

index.html

<! DOCTYPE html><html>
  <head>
    <meta charset="utf-8" />
    <title>Getting Started</title>
  </head>
  <body>
+    <div id="root"></div>
  </body>
</html>

Copy the code

Add a root node to make the REACT generated DOM mount on the div with the root id.

Install Babel so react JSX files can be processed

npm install --save-dev @babel/preset-react
Copy the code

babel.config.json

{-"presets": ["@babel/preset-env"]
+  "presets": ["@babel/preset-env"."@babel/preset-react"]}Copy the code

Added react preset set @babel/preset-react.

webpack.common.js

module.exports = {
-  entry: "./src/index.js".// The entry to the package file from which WebPack will start to analyze the dependency structure of the entire project
+  entry: "./src/index.jsx".// The entry to the package file from which WebPack will start to analyze the dependency structure of the entire project.module: {
    rules: [
      ...
      {
-       test: /\.js$/,
+       test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",},},],},... };Copy the code

Modify the entry and file format matched by loader. Then run NPM run dev and the JSX file is parsed successfully.

Support for ts

The idea of supporting TS is also simple, as TS can also be converted to JS via Babel, as can TSX. So we just need to support TS/TSX on our existing Babel setup, and we can write ts/ TSX files.

peoject

  webpack-demo
  |- package.json
  |- package-lock.json
  |- /dist
    |- main.js
    |- main.js.LICENSE.txt
  |- /src
    |- icon.png
    |- index.less
-   |- index.jsx
+   |- index.tsx
  |- postcss.config.js
  |- .browserslistrc
  |- index.html
  |- webpack.common.js
  |- webpack.dev.js
  |- webpack.build.js
Copy the code

Change the name of the index.jsx file under SRC to index.tsx.

Install dependencies

npm install --save-dev @babel/preset-typescript
Copy the code

webpack.common.js

module.exports = {
  output: {
    filename: "main.js".// The output file name
    path: path.resolve(__dirname, "dist"), // Output folder
  },
+  resolve: {
+    extensions: [".ts".".tsx".".js".".json"] +},module: {
    rules: [{...test: /\.xml$/i,
        use: ["xml-loader"],
      },
      {
-       test: /\.(js|jsx)$/,
+       test: /\.(ts|tsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",},},],},... };Copy the code

Add the tsconfig configuration file

{
  "compilerOptions": {
      "outDir": "./dist/"."sourceMap": true."noImplicitAny": true."esModuleInterop": true."module": "commonjs"."target": "es5"."noUnusedLocals": true."jsx": "react"
  },
  "include": [
      "./src/**/*"]}Copy the code

If you need more configurations, refer to this.

Note: The editor opens SRC /index.tsx if you see an error

Could not find a declaration file for module 'react'. '/Users/*********/Desktop/study/webpack-demo/node_modules/react/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/react` if it exists or add a new declaration (.d.ts) file containing `declare module 'react'; `ts(7016)
Copy the code

Install @types/react. Install @types/react. Install @types/react. NPM I — save-dev@types /react Other similar errors are treated in the same way. Here is just an example, specific look at your own need to install the package, such a tip solution is the same treatment. NPM I — save-dev@types/NPM package name

At this point, the TS support environment is ready, run it and try it out.

A simple WebPack environment has now been configured. Of course, now this is far from enough, there are some configuration needs to continue, such as:

  • Jest unit test environment setup
  • Alias Alias unification
  • Eslint,stylelint syntax configuration
  • . Prettierrc Style configuration
  • Repair and validation of submitted files during HusKY triggered Lint-staged periods
  • Mock. Js environment setup
  • Webpack performance optimization section (build, development, output, etc.)

, etc.

We will continue to refine these later. Hope everyone can not understand the question directly comment, or issue better. All commit records will be placed on Git. Follow the entire setup process. I hope I can help you. Welcome star, comments. Your likes are the biggest motivation for me to write.