这是我参与「第五届青训营」伴学笔记创作活动的第 7 天
使用Webpack
- 问题一:
(1)webpack 是用JS写的,运行在 node 环境,所以默认 webpack 打包的时候只会处理JS之间的依赖关系。像 .css 这样的文件不是一个 JavaScript 模块,需要像 loader 这样的翻译官来识别这个模块,通过特定的语法规则进行转换内容最后导出。
loader 的执行是有顺序的,支持链式的调用。loader 的执行顺序是从下到上,从右到左。比如处理样式类的文件,use:['style-loader', 'css-loader']。css-loader 处理后的文件返回给 style-loader。
一个 Loader 的职责是单一的,只需要完成一种转换。
(2)css-loader 帮助我们解析css成为js对象,sytle-loader 可以从 css-loader 解析的对象中提取 css 样式挂载到页面当中。
- 问题二:
(2)接入scss:
- SCSS 源代码会先交给 sass-loader 把 SCSS 转换成 CSS;
- 把 sass-loader 输出的 CSS 交给 css-loader 处理,找出 CSS 中依赖的资源、压缩 CSS 等;
- 把 css-loader 输出的 CSS 交给 style-loader 处理,转换成通过脚本加载的 JavaScript 代码;
参考:(3-4 使用 SCSS · 深入浅出 Webpack (wuhaolin.cn))
理解插件
参考:(Webpack 原理系列七:如何编写loader (qq.com))
- 问题一:
代码层面上的 Loader 通常是一个函数:
module.exports = function(source, sourceMap?, data?) {
// source 为 loader 的输入,可能是文件内容,也可能是上一个 loader 处理结果
return source;
};
Loader 函数接收三个参数,分别为:
source:资源输入,对于第一个执行的 loader 为资源文件的内容;后续执行的 loader 则为前一个 loader 的执行结果。sourceMap: 可选参数,代码的 sourcemap 结构。data: 可选参数,其它需要在 Loader 链中传递的信息,比如 posthtml/posthtml-loader 就会通过这个参数传递参数的 AST 对象。
loader可以通过 return 语句返回处理结果,还可以以 callback 方式返回更多信息,供下游 Loader 或者 Webpack 本身使用。
通过 this.callback(null, content, map) 语句同时返回转译后的内容与 sourcemap 内容。callback 的完整签名如下:
this.callback(
// 异常信息,Loader 正常运行时传递 null 值即可
err: Error | null,
// 转译结果
content: string | Buffer,
// 源码的 sourcemap 信息
sourceMap?: SourceMap,
// 任意需要在 Loader 间传递的值
// 经常用来传递 ast 对象,避免重复解析
data?: any
);
- 问题二:
可以为某种资源文件配置多个 Loader,Loader 之间按照配置的顺序从前到后(pitch),再从后到前依次执行,从而形成一套内容转译工作流。
例如上面提到的scss的处理:
- SCSS 源代码会先交给 sass-loader 把 SCSS 转换成 CSS;
- 把 sass-loader 输出的 CSS 交给 css-loader 处理,找出 CSS 中依赖的资源、压缩 CSS 等;
- 把 css-loader 输出的 CSS 交给 style-loader 处理,转换成通过脚本加载的 JavaScript 代码;
对于less的处理:
- less-loader:实现 less => css 的转换,输出 css 内容,无法被直接应用在 Webpack 体系下;
- css-loader:将 css 内容包装成类似
module.exports = "${css}"的内容,包装后的内容符合 JavaScript 语法; - style-loader:做的事情非常简单,就是将 css 模块包进 require 语句,并在运行时调用 injectStyle 等函数将内容注入到页面的 style 标签。
链式调用的好处:
-
保持单个 Loader 的单一职责,一定程度上降低代码的复杂度;
-
细粒度的功能能够被组装成复杂而灵活的处理链条,提升单个 Loader 的可复用性。
-
问题三:
Loader 可以以异步形式返回处理结果。 例如在 less-loader 中,逻辑分为三步:
- 调用
this.async获取异步回调函数,此时 Webpack 会将该 Loader 标记为异步加载器,会挂起当前执行队列直到callback被触发; - 调用 less 库将 less 资源转译为标准 css;
- 调用异步回调
callback返回处理结果。
- 问题一:
Loader 和 Plugin 的不同:
作用不同:
Loader 直译为"加载器"。Webpack 将⼀切⽂件视为模块,但是 webpack 原⽣是只能解析js⽂件,如果想将其他⽂件也打包的话,就会⽤到 loader 。 所以 Loader 的作⽤是让webpack拥有了加载和解析⾮js文件的能力。
Plugin 直译为"插件"。Plugin 可以扩展webpack的功能,让 webpack 具有更多的灵活性。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
不同用法:
Loader 在 module.rules 中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个 Object ,里面描述了对于什么类型的文件(test),使用什么加载(loader)和使用的参数(options)。
Plugin 在 plugins 中单独配置。 类型为数组,每一项是一个 plugin 的实例,参数都通过构造函数传入。