Webpack | 青训营笔记

85 阅读4分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 7 天

使用Webpack

image.png

  1. 问题一:

(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 样式挂载到页面当中。

  1. 问题二:

(2)接入scss:

  1. SCSS 源代码会先交给 sass-loader 把 SCSS 转换成 CSS;
  2. 把 sass-loader 输出的 CSS 交给 css-loader 处理,找出 CSS 中依赖的资源、压缩 CSS 等;
  3. 把 css-loader 输出的 CSS 交给 style-loader 处理,转换成通过脚本加载的 JavaScript 代码;

参考:(3-4 使用 SCSS · 深入浅出 Webpack (wuhaolin.cn))

理解插件

image.png

参考:(Webpack 原理系列七:如何编写loader (qq.com))

  1. 问题一:

代码层面上的 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 值即可  
    errError | null,  
    // 转译结果  
    contentstring | Buffer,  
    // 源码的 sourcemap 信息  
    sourceMap?: SourceMap,  
    // 任意需要在 Loader 间传递的值  
    // 经常用来传递 ast 对象,避免重复解析  
    data?: any  
);
  1. 问题二:

可以为某种资源文件配置多个 Loader,Loader 之间按照配置的顺序从前到后(pitch),再从后到前依次执行,从而形成一套内容转译工作流。

例如上面提到的scss的处理:

  1. SCSS 源代码会先交给 sass-loader 把 SCSS 转换成 CSS;
  2. 把 sass-loader 输出的 CSS 交给 css-loader 处理,找出 CSS 中依赖的资源、压缩 CSS 等;
  3. 把 css-loader 输出的 CSS 交给 style-loader 处理,转换成通过脚本加载的 JavaScript 代码;

对于less的处理:

  1. less-loader:实现 less => css 的转换,输出 css 内容,无法被直接应用在 Webpack 体系下;
  2. css-loader:将 css 内容包装成类似 module.exports = "${css}" 的内容,包装后的内容符合 JavaScript 语法;
  3. style-loader:做的事情非常简单,就是将 css 模块包进 require 语句,并在运行时调用 injectStyle 等函数将内容注入到页面的 style 标签。

链式调用的好处:

  1. 保持单个 Loader 的单一职责,一定程度上降低代码的复杂度;

  2. 细粒度的功能能够被组装成复杂而灵活的处理链条,提升单个 Loader 的可复用性。

  3. 问题三:

Loader 可以以异步形式返回处理结果。 例如在 less-loader 中,逻辑分为三步:

  1. 调用 this.async 获取异步回调函数,此时 Webpack 会将该 Loader 标记为异步加载器,会挂起当前执行队列直到 callback 被触发;
  2. 调用 less 库将 less 资源转译为标准 css;
  3. 调用异步回调 callback 返回处理结果。

image.png

  1. 问题一:

Loader 和 Plugin 的不同:

参考:前端面试题之前端工程化篇 (yuque.com)

作用不同:

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 的实例,参数都通过构造函数传入。