字节面试题:webpack的loader和plugin有什么区别?

709 阅读7分钟

关于其他的字节面试文章已经更新得差不多了,希望能够帮助到各位

字节面试题:webpack的loader和plugin有什么区别? - 掘金 (juejin.cn)

字节面试题:为什么vite更快 - 掘金 (juejin.cn)

手撕深拷贝?这一篇就够了! - 掘金 (juejin.cn)

字节面试题:请你谈谈vue的响应式原理(一) - 掘金 (juejin.cn)

字节面试题:请你谈谈vue的响应式原理(二) - 掘金

字节面试题:没有koa的cors你怎么处理跨域? - 掘金

前言

Webpack 是一个非常强大的模块打包工具,它能够处理各种类型的资源文件,并将它们转换成浏览器可以理解的形式。Webpack 的核心功能之一是通过 loader 和 plugin 来扩展其功能。对于一个前端开发而言,熟练掌握二者必不可少,但熟练掌握的前提是得知道这是个啥,在字节的面试中也问到过loader和plugin有什么区别?在我之前的 ——文章 之中简单提到过如何去使用plugin和loader以及二者的区别,但只有官方文档上的简单一句话:

插件目的在于解决 loader 无法实现的其他事

从而得出“plugin比loader更强大”。但是通过本人的亲身经历可以很负责地告诉大家:这个答案不行。甚至面试官会反问一句“那这么说的话loader岂不是没有存在的意义了?”所以痛定思痛,决定把二者的区别详细给大家讲讲。

正文

在之前写css的文章的时候就给大家提到过,当遇到诸如“请你聊聊xxx”或是“请你说说xxx和xxxxx的区别”的问题的时候,就按照“xxx是什么”=>“xxx的特点”=>“xxx有什么用”=>“xxx的原理是什么”(大招慎用)=>“如果没有xxx该怎么实现相同功能”(必杀技慎用,一不留神杀敌一千自损八百)的步骤来,这里也是一样。在介绍二者的区别是什么之前你得先介绍这二者分别是个什么东西,总之别嫌自己说得多,就怕说的不够多,把面试官当成三岁小孩,尽可能生动形象且详细地把内容掰开揉碎了讲。不过考虑到loader和plugin的基本用法在之前的文章中已经聊到过,所以这里就不做赘述了。

Webpack中 Loader 和 Plugin 的概念

1. Webpack Loader

  Loader 是 Webpack 中的一种功能,允许你处理不同类型的文件,将它们转换成模块,使得它们能够在构建过程中被正确处理。Loader 是一个函数,它接受输入文件,并返回一个转换后的输出文件。你可以把 loader 想象成一种翻译官,它的任务就是把 Webpack 不认识的东西翻译成它能理解的语言。比如说,当你想要加载一张图片或者一段 CSS 代码时,Webpack 默认只会处理 JavaScript 文件,所以你需要一个 loader 来告诉 Webpack 如何处理这些非 JS 文件。

Loader 的特点:

链式调用:Loader 可以串联使用,形成一个处理管道。

异步处理:Loader 可以同步或异步执行。

动态加载:Webpack 可以在运行时动态地加载 loader。比如你在开发的时候不确定具体会处理什么类型的文件,担心自己引入的loader不够用,这个时候就需要动态加载

const context = require.context('./', false, /\.([^.]+)$/);
context.keys().forEach((key) => { 
    context(key); // 自动根据文件扩展名应用相应的 loader
    });

2. Webpack Plugin

plugin 更像是一个全能型选手,它可以做很多 loader 做不了的事情。Plugin 可以在整个构建过程中添加、修改或者删除任何东西。它们更像是 Webpack 构建过程中的插件,可以做很多高级的任务。

Plugin 的特点:

更广泛的钩子:Plugin 提供了一系列钩子,可以在构建过程的不同阶段执行。

异步处理:Plugin 可以异步执行。

独立于文件处理:Plugin 不仅可以处理文件,还可以处理其他方面的事情。

Loader 和 Plugin 的区别

作用范围:

Loader 主要用于文件的转换,将文件转换成模块,使得它们能够在构建过程中被正确处理。

Plugin 则可以执行更广泛的自定义行为,不仅限于文件处理,还可以在整个构建过程中插入自定义逻辑。

触发时机:

Loader 在解析文件时被触发,即当 Webpack 遇到一个文件时就会调用相应的 loader。

Plugin 可以在构建过程中的任意阶段被触发,通过 Webpack 提供的各种钩子。

执行顺序:

Loader 可以串联使用,形成一个处理链,前一个 loader 的输出作为后一个 loader 的输入。

Plugin 按照在配置文件中的定义顺序执行。  

不同适用场景

Loader

你可以把 loader 想象成一种翻译官,它的任务就是把 Webpack 不认识的东西翻译成它能理解的语言。比如说,当你想要加载一张图片或者一段 CSS 代码时,Webpack 默认只会处理 JavaScript 文件,所以你需要一个 loader 来告诉 Webpack 如何处理这些非 JS 文件。

适合使用 loader 的情景:

当你需要处理某种特定类型的文件,并且需要将其转换成 Webpack 可以理解的模块时。

比如说,你需要把 CSS 文件转换成可以被导入的模块,或者把图片文件转换成 URL 或者 base64 编码。

通常,loader 会在你引入文件时自动被调用,你不需要特别去手动触发它。

Plugin

而 plugin 更像是一个全能型选手,它可以做很多 loader 做不了的事情。Plugin 可以在整个构建过程中添加、修改或者删除任何东西。它们更像是 Webpack 构建过程中的插件,可以做很多高级的任务。

适合使用 plugin 的情景:

当你需要做一些更复杂的操作,比如压缩代码、清理输出目录、生成额外的文件(比如 HTML 文件)等。

Plugin 可以在构建过程的多个阶段被触发,这意味着你可以利用它来做一些在 loader 层面难以实现的事情。通常,你会在 Webpack 的配置文件中明确地添加 plugin,并指定它应该在哪个阶段执行。

归纳一下

Loader 适合用于文件级别的转换,比如把 CSS 文件转换成模块,或者把图片文件处理成数据 URL。

Plugin 适合用于更复杂的构建任务,比如生成额外的文件、优化资源、清理文件夹等。

简单来说,如果你只是想处理文件,让 Webpack 能够识别它们,那么用 loader;如果你想要做更复杂的构建相关的任务,那就用 plugin。

Loader是否没有存在的意义?

讲了这么多,我们再次回到开头提到的面试官的问题——“loader岂不是没有存在的意义了?”,一般这么问的话答案都很明显,但这不是高考选择题,而是解答题,单纯回答“不是”肯定不行。尽管 Plugin 更加强大,但 Loader 在 Webpack 中仍然非常重要。

文件转换:

Loader 是处理文件的核心工具,没有它,Webpack 就无法处理非 JavaScript 文件。而有了loader,无论是css,照片,字体类型或者是其他例如JSON,xml以及markdown之类的文件,都可以被转换为js模块(注意不是纯js代码)

链式调用:

Loader 的链式调用特性使得处理流程非常灵活,可以很容易地组合不同的处理步骤。

易于使用:

Loader 的配置相对简单,易于理解和使用。

总结

Loader 和 Plugin 在 Webpack 中各有专长,它们共同协作以完成复杂的构建任务。Loader 专注于文件的转换,而 Plugin 则负责更广泛的构建任务。两者缺一不可,它们一起构成了 Webpack 强大的构建能力。除了上面提到的“翻译官”的例子,你也可以把loader和plugin看做是菜刀和锅,只有菜刀把菜切碎了,锅才能把菜炒熟。举了这么多例子,希望可以帮助各位更好地理解二者的区别和作用。最后,祝各位读者老爷0 waring(s),0 error(s)。