介绍目前常见前端面试题,Webpack 基础原理题
参考慕课网实战课 前端框架及项目面试-聚焦 Vue3 React Webpack 总结的知识点
webpack
- webpack 已是前端打包构建的不二选择
- 每日必用,面试必考
- 成熟的工具,重点在于配置和使用,原理并不高优
讲解范围
- 基本配置
- 高级配置
- 优化打包效率
- 优化产出代码
- 构建流程概述
- babel
关于webpack 5
- webpack5 主要是内部效率的优化
- 对比 webpack4,没有太多使用上的改动
- 你可以直接使用 webpack5 来学习课程
回顾之前的 webpack 面试题
- 前端代码为何要进行构建和打包?
- module chunk bundle 分别什么意思,有何区别?
- loader 和 plugin 的区别?
- webpack 如何实现懒加载?
- webpack 常见性能优化
- babel-runtime 和 babel-polyfill 的区别
webpack 基本配置
- vue-cli create-react-app
- 常用上述脚手架,而不会自己配置 webpack?
- 则面试不会通过
- 拆分配置和merge
- 启用本地服务
- 处理 ES6
- 处理样式
- 处理图片
- (模块化)
代码示例用到 webpack-demo 项目的 build-base-conf
webpack 高级配置
- 基本配置只能做demo,不能做线上项目
- 面试考察基本配置,只是为了快速判断你是否用过 webpack
- 以下高级配置,也是通过面试的必要条件
- 多入口
- 抽离 CSS 文件
- 抽离公共代码
- 多入口
代码示例用到 webpack-demo 项目的 build-multi-entry
- 抽离 CSS 文件
代码示例用到 webpack-demo 项目的 build-min-extract-css
- 抽离公共代码
代码示例用到 webpack-demo 项目的 build-splitChunks
- 懒加载

- 处理 JSX
- 处理 Vue
module chunk bundle 的区别
- module - 各个源码文件,webpack 中一切皆模块
- chunk - 多模块合并成的,如
entry
import()
splitChunk
- bundle - 最终的输出文件
webpack 性能优化
- 大厂必考 & 社区热议话题
- 优化打包构建速度 - 开发体验和效率
- 优化产出代码 - 产品性能
webpack 性能优化 - 构建速度
- 优化 babel-loader
- IgnorePlugin
- noParse
- happyPack
- ParallelUglifyPlugin
- 自动刷新
- 热更新
- DllPlugin
代码演示:
- 优化
babel-loader
代码示例用到 webpack-demo 项目的 build-optimization
IgnorePlugin
避免引入无用模块import moment from ‘moment'
- 默认会引入所有语言 JS 代码,代码过大
- 如何只引入中文?
noParse
避免重复打包

IgnorePlugin
vsnoParse
IgnorePlugin
直接不引入,代码中没有noParse
引入,但不打包
happyPack
多进程打包- JS 单线程,开启多进程打包
- 提高构建速度(特别是多核CPU)
ParallelUglifyPlugin
多进程压缩 JS- webpack 内置 Uglify 工具压缩 JS
- JS单线程,开启多进程压缩更快
- 和 happyPack 同理
关于开启多进程
- 项目较大,打包较慢,开启多进程能提高速度
- 项目较小,打包很快,开启多进程会降低速度(进程开销)
- 按需使用
自动刷新

- 热更新
- 自动刷新:整个网页全部刷新,速度较慢
- 自动刷新:整个网页全部刷新,状态会丢失
- 热更新:新代码生效,网页不刷新,状态不丢失
- DlIPlugin 动态链接库插件
- 前端框架如 vue React,体积大,构建慢
- 较稳定,不常升级版本
- 同一个版本只构建一次即可,不用每次都重新构建
- webpack已内置DlIlPlugin支持
- DlIPlugin-打包出dll文件
- DlIReferencePlugin-使用dll文件
代码示例用到 webpack-dll-demo 项目
Webpack 面试题
webpack 性能优化
优化前的准备工作
- 准备基于时间的分析工具:我们需要一类插件,来帮助我们统计项目构建过程中在编译阶段的耗时情况。
speed-measure-webpack-plugin
分析插件加载的时间 - 使用
webpack-bundle-analyzer
分析产物内容
代码优化:
无用代码消除,是许多编程语言都具有的优化手段,这个过程称为 DCE (dead code elimination),即 删除不可能执行的代码;
例如我们的 UglifyJs
,它就会帮我们在生产环境中删除不可能被执行的代码,例如:
1 | var fn = function() { |
摇树优化 (Tree-shaking),这是一种形象比喻。我们把打包后的代码比喻成一棵树,这里其实表示的就是,通过工具 “摇” 我们打包后的 js 代码,将没有使用到的无用代码 “摇” 下来 (删除)。即 消除那些被 引用了但未被使用 的模块代码。
- 原理: 由于是在编译时优化,因此最基本的前提就是语法的静态分析,ES6的模块机制 提供了这种可能性。不需要运行时,便可进行代码字面上的静态分析,确定相应的依赖关系。
- 问题: 具有 副作用 的函数无法被
tree-shaking
- 在引用一些第三方库,需要去观察其引入的代码量是不是符合预期;
- 尽量写纯函数,减少函数的副作用;
- 可使用
webpack-deep-scope-plugin
,可以进行作用域分析,减少此类情况的发生,但仍需要注意;
code-spliting: 代码分割技术,将代码分割成多份进行 懒加载 或 异步加载,避免打包成一份后导致体积过大,影响页面的首屏加载;
Webpack
中使用SplitChunksPlugin
进行拆分;- 按 页面 拆分: 不同页面打包成不同的文件;
- 按 功能 拆分:
- 将类似于播放器,计算库等大模块进行拆分后再懒加载引入;
- 提取复用的业务代码,减少冗余代码;
- 按 文件修改频率 拆分: 将第三方库等不常修改的代码单独打包,而且不改变其文件 hash 值,能最大化运用浏览器的缓存;
scope hoisting: 作用域提升,将分散的模块划分到同一个作用域中,避免了代码的重复引入,有效减少打包后的代码体积和运行时的内存损耗;
编译性能优化:
- 升级至 最新 版本的
webpack
,能有效提升编译性能; - 使用
dev-server
/ 模块热替换 (HMR
) 提升开发体验;- 监听文件变动 忽略 node_modules 目录能有效提高监听时的编译效率;
- 缩小编译范围
modules
: 指定模块路径,减少递归搜索;mainFields
: 指定入口文件描述字段,减少搜索;noParse
: 避免对非模块化文件的加载;includes/exclude
: 指定搜索范围/排除不必要的搜索范围;alias
: 缓存目录,避免重复寻址;
babel-loader
- 忽略
node_moudles
,避免编译第三方库中已经被编译过的代码 - 使用
cacheDirectory
,可以缓存编译结果,避免多次重复编译
- 忽略
- 多进程并发
webpack-parallel-uglify-plugin
: 可多进程并发压缩 js 文件,提高压缩速度;HappyPack
: 多进程并发文件的Loader
解析;
- 第三方库模块缓存:
DLLPlugin
和DLLReferencePlugin
可以提前进行打包并缓存,避免每次都重新编译;
- 使用分析
Webpack Analyse / webpack-bundle-analyzer
对打包后的文件进行分析,寻找可优化的地方- 配置profile:true,对各个编译阶段耗时进行监控,寻找耗时最多的地方
source-map
:- 开发:
cheap-module-eval-source-map
- 生产:
hidden-source-map
;
- 开发:
优化webpack打包速度
- 减少文件搜索范围
- 比如通过别名
loader
的test
,include & exclude
Webpack4
默认压缩并行Happypack
并发调用babel
也可以缓存编译Resolve
在构建时指定查找模块文件的规则- 使用
DllPlugin
,不用每次都重新构建 externals
和DllPlugin
解决的是同一类问题:将依赖的框架等模块从构建过程中移除。它们的区别在于- 在 Webpack 的配置方面,
externals
更简单,而DllPlugin
需要独立的配置文件。 DllPlugin
包含了依赖包的独立构建流程,而externals
配置中不包含依赖框架的生成方式,通常使用已传入 CDN 的依赖包externals
配置的依赖包需要单独指定依赖模块的加载方式:全局对象、CommonJS、AMD 等- 在引用依赖包的子模块时,
DllPlugin
无须更改,而externals
则会将子模块打入项目包中
- 在 Webpack 的配置方面,
优化打包体积
- 提取第三方库或通过引用外部文件的方式引入第三方库
- 代码压缩插件
UglifyJsPlugin
- 服务器启用
gzip
压缩 - 按需加载资源文件
require.ensure
- 优化
devtool
中的source-map
- 剥离
css
文件,单独打包 - 去除不必要插件,通常就是开发环境与生产环境用同一套配置文件导致
Tree Shaking
在构建打包过程中,移除那些引入但未被使用的无效代码- 开启
scope hosting
- 体积更小
- 创建函数作用域更小
- 代码可读性更好
打包体积 优化思路
- 提取第三方库或通过引用外部文件的方式引入第三方库
- 代码压缩插件
UglifyJsPlugin
- 服务器启用gzip压缩
- 按需加载资源文件
require.ensure
- 优化
devtool
中的source-map
- 剥离
css
文件,单独打包 - 去除不必要插件,通常就是开发环境与生产环境用同一套配置文件导致
打包效率
- 开发环境采用增量构建,启用热更新
- 开发环境不做无意义的工作如提取
css
计算文件hash等 - 配置
devtool
- 选择合适的
loader
- 个别
loader
开启cache
如babel-loader
- 第三方库采用引入方式
- 提取公共代码
- 优化构建时的搜索路径 指明需要构建目录及不需要构建目录
- 模块化引入需要的部分
Loader
编写一个loader
1 loader`就是一个`node`模块,它输出了一个函数。当某种资源需要用这个`loader`转换时,这个函数会被调用。并且,这个函数可以通过提供给它的`this`上下文访问`Loader API`。 `reverse-txt-loader
1 | // 定义 |
说一下 webpack 的一些 plugin,怎么使用 webpack 对项目进行优化
构建优化
- 减少编译体积
ContextReplacementPugin
、IgnorePlugin
、babel-plugin-import
、babel-plugin-transform-runtime
- 并行编译
happypack
、thread-loader
、uglifyjsWebpackPlugin
开启并行 - 缓存
cache-loader
、hard-source-webpack-plugin
、uglifyjsWebpackPlugin
开启缓存、babel-loader
开启缓存 - 预编译
dllWebpackPlugin && DllReferencePlugin
、auto-dll-webapck-plugin
性能优化
- 减少编译体积
Tree-shaking
、Scope Hositing
hash
缓存webpack-md5-plugin
- 拆包
splitChunksPlugin
、import()
、require.ensure
谈谈你对webpack的看法
WebPack
是一个模块打包工具,你可以使用WebPack
管理你的模块依赖,并编绎输出模块们所需的静态文件。它能够很好地管理、打包Web
开发中所用到的HTML
、Javascript
、CSS
以及各种静态文件(图片、字体等),让开发过程更加高效。对于不同类型的资源,webpack
有对应的模块加载器。webpack
模块打包器会分析模块间的依赖关系,最后 生成了优化且合并后的静态资源
gulp是什么
gulp
是前端开发过程中一种基于流的代码构建工具,是自动化项目的构建利器;它不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成- Gulp的核心概念:流
- 流,简单来说就是建立在面向对象基础上的一种抽象的处理数据的工具。在流中,定义了一些处理数据的基本操作,如读取数据,写入数据等,程序员是对流进行所有操作的,而不用关心流的另一头数据的真正流向
- gulp正是通过流和代码优于配置的策略来尽量简化任务编写的工作
- Gulp的特点:
- 易于使用:通过代码优于配置的策略,gulp 让简单的任务简单,复杂的任务可管理
- 构建快速 利用
Node.js
流的威力,你可以快速构建项目并减少频繁的IO
操作 - 易于学习 通过最少的
API
,掌握gulp
毫不费力,构建工作尽在掌握:如同一系列流管道