React + less + TS supports webpack-based scaffolding from scratch. Mainly for the entry, hope to build the whole idea to speak clearly, to help novice build a simple Webpack scaffolding. Those who already have relevant experience are not suitable. Unit testing, Webpack optimization and other content will be added later as a summary of personal learning. Github address for this article. Welcome to star or comment on issues. The corresponding commit on Git also records the setup and comments. You can just look at COMMIT to learn.

Note: Webpack version of this article is above 5

What is Webpack?

In short, WebPack is a static module wrapper for modern JS applications. The picture on the official website also succinctly illustrates the corresponding relationship. In a project, because various file resources depend on each other (for example, HTML introduces image, font resources, and so on). Webpack can build a dependency graph by analyzing dependencies between files, and then recursively integrate multiple resources into a final static resource through the dependency graph. But the specific principle is not the in-depth point of this article, here is probably an impression, let us continue to the next step.

Initialize the project

First we need to create a project, initialize NPM, and install WebPack and WebPack-CLI locally. Here is the command line executed at the terminal.

mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev
Copy the code

Now we create the following directory files and their corresponding contents under the root directory.

Project Contents:

webpack-demo
  |- package.json
+ |- index.html
+ |- /src
+   |- index.js
Copy the code

src/index.js

function component() {
  const element = document.createElement('div');

  // Lodash, currently included via a script, is required for this line to work
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');

  return element;
}

document.body.appendChild(component());
Copy the code

index.html

<! DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Getting Started</title> <script SRC = "https://unpkg.com/[email protected]" > < / script > < / head > < body > < script SRC = ". / SRC/index. Js "> < / script > < / body > < / HTML >Copy the code

This is the original way to use the LoDash library. When we run index. HTML in a browser, we can see hello WebPack displayed on the page. This is because index. HTML introduced the LoDash library via script tags. That’s why _. Join in index.js spells [‘Hello’, ‘webpack’] into ‘Hello webpack’. But there are several problems:

  1. Lodash exists globally, and execution of the index.js file depends on lodash.js.
  2. Index.js will not even execute if it lacks dependencies or contains the wrong order.
  3. Lodash may not be in use, but browsers will still load the library.

So how does WebPack manage these situations?

Creating a bundle

Let’s adjust the project structure first.

  webpack-demo
  |- package.json
+ |- /dist
+   |- index.html
- |- index.html
  |- /src
    |- index.js
Copy the code

Install the Lodash package locally

First we need to download the loDash package in the project root directory via NPM.

npm install --save lodash
Copy the code

The node_modules folder appears after the download. This is the folder where THE NPM download is saved in the local library. Open it and you can see the source of the LoDash library.

Then change the following two files.

src/index.js

+import _ from 'lodash';

 function component() {
   const element = document.createElement('div');

   element.innerHTML = _.join(['Hello', 'webpack'], ' ');

   return element;
 }

 document.body.appendChild(component());
Copy the code

Here loDash is imported via import. Let’s change the script tag in index.html.

dist/index.html

<! DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Getting Started</title> - <script SRC = "https://unpkg.com/[email protected]" > < / script > < / head > < body > - < script SRC = ". / SRC/index. Js "> < / script > + < script src="main.js"></script> </body> </html>Copy the code

The files in the project can then be packed by executing NPX Webpack in the terminal (NPX Webpack packs the current project using webPack’s default packaging configuration).

Asset main.js 69.5 KiB [emitted] [Notifying Note] (name, note: main) 1 related asset runtime modules 1010 bytes 5 modules cacheable modules 532 KiB ./src/index.js 297 bytes [built] [code generated] ./node_modules/lodash/lodash.js 531 KiB [built] [code generated]Copy the code

You can see from the output above that two things are packaged: index.js and lodash in node_modules. The project folder will look like this.

webpack-demo |- package.json + |- package-lock.json |- /dist + |- main.js + |- main.js.LICENSE.txt |- index.html |- /src  |- index.jsCopy the code

Mian.js is what we packaged. Dist /index.html import it. SRC /index.js instead executes import _ from ‘lodash’. So in SRC /index.js, _. Join can be executed. So the _. Join in index.js would not have been executed if we hadn’t said import _ from ‘lodash’ in SRC /index.js. Because WebPack analyzes import statements, it knows whether the current script (SRC /index.js) needs to import the LoDash library, thus avoiding global contamination by LoDash. That solves those problems.

Well, at this point, you probably have a general idea of how WebPack packaging differs from traditional Script tag imports. So let’s go further and configure the whole project.

Creating a Configuration File

Webpack can be configured using the corresponding configuration file, or you can run the configuration directly from the command line, in this case using the configuration file. Next we create a configuration file (webpack.config.js).

project

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

webpack.config.js

const path = require('path'); Module.exports = {entry: './ SRC /index.js', // the entry to the package file from which webPack will start to parse the dependencies of the entire project output: {filename: Resolve (__dirname, 'dist'), // Output folder},};Copy the code

Here, the two fields entry and output represent the starting and ending points of the entire Webpack packaging process. Entry specifies that the packaging process starts from SRC /index.js, and Output specifies some attributes of the output file. See the comments in the code above for details.

Now we can run NPX webpack –config webpack.config.js to package the project.

. [$] <((git)-[master]-)> NPX webpack --config webpack.config.js Asset main.js 69.5 KiB [emitted] [Notifying Note] (name, note, note) main) 1 related asset runtime modules 1010 bytes 5 modules cacheable modules 532 KiB ./src/index.js 297 bytes [built] [code generated] ./node_modules/lodash/lodash.js 531 KiB [built] [code generated]Copy the code

npm scripts

It would be a bit taxing if we had to type a bunch of commands like this every time, so we can add to the command line in package.json. Simplify related operations.

package.json

"scripts": {   
    "test": "echo \"Error: no test specified\" && exit 1",
 +  "build": "webpack" 
 },
Copy the code

Instead of NPX webpack –config webpack.config.js, we execute the corresponding NPM run build. Webpack.config. js is the default webpack package, so it will be used by default if not specified after NPM run build.

Static resource packaging

As you can see from the previous steps, we packaged the source code for the project and the JS library we used and imported it through index.html. This can set up the entire project, but WebPack only supports parsing JS and JSON files by default. PNG, CSS and other resources cannot be parsed. So what if we need to introduce static resources into our project? Webpack handles this type of static resource using a loader. So what is loader?

Loader

Loader can let WebPack handle other types of files besides JS and JSON. Add them to webpack’s resource dependency graph. Let’s try adding the ability to parse less files to WebPack.

Less File parsing

** To increase dependencies, ** run the following command in the project directory.

npm install --save-dev style-loader css-loader less-loader less
Copy the code

webpack.config.js

module.exports = {
  ...
  module: {    
        rules: [
 +          {  
 +             test: /\.(css|less)$/i,
 +             use: [         
 +                   {   loader: "style-loader"   },
 +                   {   loader: "css-loader"     },
 +                  {   loader: "less-loader"  }, 
 +             ],      
 +         }, 
         ],
  },
  ...
};
Copy the code
  • Style-loader: Used to inject CSS styles into the header of index. HTML as style tags.
  • Less-loader: indicates the loader that processes less.

project

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

src/index.less

body { background-color: red; }Copy the code

Run NPM run build and you can see that the package was successful. Open a browser to preview the effect.

The image above shows that the LESS file is compiled.

But sometimes we need to deal with CSS prefixes for compatibility. At this point we can use the Loader of PostCSS to do this.

Install dependencies

npm install --save--dev autoprefixer cssnano postcss postcss-loader
Copy the code

project

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

webpack.config.js

module.exports = {
  ...
  module: {    
        rules: [
           {  
              test: /\.(css|less)$/i,
              use: [         
                    {   loader: "style-loader"   },
                    {   loader: "css-loader"     },
+                   {   loader: "postcss-loader"  },
                    {   loader: "less-loader"  }, 
              ],      
          }, 
         ],
  },
  ...
};
Copy the code

postcss.config.js

Module. exports = {plugins: [// automatic plugins ("autoprefixer"), // automatic plugins ("cssnano"),],};Copy the code

.browserslistrc

> 0.25%
last 2 versions
Copy the code

Add a CSS style to ** SRC /index.less**.

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

Then we execute the NPM run build package and open the browser to check.

This indicates that the prefix has been successfully added. Here the LESS file has been prepared.

Image resource processing

Webpack5 already has built-in loading of resource modules, so it’s a little different from CSS loading.

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
Copy the code

webpack.config.js

const path = require("path");
module.exports = {  
    ...
    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",      
  +         },
          ],
     },
};
Copy the code

src/index.js

import _ from "lodash";
import "./index.less";
import iconPng from "./icon.png";

function component() {  
   const element = document.createElement("div");
   // Lodash, currently included via a script, is required for this line to work 
   element.innerHTML = _.join(["Hello", "webpack"], " ");  

   // Add the image to our existing div.  
+  const myIcon = new Image();  
+  myIcon.src = iconPng;  
+  element.appendChild(myIcon);  

    return element;
}

document.body.appendChild(component());
Copy the code

Then we execute the NPM run build package and open the browser to check.

The image loads normally.

In the same vein, you can increase parsing of other static resources. Other resource loading details can see the official documentation. Remember to install the appropriate Loader dependencies.

webpack.config.js

const path = require("path");
module.exports = {  
    ...
    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: /\.(woff|woff2|eot|ttf|otf)$/i,
+               type: "asset/resource", 
+           },
+           {
+                test: /\.(csv|tsv)$/i,
+                use: ["csv-loader"],
+            },
+            {
+                 test: /\.xml$/i,
+                 use: ["xml-loader"],
+             },          
        ],
     },
};
Copy the code

The next article