webpack loader

前言

webpack 有两种扩展方式。一种是 Loader 主要是负责将其他的资源形态转译成 webpack 可以处理的标准 JavaScript 代码;另一种是 Plugin 主要伴随着 webpack 整个生命周期,做一些重塑逻辑。

本文主要介绍第一种扩展方式 Loader。

Loader 是什么?

由于 webpack 只能处理标准的 JavaScript 代码,我们在使用 webpack 打包的过程中还需要处理图片/样式等等内容,那么这些内容都需要先转为 JS 代码才能够被 webpack 打包,因此需要 Loader 来帮我们实现。

Loader 的本质

Loader 的本质是导出函数的 JavaScript 模块,其导出的函数可以实现内容的转换,简单的 Loader 框架如下,接受源代码做一些计算返回修改之后的代码

module.exports = function (source, sourceMap?, data?) {
  // 执行计算
  return modifySource;
};

Loader 的分类

对于 Loader 来说,一共分为四种类型

  • pre: 前置 loader
  • normal: 普通 loader
  • inline: 行内 loader
  • post: 后置 loader

可以通过 webpack enforce 属性来做配置 pre/post,如果不配置默认则为普通 loader

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: 'css-loader',
        // enforce: 'pre' | 'post',
      },
    ],
  },
};

可以通过内联 import 语句添加前缀,可以覆盖配置中的所有 loader, preLoader 和 postLoader

  • 使用 ! 前缀,将禁用所有已配置的 normal loader(普通 loader)

    import Styles from '!style-loader!css-loader?modules!./styles.css';
  • 使用 !! 前缀,将禁用所有已配置的 loader(preLoader, loader, postLoader)

    import Styles from '!!style-loader!css-loader?modules!./styles.css';
  • 使用 ! 前缀,将禁用所有已配置的 preLoader 和 loader,但是不禁用 postLoaders

    import Styles from '-!style-loader!css-loader?modules!./styles.css';

Normal Loader

首先我们先分别定义三个简单的 Normal Loader

// ==== LoaderC ====
function LoaderC(source) {
  console.log('LoaderC run=====', source);
  return source + '~loaderC';
}
module.exports = LoaderC;

// ==== LoaderB ====
function LoaderB(source) {
  console.log('LoaderB run=====', source);
  return source + '~loaderB';
}
module.exports = LoaderB;

// ==== LoaderA ====
function LoaderA(source) {
  console.log('LoaderA run=====', source);
  return `module.exports = '${source}~loaderA'`;
}

module.exports = LoaderA;

在 webpack.config.js 中如下使用这些 loaders

const path = require('path');

module.exports = {
  entry: './src/index.js',
  context: path.resolve(__dirname, '.'),
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.js$/,
        use: ['babel-loader'],
      },
      {
        test: /\.txt$/,
        use: [
          path.resolve(__dirname, 'src/loaders/loaderA.js'),
          path.resolve(__dirname, 'src/loaders/loaderB.js'),
          path.resolve(__dirname, 'src/loaders/loaderC.js'),
        ],
      },
    ],
  },
};

入口文件 index.js 添加一个 txt 的依赖模块

import text from './name.txt';

console.log(text);

执行一次打包

Untitled

Untitled

能够发现 Normal Loader 是从 C⇒B⇒A 的执行顺序,也就是从下往上或者从右往左的顺序。并且上一个 loader 返回的结果作为下一个 loader 的 source

Untitled

Pitch Loader