原文链接:https://survivejs.com/webpack...
翻译计划:https://segmentfault.com/a/11...附言:因为发现书中一些内容单独放出来会比较尴尬,所以会跳过部分章节,当然完整版会全部翻译,已经正在研究原版的网站搭建工程了
Webpack 提供了多种配置模块 loader 的方法。 Webpack 2 开始通过引入 use
字段,简化了 loader 使用。在这里使用绝对路径是一个好主意,因为它们允许你在不影响构建的情况下移动配置。
另一种方法是设置 context
字段,因为这会产生类似的效果并影响 entry 和 loader 的路径解析。但是它对输出没有影响,你仍然需要使用绝对路径或 /
。
即使你设置了 include
或 exclude
规则,从 node_modules 加载的包仍然可以正常工作,因为它们已经被编译为开箱即用的代码。如果它们没这么做,那么你必须应用 Consuming Packages 章节中涵盖的技术。
T> include
/exclude
在处理 node_modules 问题时非常方便,因为当你将 JavaScript 文件导入项目时,webpack 会默认处理并遍历已安装的包。为了让 webpack 不处理 node_modules,你需要使用 exclude
。其他文件类型不会遇到此问题。
剖析 Loader
Webpack 通过 loader 支持多种格式的文件。此外,它支持一些开箱即用的 JavaScript 模块规范。文件格式不同,但思路都是一致的,你必须设置一个或多个 loader,并将它们与你的目录结构连接起来。
{pagebreak}
下例中 webpack 通过 Babel 处理 JavaScript:
webpack.config.js
module.exports = { ... module: { rules: [ { // **Conditions** to match files using RegExp, function. test: /\.js$/, // **Restrictions** // Restrict matching to a directory. This // also accepts an array of paths or a function. // The same applies to `exclude`. include: path.join(__dirname, "app"), exclude(path) { // You can perform more complicated checks as well. return path.match(/node_modules/); }, // **Actions** to apply loaders to the matched files. use: "babel-loader", }, ], }, };
T> 如果你对 RegExp 的匹配不熟悉,可以使用在线工具,例如 regex101,RegExr 或 Regexper。
Loader 的运算顺序
一定要记住 loader 总是从右到左,从下到上(拆开写的时候)进行运算的。把它看成函数比较容易理解所谓“从右到左运行”。你可以把 use: ["style-loader", "css-loader"]
看作 style(css(input))
。
要查看规则,请看以下示例:
{ test: /\.css$/, use: ["style-loader", "css-loader"], },
根据从右到左的规则,可以等效拆分为:
{ test: /\.css$/, use: "style-loader", }, { test: /\.css$/, use: "css-loader", },
强制执行顺序
尽管可以使用上述规则配置,但是也可以强制在常规规则之前或之后应用特定规则。enforce
字段在这里可以派上用场。把他设置为 pre
or post
以在其他 loader 之前或之后进行处理。
Lint 是一个很好的例子,因为 Lint 必须先于任何其他行为。enforce: "post"
倒是很少用到,这多是你想对构建结果进行检查时使用的。
{pagebreak}
基本语法如下:
{ // Conditions test: /\.js$/, enforce: "pre", // "post" too // Actions use: "eslint-loader", },
如果你可以保证 test
中的 loader 顺序无误,那么可以不使用 enforce
。不过使用 enforce
方便你把不同步骤的 loader 分离开来,更容易组织。
Loader 的传参
可通过 query 把参数传到 loader:
{ // Conditions test: /\.js$/, include: PATHS.app, // Actions use: "babel-loader?presets[]=env", },
这种配置风格也适用于 entry 和 import,webpack 会处理他们。在某些个别情况下,这个写法能派上用场,但通常情况下最好使用以下更具可读性的方案。
{pagebreak}
传入对象到 use
:
{ // Conditions test: /\.js$/, include: PATHS.app, // Actions use: { loader: "babel-loader", options: { presets: ["env"], }, }, },
如果你想使用多个 loader,你可以将一个对象数组传递给 use
:
{ test: /\.js$/, include: PATHS.app, use: [ { loader: "babel-loader", options: { presets: ["env"], }, }, // Add more loaders here ], },
{pagebreak}
使用函数在 use 字段添加分支
本书中,你在更高级别上进行环境配置。实现类似结果的另一个选择是在 use
处使用分支,因为 webpack 的 loader 定义接受函数作为参数,你可以通过此函数区分环境:
{ test: /\.css$/, // `resource` refers to the resource path matched. // `resourceQuery` contains possible query passed to it // `issuer` tells about match context path use: ({ resource, resourceQuery, issuer }) => { // You have to return something falsy, object, or a // string (i.e., "style-loader") from here. // // Returning an array fails! Nest rules instead. if (env === "development") { return { use: { loader: "css-loader", // css-loader first rules: [ "style-loader", // style-loader after ], }, }; } }, },
用心感受,这是组合配置的另一种手段。
内联式定义
尽管配置级 loader 定义更可取,但可以内联编写 loader 定义:
// Process foo.png through url-loader and other // possible matches. import "url-loader!./foo.png"; // Override possible higher level match completely import "!!url-loader!./bar.png";
这种方法的问题在你的源代码会与 webpack 耦合。相同的机制还适用于 entry:
{ entry: { app: "babel-loader!./app", }, },
匹配文件的备选方法
test
结合 include
或 exclude
是匹配文件的最常用方法。这些字段接受以下数据类型:
test
——匹配 RegExp,字符串,函数,对象或数组。include
——同上。exclude
——同上,输出与include
相反。resource: /inline/
——匹配包含查询内容的资源路径。示例:/path/foo.inline.js
,/path/bar.png?inline
。issuer: /bar.js/
——匹配从某处请求的资源。示例:如果/path/foo.png
从/path/bar.js
请求,那么/path/foo.png
将匹配。resourcePath: /inline/
——匹配包含查询内容的资源路径(不包括 query)。示例:/path/foo.inline.png
。resourceQuery: /inline/
——匹配包含查询内容的 query(不包括 query)。示例:/path/foo.png?inline
。
基于布尔值的字段可用于进一步进行约束:
Boolean based fields can be used to constrain these matchers further:
not
——不匹配给定条件(参见test
表示接受的值)。and
——同时匹配一系列条件。or
——与数组中其中一个条件匹配。
基于 resourceQuery 加载
oneOf
字段可以根据资源相关匹配将 webpack 路由到特定的 loader:
{ test: /\.png$/, oneOf: [ { resourceQuery: /inline/, use: "url-loader", }, { resourceQuery: /external/, use: "file-loader", }, ], },
如果你需要在文件名中查询,应该使用 resourcePath
而不是 resourceQuery
。
{pagebreak}
基于 issuer 加载
issuer
基于资源的导入位置进行操作。以下示例改编自 css-loader issue 287,style-loader 将应用于 JavaScript 导入的 CSS 文件:
{ test: /\.css$/, rules: [ { issuer: /\.js$/, use: "style-loader", }, { use: "css-loader", }, ], },
另一种方法结合了 issuer
和 not
:
{ test: /\.css$/, rules: [ // CSS imported from other modules is added to the DOM { issuer: { not: /\.css$/ }, use: "style-loader", }, // Apply css-loader against CSS imports to return CSS { use: "css-loader", }, ], }
了解 loader 行为
通过观察 loader 行为可以更深入地理解它们。 loader-runner 允许你在没有 webpack 的情况下单独运行它们。Webpack 在底层也是使用此软件包,Extending with Loaders 章节将会详细介绍它。
inspect-loader 可以监视 loader 之间传递的内容。将此 loader 添加到你的配置即可检查其中的数据流,而不必在 node_modules 中插入 console.log
。
总结
Webpack 提供了多种设置 loader 的方法,但在 webpack 4 中用好 use
就足够了。注意 loader 的处理顺序,这是很多常见的问题来源。
回顾一下:
Loaders 决定了 webpack 的模块解析机制匹配到文件时应该作何处理。
loader 定义包括用于匹配的条件(conditions),以及匹配成功需要进行的动作(actions)。
Webpack 2 引入了
use
字段。它将以前的loader
和loaders
字段结合到了一起。Webpack 4 提供了多种匹配和改变 loader 行为的方法。例如,你可以在匹配 loader 后进行 resource query 匹配,指引 loader 进行特定操作。
在下一章中,你将学习使用 webpack 加载图片。
共同學習,寫下你的評論
評論加載中...
作者其他優質文章