原稿:语雀 · Loader · 原目录:Webpack › 官方指南学习 › Loader

本篇的代码使用 webpack doc:管理资源提供的 demo

预处理器 Loader 是 Webpack 生态里一个重要的组成。Webpack 在进行打包的时候,对所有引入的资源文件都当作模块来处理。但 Webpack 自身只支持对 JS 文件处理(现在的版本也支持对 JSON 文件处理),如果引入 CSS文件或图片,那么 Webpack 在处理该模块的时候,会在控制台报错:Module parse failed … You may need an appropriate loader to handle this file type. 控制台告诉你模块解析失败,需要合适的 loader来处理该文件类型。当 Webpack 自身无法处理某种类型的文件的时候,可以通过配置特定的 loader,赋予Webpack 来处理该类型文件的能力

加载 CSS

首先安装 style-loader 和 css-loader:npm install –save-dev style-loader css-loader

并在配置文件中添加:

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
};
  • 模块 loader 会链式调用:每个 loader 都将对资源进行转换。链会逆序执行。第一个 loader 将其结果(被转换后的资源)传递给下一个 loader,依此类推。最后,webpack 期望链中的最后的 loader 返回 JavaScript
  • 应保证 style-loader 在前,css-loader 在后,css-loader 处理后的资源会再被 style-loader 处理
  • css-loader 是必需的,它的作用是解析 CSS 文件,包括解析 @import 等 CSS 语法。CSS 文件解析后会以字符串的形式打包到 JS 文件中。但此时样式并不会生效,因为我们需要把 CSS 插入到 html 里才会生效
  • style-loader 负责把JS里的样式代码插入到 html 文件里:通过 JS 动态生成 style 标签插入到文档的 head 标签里

创建 src/style.css

.hello {
  color: red;
}

在入口点通过 import “./style.css” 引入

import _ from "lodash";
+ import "./style.css";

function component() {
  const element = document.createElement("div");
  element.innerHTML = _.join(["Hello", "webpack"], " ");
+  element.classList.add('hello');

  return element;
}

document.body.appendChild(component());

运行 build 命令,打开 index.html,可以看到样式已经加载

image.png

加载图片

webpack5 内置的 Asset Modules 支持对图像的模块化处理,修改配置文件的 modules 规则,加入对于图片资源的匹配

rules: [
  {
    test: /\.css$/i,
    use: ["style-loader", "css-loader"],
  },
  {
    test: /\.(png|svg|jpg|jpeg|gif)$/i,
    type: "asset/resource",
  },
],
  • 在 import MyImage from './my-image.png' 时,图像将被处理并添加到 output 目录,并且 MyImage 变量将包含该图像在处理后的最终 url
  • 在使用 css-loader 时,会使用类似过程处理 CSS 中的 url('./my-image.png')。loader 会识别这是一个本地文件,并将 './my-image.png' 路径替换为 output 目录中图像的最终路径
  • html-loader 以相同的方式处理 <img src="./my-image.png" />

在 src/ 下放入图片,在 src/index.js 中 import

import _ from "lodash";
import "./style.css";
+ import svg from "./test.svg";

function component() {
  const element = document.createElement("div");
  element.innerHTML = _.join(["Hello", "webpack"], " ");
  element.classList.add("hello");

+  // 将图像添加到已经存在的 div 中。
+  const mySVG = new Image();
+  mySVG.src = svg;
+  element.appendChild(mySVG);

  return element;
}

document.body.appendChild(component());

同时为了测试,在 css 中引入同一张图片作为背景

 .hello {
   color: red;
+  background: url('./test.svg');
 }

执行 build,查看 index.html,此时图片能够正确显示,且在 \dist 目录下有一个新生成的 svg 文件

image.png

全局资源

通过上述方式加载资源,可以以更直观的方式将模块和资源组合在一起。无需依赖于含有全部资源的 /assets 目录,而是将资源与代码组合在一起使用。