Webpack style of loader – loader

Webpack itself can only process JS files, and the files that JS files in our project will rely on also include HTML, CSS, JPG and other types. Since then, Loader is specially used to convert non-JS modules into JS modules. Also recommend its single responsibility (a loader is only responsible for one transformation)

loader

Official documentation – Loaders

Loader Basic Knowledge

Loader Interface

The above three documents have basically explained loader knowledge in a comprehensive way. The following lists some common knowledge points and personal understanding:

define

A loader is essentially a JavaScript module exported as a function. The Loader Runner calls this function and passes in the results or resource files generated by the previous loader.

/ * * * *@param {string|Buffer} Content Indicates the content of the source file *@param {object} (map) can be used by https://github.com/mozilla/source-map SourceMap data *@param {any} [meta] Meta data, can be any content */
module.exports = function (content, map, meta) {
  // Your WebPack Loader code
  // Here we just print a sentence and return the content (or custom content) to the next loader
  console.log("This is my first custom loader");
  return content;
};

/ * * *@remainingRequest Remaining requests: request string * for the loader following itself in the loader chain@precedingRequest The request string * of the loader that precedes it in the loader chain@data Data object */
module.exports.pitch = function (remainingRequest, precedingRequest, data) {
  // Your WebPack Loader code
  // This. Data can be updated in the normal method
  data.value = 66;
  // return something;
};
Copy the code

category

Rule.enforce

There are four types: pre, normal, inline, and post. The execution sequence is different

Inline is available through! To disable loader:

// Disable plain loaders
import { a } from ! "" ./file1.js";

// Disable preloading and plain loaders
import { b } from "-! ./file2.js";

Disable all laoders
import { c } from "!!!!! ./file3.js";
Copy the code

Inline loader and! Should not be used Prefix, because it’s non-standard. They may be used by loader-generated code

  • Pitching phase (left-to-right): Pitch method on the loader called in post-(post), inline (inline), normal (normal), pre (pre) order. For more detailed information, please see [Pitching Loader] (webpack.docschina.org/api/loaders…

    Use: In some cases, the loader only cares about the metadata following the request and ignores the results of the previous loader

  • Normal phase (from right to left): A Normal method on the Loader, called in the order pre, Normal, inline, and post. Conversion of module source code occurs in this phase.

For example:

module.exports = {
  / /...
  module: {
    rules: [{/ /...
        use: ["a-loader"."b-loader"."c-loader"],},],},};Copy the code

Its execution sequence is:

|- a-loader `pitch`
  |- b-loader `pitch`
    |- c-loader `pitch`
      |- requested module is picked up as a dependency
    |- c-loader normal execution
  |- b-loader normal execution
|- a-loader normal execution
Copy the code

If the pitch of the B-loader returns something in the above configuration, the order of execution will be:

|- a-loader `pitch`
  |- b-loader `pitch` returns something
|- a-loader normal execution
Copy the code

So when the Loader’s pitch method has a return value, it skips the rest of the Loader methods (even if they all have pitch methods), and then goes back to itself and ends

model

  • Synchronous:this.callback
  • Asynchronous:this.async
// callback
module.exports = function (content, map, meta) {
  const output = someSyncOperation(content);

  return output;
  // or
  this.callback(null, output, map, meta);
  return;
};

// async
module.exports = function (content, map, meta) {
  const callback = this.async();

  someAsyncOperation(content, function (err, result, sourceMaps, meta) {
    if (err) return callback(err);

    callback(null, result, sourceMaps, meta);
  });
};
Copy the code

Write your own loader

The official suggested that follows the principle: webpack.docschina.org/contribute/…

style-loader

Basic knowledge of

Webpack style – loader documentation

Inserting CSS into the DOM is typically used with csS-loader (which loads CSS files and parses imported CSS files, eventually returning CSS code)

use

example

npm init -y

yarn add webpack webpack-cli style-loader css-loader file-loader --save-dev
Copy the code

Create several CSS test files:

/* assets/a.css */
.a {
  font-size: 16px;
}
Copy the code
/* assets/b.css */
.b {
  font-size: 16px;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
Copy the code
/* assets/c.css */
@import url(./a.css);

.c {
  display: inline-block;
  font-weight: 600;
}
Copy the code

Entry file:

// src/index.js
export const add = (num1, num2) = > {
  return num1 + num2;
};

import ".. /assets/c.css";
import ".. /assets/b.css";

// import bCSS from '.. /assets/b.css';
// bCSS.use();
// bCSS.unuse();

console.log("this is index.js");
console.log(add(66.99));
Copy the code
<! -- dist/index.html -->
<! DOCTYPEhtml>
<html>
  <head>
    <meta charset="utf-8" />
    <title>start</title>
    <! -- <link rel="stylesheet" type="text/css" href="./assets/b.css" /> -->
  </head>
  <body>
    <div class="b">This is webpack loader example</div>
  </body>
  <script src="main.js"></script>
</html>
Copy the code

Webpack configuration file: webpack.config.js

const path = require("path");

module.exports = {
  mode: "development".entry: "./src/index.js".output: {
    filename: "main.js".path: path.resolve(__dirname, "dist"),},module: {
    rules: [{test: /\.css$/i,
        use: [
          // 'style-loader',
          {
            loader: "style-loader".options: {
              injectType: "styleTag"./ / the default value
              // injectType: "singletonStyleTag"
              // injectType: "lazyStyleTag"
              // injectType: "lazySingletonStyleTag"
              InjectType: "linkTag" injectType: "linkTag" injectType: "linkTag" injectType: "linkTag}},"css-loader".// 'file-loader'],},],},};Copy the code

Then run webpack (you can also configure a shortcut command XXX, yarn XXX in the scripts of package.json) to package, and open index.html in a browser to view the package result

injectType

Optional value: styleTag(default value), singletonStyleTag, autoStyleTag, lazyStyleTag, lazySingletonStyleTag, lazyAutoStyleTag, or linkTag

  • styleTag

    Styles are automatically inserted into the DOM by using multiple

    , that is, an import generates a style tag

<style>
  .a {
    font-size: 16px;
  }
</style>
<style>
  .c {
    display: inline-block;
    font-weight: 600;
  }
</style>
<style>
  .b {
    font-size: 16px;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
  }
</style>
Copy the code
  • singletonStyleTag

    Corresponds to styleTags, but it incorporates them into a style tag. Duplicate style names are not processed

<style>
  .a {
    font-size: 16px;
  }
  .c {
    display: inline-block;
    font-weight: 600;
  }

  .a {
    font-size: 16px;
  }
  .b {
    font-size: 16px;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
  }
</style>
Copy the code
  • linkTag

    Use multiple inserts of styles into the DOM

<link
  rel="stylesheet"
  href="file:///D:/testCodes/webpack-style-loder/dist/d06ed220ba698dc21e8270035e104dce.css"
/>
<link
  rel="stylesheet"
  href="file:///D:/testCodes/webpack-style-loder/dist/ada3b1108d67c1ded7467f095ae0a549.css"
/>
Copy the code

insert

Type: String|Function, Default: head

By default, style-loader adds/to the end of the page tag unless insert is specified.

This gives the STYle-loader created CSS a higher priority than the CSS that already exists within the tag. You can use other values when the default behavior doesn’t meet your needs, but we don’t recommend this.

In addition to injectType and insert parameters, there are attributes and esModule parameters, as described in the above official documentation

Thanks for the cover image: Po Go – Understand WebPack-Loader

Preview: style-loader source view loader principle