众所周知,原生的 webpack 仅支持 JS 和 JSON 两种文件类型(这是 webpack 开箱可用的自带能力),想要使用其他类型的资源就要借助各种 Loader 或资源模块(asset module),下面就是介绍 webpack 对几种常见资源的解析方式。
babel-loader
webpack 只支持 JavaScript
文件,如果想要用 ES6/ES7
、 React JSX
或者 vue
该怎么办?babel-loader
就是为此而生。 babel-loader
允许我们使用 Babel
和 webpack
转译 JavaScript
文件。
我们以 ES6
和 React 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-loader
和 style-loader
。
css-loader
用于加载.css
文件,并且转换成 commomjs 对象插入到 js 代码中去。style-loader
负责将样式通过<style>
标签插入到head
中。
首先,还是安装 css-loader
和 style-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
,所以需要先安装 less
和 less-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
打包后的效果,没毛病:
解析资源文件(图片、字体等)
在 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:
使用资源模块解析字体
使用资源模块的话,我们的配置项的变化在于,将 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
目录下就会生成解析后的字体:
看一下实际的页面效果,字体显示正常: