webpack 完全指南:文件解析

2,053 阅读3分钟

众所周知,原生的 webpack 仅支持 JS 和 JSON 两种文件类型(这是 webpack 开箱可用的自带能力),想要使用其他类型的资源就要借助各种 Loader 或资源模块(asset module),下面就是介绍 webpack 对几种常见资源的解析方式。

babel-loader

webpack 只支持 JavaScript 文件,如果想要用 ES6/ES7React JSX 或者 vue 该怎么办?babel-loader 就是为此而生。 babel-loader 允许我们使用 Babelwebpack 转译 JavaScript 文件。

我们以 ES6React JSX 为例,介绍一下 babel-loader 的使用方式。

首先,安装一下 babel-loader

npm i babel-loader -D

然后,我们在 webpack 配置文件( webpack.config.js )中,添加 babel-loader 的使用规则:对匹配到的 js 文件使用 babel-loader 进行解析。

// webpack.config.js

module.exports = {
  // ...
  module: {
    rules: [{ test: /\.js$/, use: "babel-loader" }],
  },
};

babel-loader 是依赖于 babel 的,因此还需要对 babel 进行配置( .babelrc )。

解析 ES6

安装解析 ES6 的 preset:

npm i @babel/core @babel/preset-env -D

添加到 .babelrc 中:

{
  "presets": ["@babel/preset-env"]
}

可以添加一个包含 ES6 语法的文件,打包(npx webpack)看一下效果:

src/index.js:

const user = { name: "juejin" };
function hello({ name }) {
  document.write(`hello ${name}`);
}

hello(user);

解析后,dist/index.js:

document.write("hello ".concat("juejin"));

解析 React JSX

安装 react :

npm i react react-dom -S

安装解析 React JSX 的 preset:

npm i @babel/preset-react -D

添加到 .babelrc 中:

{
  "preset": [
    "@babel/preset-env",
  + "@babel/preset-react"
  ]
}

这样我们就可以来解析一个 JSX 语法的文件了:

src/search.js

import React from "react";
import ReactDOM from "react-dom";

ReactDOM.render(<h1>Hello, world!</h1>, document.getElementById("root"));

在打包生成的 dist 目录下添加 html 文件,挂在解析后的 JSX 文件:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="./search.js"></script>
  </body>
</html>

css-loader 和 style-loader

解析 CSS

在 webpack 中想解析 CSS 文件,就要使用 css-loaderstyle-loader

  • css-loader 用于加载 .css 文件,并且转换成 commomjs 对象插入到 js 代码中去。
  • style-loader 负责将样式通过 <style> 标签插入到 head 中。

首先,还是安装 css-loaderstyle-loader

npm i css-loader style-loader -D

然后在 webpack.config.js 中配置对 .css 文件的解析规则:

module.exports = {
  // ...
  module: {
    rules: [{ test: /\.css$/, use: ["style-loader", "css-loader"] }],
  },
};

这里需要注意: loader 是从右往左的链式调用,因为我们要先用 css-loader 解析 css,再通过 style-loader 插入样式,所以书写顺序是 ["style-loader", "css-loader"]

解析 Less / Sass

日常开发过程中,less/sass 功能更强更实用,webpack 对 less/sass 的解析也很简单,以 .less 文件为例,只需要增加一个 less-loader

  • less-loader,用于将 less 转换成 css

less-loader 依赖于 less ,所以需要先安装 lessless-loader

npm i less less-loader -D

然后,在 webpack.config.js 中的配置:

module.exports = {
  // ...
  module: {
    rules: [
      { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader"] },
    ],
  },
};

我们可以在之前的 search.js 中一个引入一个 less 文件,看看效果:

search.js

import React from "react";
import ReactDOM from "react-dom";
import "./search.less";

ReactDOM.render(
  <h1 className="search-text">
    Hello, <span>world!</span>
  </h1>,
  document.getElementById("root")
);

search.less

.search-text {
  color: red;
  span {
    color: green;
  }
}

npx webpack 打包后的效果,没毛病:

01.png

解析资源文件(图片、字体等)

在 webpack 5 之前,通常使用:

  • raw-loader 将文件导入为字符串
  • url-loader 将文件作为 data URI 内联到 bundle 中
  • file-loader 将文件发送到输出目录

在 webpack 5 中,通过添加 4 种新的模块类型,来替换所有这些 loader:

  • asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
  • asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
  • asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
  • asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。

我们通过解析图片和解析文字,分别介绍一下两种方式的用法

使用 file-loader 解析图片

安装 file-loader

npm i file-loader -D

webpack.config.js 中的配置:

module.exports = {
  //...
  module: {
    // ...
    rules: [{ test: /\.(png|svg|jpg|gif)$/, use: ["file-loader"] }],
  },
};

src/assets 目录下添加一张测试图片 logo.png,然后在 search.js 中引入并显示这张图片:

import React from "react";
import ReactDOM from "react-dom";
import "./search.less";
+ import logo from "./assets/logo.png";

ReactDOM.render(
  <h1 className="search-text">
    Hello, <span>world!</span>
+    <img src={logo} />
  </h1>,
  document.getElementById("root")
);

npx webpack 打包后,dist 目录下就会生成解析后的图片,文件名是图片的 Hash:

01.png

使用资源模块解析字体

使用资源模块的话,我们的配置项的变化在于,将 use: 'file-loader' 改成 type: 'asset/resource'

module.exports = {
  // ...
  module: {
    rules: [
      // ...
      { test: /\.(woff|woff2|eot|ttf|otf)$)/, type: "asset/resource" },
    ],
  },
};

src/assets 目录下添加一个测试字体,比如 TitanOne.ttf(随意找的一个免费英文字体),然后在 search.less 中引入:

@font-face {
  font-family: "TradeWinds";
  src: url("./assets/TradeWinds.ttf");
}

.search-text {
  color: red;
  font-family: "TradeWinds";
  span {
    color: green;
  }
}

npx webpack 打包后,dist 目录下就会生成解析后的字体:

01.png

看一下实际的页面效果,字体显示正常:

01.png

webpack 系列