Webpack面试考点之核心概念

1、webpack是什么?

webpack 是一种前端资源构建工具,一个静态模块打包器(module bundler)。 在 webpack 看来, 前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理。它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)。

webpack作用:

1)模块打包。可以将不同模块的文件打包整合在一起,并且保证它们之间的引用正确,执行有序。利用打包我们就可以在开发的时候根据我们自己的业务自由划分文件模块,保证项目结构的清晰和可读性。

2)编译兼容。在前端的“上古时期”,手写一堆浏览器兼容代码一直是令前端工程师头皮发麻的事情,而在今天这个问题被大大的弱化了,通过webpack的Loader机制,不仅仅可以帮助我们对代码做polyfill,还可以编译转换诸如.less, .vue, .jsx这类在浏览器无法识别的格式文件,让我们在开发的时候可以使用新特性和新语法做开发,提高开发效率。

3)能力扩展。通过webpack的Plugin机制,我们在实现模块化打包和编译兼容的基础上,可以进一步实现诸如按需加载,代码压缩等一系列功能,帮助我们进一步提高自动化程度,工程效率以及打包输出的质量。

2、webpack 五个核心概念

1)Entry

入口(Entry)指示 webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图。

2)Output

输出(Output)指示 webpack 打包后的资源bundles 输出到哪里去,以及如何命名。

3)Loader

Loader 让 webpack 能够去处理那些非JavaScript 文件 (webpack 自身只理解JavaScript)

4)Plugins

插件(Plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。

5)Mode

模式(Mode)指示 webpack 使用相应模式的配置。

3、loder是什么

webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。在打包过程中,会默认把所有遇到的文件都当作 JavaScript代码进行解析,因此当项目存在非JS类型文件时,我们需要先对其进行必要的转换,才能继续执行打包任务。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。loader 本质上是导出为函数的 JavaScript 模块。

1)loder的分类

loader 可以被分为四类,分别是:后置post,普通normal,行内inline,前置pre

对于post,normal,pre,主要取决于在配置里Rule.enforce的取值:pre || post,若无设置,则为normal。

2)loader的配置方式

关于配置loader的方式有三种:

配置方式(推荐):在 webpack.config.js文件中指定 loader。

内联方式:在每个 import 语句中显式指定 loader。

CLI 方式:在 shell 命令中指定它们。

3)loder的优先级

四种 loader 调用先后顺序为:pre > normal > inline > post 。在相同种类 loader 的情况下,调用的优先级为,自下而上,自右向左。

4)loder的调用链

每个 loader 都有自己的 normal 函数和 pitch 函数,而调用过程则是先根据从低到高的优先级顺序,调用 loader 各自的 pitch 函数,再由高到低调用各自的 normal 函数,其过程,更像是一个洋葱模型。

5)常见的loader

style-loader:创建 style 标签,将 js 中的样式资源插入进行,添加到 head 中生效。

css-loader:将css文件变成commonjs模块加载js中,里面内容是样式字符串。

less-loader:将 less 文件编译成 css 文件。

file-loader:把识别出的资源模块,移动到指定的输出目录,并且返回这个资源在输出目录的地址(字符串)。

url-loader:可以处理 file-loader 所有的事情,但是遇到图片格式的模块,可以选择性的把图片转成 base64 格式的字符串,并打包到 js 中,对小体积的图片比较合适,大图片不合适。

针对每个文件类型,loader是支持以数组的形式配置多个的,因此当Webpack在转换该文件类型的时候,会按顺序链式调用每一个loader,前一个loader返回的内容会作为下一个loader的入参。

编写loader:

4、Plugin是什么

如果说Loader负责文件转换,那么Plugin便是负责功能扩展。Loader和Plugin作为Webpack的两个重要组成部分,承担着两部分不同的职责。Plugin专注处理 webpack 在编译过程中的某个特定的任务的功能模块,可以称为插件。Plugin 是一个扩展器,它丰富了 webpack 本身,针对是 loader 结束后,webpack 打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听 webpack 打包过程中的某些节点,执行广泛的任务。

它们会运行在 webpack 的不同阶段(钩子 / 生命周期),贯穿了webpack整个编译周期。编译生命周期钩子,有如下:

entry-option:初始化 option。

run:开始编译。

compile:真正开始的编译,在创建 compilation 对象之前。

compilation:生成好了 compilation 对象。

make 从 entry 开始递归分析依赖,准备对每个模块进行 build。

after-compile:编译 build 过程结束。

emit:在将内存中 assets 内容写到磁盘文件夹之前。

after-emit:在将内存中 assets 内容写到磁盘文件夹之后。

done:完成所有的编译过程。

failed:编译失败的时候。

webpack基于发布订阅模式,在运行的生命周期中会广播出许多事件,插件通过监听这些事件,就可以在特定的阶段执行自己的插件任务,从而实现自己想要的功能。

Plugin 的特点:

a、是一个独立的模块;

b、模块对外暴露一个 js 函数;

c、函数的原型 (prototype) 上定义了一个注入 compiler 对象的 apply方法, apply 函数中需要有通过 compiler 对象挂载的 webpack 事件钩子,钩子的回调中能拿到当前编译的 compilation 对象,如果是异步编译插件的话可以拿到回调。

d、callback完成自定义子编译流程并处理 complition 对象的内部数据;

e、如果异步编译插件的话,数据处理完成后执行 callback 回调。

webpack编译会创建两个核心对象:

compiler:包含了 webpack 环境的所有的配置信息,包括 options,loader 和 plugin,和 webpack 整个生命周期相关的钩子

compilation:作为 plugin 内置事件回调函数的参数,包含了当前的模块资源、编译生成资源、变化的文件以及被跟踪依赖的状态信息。当检测到一个文件变化,一次新的 Compilation 将被创建。

如果要实现plugin,也需要遵循一定的规范:

插件必须是一个函数或者是一个包含 apply 方法的对象,这样才能访问compiler实例

传给每个插件的 compiler 和 compilation 对象都是同一个引用,因此不建议修改

异步的事件需要在插件处理完任务时调用回调函数通知 Webpack 进入下一个流程,不然会卡住。

常用的Plugin:

HotModuleReplacementPlugin:模块热更新插件。Hot-Module-Replacement 的热更新是依赖于 webpack-dev-server,后者是在打包文件改变时更新打包文件或者 reload 刷新整个页面,HRM 是只更新修改的部分。HotModuleReplacementPlugin是webpack模块自带的,所以引入webpack后,在plugins配置项中直接使用即可。

html-webpack-plugin:生成 html 文件。将 webpack 中entry配置的相关入口 chunk 和 extract-text-webpack-plugin抽取的 css 样式 插入到该插件提供的template或者templateContent配置项指定的内容基础上生成一个 html 文件,具体插入方式是将样式link插入到head元素中,script插入到head或者body中。

inject 有四个选项值

true:默认值,script标签位于html文件的body底部

body:script标签位于html文件的body底部(同 true)

head:script标签位于head标签内

false:不插入生成的 js 文件,只是单纯的生成一个html文件

clean-webpack-plugin:clean-webpack-plugin 用于在打包前清理上一次项目生成的 bundle 文件,它会根据output.path 自动清理文件夹;

extract-text-webpack-plugin:将 css 成生文件,而非内联 。该插件的主要是为了抽离 css 样式,防止将样式打包在 js 中引起页面样式加载错乱的现象;

mini-css-extract-plugin:提取 css 成单独文件,对每个包含 css 的 js 文件都会创建一个 CSS 文件,支持按需加载 css和 sourceMap。这个插件应该只用在生产环境配置。

postcss-loader/postcss-preset-env:css 兼容性处理。这里需要修改package.json, css兼容性处理:postcss --> postcss-loader postcss-preset-env 帮postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式。

"browserslist": {

// 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development

              "development": [

                "last 1 chrome version",

                "last 1 firefox version",

                "last 1 safari version"

              ],

              // 生产环境:默认是看生产环境

              "production": [

                ">0.2%",

                "not dead",

                "not op_mini all"

              ]

            }

5、Loader和Plugin的区别

loader 是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中。

plugin 赋予了 webpack 各种灵活的功能,例如打包优化、资源管理、环境变量注入等,目的是解决 loader 无法实现的其他事。

可以看到,两者在运行时机上的区别:loader 运行在打包文件之前;plugins 在整个编译周期都起作用。

在Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过Webpack提供的 API改变输出结果。

对于loader,实质是一个转换器,将A文件进行编译形成B文件,操作的是文件,比如将A.scss或A.less转变为B.css,单纯的文件转换过程

你可能感兴趣的:(Webpack面试考点之核心概念)