Preface: the author study webpack knowledge from the foundation to the principle to write a series, in order to review. Hope to help more friends who are learning Webpack.

Webpack series learning – First experience

Webpack series learning – Basic Usage one

Webpack series learning – various loaders to use

Webpack series learning – hot update and compression

Webpack series learning – Using ESLint and publishing NPM packages

Webpack series learning – Building webPack configurations

Webpack series learning – detailed implementation of easy Webpack

define

Loader is simply a JS module exported as a function

structure

The simplest loader code structure is:

module.exports = function(source){
  return source;
}
Copy the code

Execution sequence of multiple Loaders

The execution sequence is sequential, from right to left

An example is used to verify the loader execution order

  • 1. Configure a-loader and B-loader in webpack.config.js
// webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/index.js'.output: {
    path: path.join(__dirname, 'dist'),
    filename: 'main.js',},module: {
    rules: [{test: /\.js$/,
        use: [path.resolve('./loaders/a-loader.js'), path.resolve('./loaders/b-loader.js'],},],},};Copy the code
  • 2. Write a-loader.js and b-loader.js respectively

// a-loader.js
module.exports = function a(source) {
  console.log('loader a is used; ');
  return source;
};

// b-loader.js
module.exports = function b(source) {
  console.log('loader b is used; ');
  return source;
};
Copy the code
  • 3. Run web Pack, it can be seen that B was printed first, and then A

Loader debugger: loader-runner

Definition:

Loader-runner allows loaders to run without installing webpack

Function:

As a dependency of WebPack, it is used in Webpack to execute loader, develop and debug loader

The use of loader – runner

import { runLoaders } from "loader-runner";

runLoaders({
  resource: "/abs/path/to/file.txt? query".// String: The absolute path to the resource (you can add a query String)
  loaders: ["/abs/path/to/loader.js? query"].// String[]: absolute path of loader (can add query String)
  context: { minimize: true },
  // Additional Loader context in addition to the base context
  readResource: fs.readFile.bind(fs)
  // A function that reads resources
}, function(err, result) {
  // err: Error?
})
Copy the code

Use loader-runner to develop a raw-loader (convert the contents of a file to string)

1. Write raw-loader and test cases


// src/raw-loader.js
module.exports = function (source) {
  const json = JSON.stringify(source)
    .replace(/\u2028/g.'\\u2028')
    .replace(/\u2029/g.'\\u2029');

  return `export default ${json}`;
};

// src/demo.txt
aaa
Copy the code

2. Using the run – loader


// /run-loader.js
const { runLoaders } = require('loader-runner');
const fs = require('fs');
const path = require('path');

runLoaders(
  {
    resource: path.join(__dirname, './src/demo.txt'),
    loaders: [path.join(__dirname, './src/raw-loader.js')].context: {
      minimize: true,},readResource: fs.readFile.bind(fs),
  },
  (err, res) = > {
    err ? console.log(err) : console.log(res); });Copy the code

3. Run node run-loader.js to view the result

Obtaining Loader parameters

Use the loader-utils package. Let’s just install it.

npm i loader-utils -S
Copy the code

Add a parameter to run-loader.js as follows:


loaders: [
      {
        loader: path.join(__dirname, './src/raw-loader.js'),
        options: {
          name: 'test',
        },
      },
    ],
Copy the code

Then use loader-utils in raw-loader.js to get the parameters

const loaderUtils = require('loader-utils');
module.exports = function (source) {
  const { name } = loaderUtils.getOptions(this);
  console.log(name);
  const json = JSON.stringify(source)
    .replace(/\u2028/g.'\\u2028')
    .replace(/\u2029/g.'\\u2029');

  return `export default ${json}`;
};
Copy the code

Print name and view the result

Loader exception handling

1. Use the throw function in the loader

2. Pass an error through this.callback


this.callback(
  err: Error | null.content: string | Buffer, sourceMap? : SourceMap, meta? : any )Copy the code

How to develop an asynchronous loader

Return an asynchronous function via this.async. The first argument is Error, and the second argument is the result of the processing


const fs = require('fs');
const path = require('path');
module.exports = function (source) {
  const callback = this.async();

  fs.readFile(path.join(__dirname, './async.txt'), 'utf-8'.(err, data) = > {
    callback(null, data);
  });
};
Copy the code

Run the print, and you can see that the result is asynchronous

Using cache in loader:

1. Loader cache is enabled by default in webpack. You can use this.cacheable(false) to disable cache

2. Cache condition: The loader result has a certain output under the same input. A dependent loader cannot use the cache.