One, foreword

Webpack is a static module wrapper for modern JavaScript applications. So how does WebPack implement different types of resource module loading?

Yes, by loader. Loader converts the source code of a module. Loader allows you to preprocess files when importing or loading modules.

We take the following questions to thoroughly understand Loader ~

Why use loader

How does WebPack load resource modules? Let’s first try wrapping the CSS files in the project directly with WebPack.

Initialize a WebPack project in the following directory:

Create a new index. CSS file in the SRC directory. The purpose of creating this file is to use the CSS file as the entry point and try to use webPack to package it separately.

/* index.css */
body {
  margin: 0 auto;
  padding: 0 20px;
  width: 1000px;
  background-color: #ccc;
}
Copy the code

Adjust the Webpack configuration so that the entry file path is specified as the index. CSS path.

// webpack.config.js
module.exports = {
  entry: "./src/index.css".output: {
    filename: "bundle.js",}};Copy the code

Then we go to the terminal and run the NPX webpack command. You will see that the command line will prompt Module parse failed: Unexpected token (1:5) Module parse error.

Careful students will find a solution immediately following: You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.

Roughly speaking, you may need the appropriate loader to process this file type, there is currently no loader configured to process this file.

This is where loader becomes important.

3. How to configure loader

Continue with the problem of packing index. CSS. To load CSS files, we can try the common CSS-loader.

yarn add css-loader -D
Copy the code

Webpack configuration is also changed:

// webpack.config.js
module.exports = {
  mode: "none".// Avoid warnings when the packaging mode is not specified.module: {
    rules: [{test: /\.css$/,
        use: "css-loader",},],},};Copy the code

Add an array of rules objects to the Module property in the WebPack configuration. The value of the test attribute is a regular expression that matches the format of the file that is processed by the current Loader. The value of the use attribute is the loader name.

If you pack it up again, you won’t get an error.

If you want the index. CSS module to work on the page, just add an extra style-loader and the style is OK.

The function of the style-loader is to create a style tag that contains CSS styles. The tag is appended to the page last.

Note That multiple Loaders are configured in the following order:

  • The last loader is called earliest and will pass in the original resource content
  • The first loader is called last and the expected value is outgoing JavaScript and source map (optional)
  • When the intermediate loader executes, the output from the previous loader is passed in

So csS-loader goes last. The configuration is as follows:

// webpack.config.js
module.exports = {
  ...
  module: {
    rules: [{test: /\.css$/,
        use: ["style-loader"."css-loader"],},],},};Copy the code

[“style-loader”, “css-loader”, “less-loader”] [“style-loader”, “css-loader”, “less-loader”]

How to write a Loader

The general process you want to achieve:

Next, let’s try to implement a simple version of the csS-Loader and style-Loader shown above.

4.1 create a loader

We created css-loader.js and style-loader.js files in the project root directory.

The main code is as follows:

├ ─ ─ the SRC · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · source dir │ ├ ─ ─ index. The CSS · · · · · · · · · · · · · · · · · · · · · · · CSS module+ │ └ ─ ─ index. Js · · · · · · · · · · · · · · · · · · · · · · · · entry module
+ ├ ─ ─ CSS - loader. Js · · · · · · · · · · · · · · · · · · · · · · · CSS loader├ ─ ─ package. Json · · · · · · · · · · · · · · · · · · · · · · · · package file+ ├ ─ ─ style - loader. Js · · · · · · · · · · · · · · · · · · · · · style loader└ ─ ─ webpack. Config. Js · · · · · · · · · · · · · · · · · · · webpack config fileCopy the code
/* index.css */
body {
  margin: 0 auto;
  padding: 0 20px;
  width: 1000px;
  background-color: #ccc;
}
Copy the code
// index.js
import "./index.css";
console.log("loader ok!");
Copy the code

Each Webpack Loader needs to export a function, which is the process of processing resources by our loader. Its input is the content of the loaded resource file, and its output is the result after processing. We receive input by the source parameter and output by the return value. Here we try to print the source and then return the string Hello Webpack csS-loader directly inside the function! , the specific code is as follows:

// css-loader.js
module.exports = (source) = > {
  console.log(source);
  return "hello webpack css-loader!";
};

Copy the code

Let’s go back to the webPack configuration file and adjust the loader rules to use the CSS -loader.js module we just wrote. The code is as follows:

// webpack.config.js
module.exports = {
  mode: "none".// Change the entry to index.js
  entry: "./src/index.js".output: {
    filename: "bundle.js",},module: {
    rules: [{test: /\.css$/.// Change here
        use: ["./css-loader"],},],},};Copy the code

Note: Use can use not only the module name but also the module file path, just like require in Node.

After the configuration is complete, we open the command line terminal again to run the packaging command, as shown in the figure below:

The loader parameter is the contents of the file.

Error message: You may need an additional loader to handle the result of these loaders.

Tip: The final result of webPack loading resource file must be a standard JS code string.

Normal process:

We should now be thinking of the csS-Loader problem.

4.2 CSS – loader

The CSS-Loader is used to integrate multiple CSS modules.

module.exports = (source) = > {
  // Match url(XXX) similar structure
  const reg = /url((.+?) )/g;
  // Position subscript
  let pos = 0;
  // The currently matched code snippet
  let current;
  const arr = ["let list = []"];
  while ((current = reg.exec(source))) {
    const [matchUrl, g] = current;
    const lastPos = reg.lastIndex - matchUrl.length;
    arr.push(`list.push(The ${JSON.stringify(source.slice(pos, lastPos))}) `);
    pos = reg.lastIndex;
    arr.push(`list.push('url(' + require('${g}` '+') '));
  }
  arr.push(`list.push(The ${JSON.stringify(source.slice(pos))}) `);
  arr.push(`module.exports = list.join('')`);
  // Add a carriage return between lines of code
  return arr.join("\n");
};
Copy the code

General idea:

  • The entire CSS snippet is divided into sections with a url(XXX) -like structure as a node
  • The path in the URL changed to require import
  • The CSS code is pieced together in the form of arrays to form a whole

Loader packing results are as follows:

This is a fragment of the output bundle.js, which concatenates the string we just returned directly into the module. This also explains the problem with the package syntax error (loader must return JS code after processing).

4.3 style – loader

The style-loader will mount the integrated CSS portion into the head tag.

The code is as follows:

module.exports = function (source) {
  return `
    const styleElement = document.createElement('style');
    styleElement.innerHTML = The ${JSON.stringify(source)}
    document.head.appendChild(styleElement);
  `;
};
Copy the code

4.4 Summary after Writing loader

Loader is a function that, once a module is imported or required, intercepts the source code of these modules, makes modifications to them, and then outputs them to another module. The loop repeats, and finally outputs them to the entry file to form the final code.

It is the Loader mechanism that allows us to load any resource we want through WebPack.

Five, thank you

  • If this article helped you, just give it a like! Thanks for reading.