Webpack高频面试题
1 谈谈你对webpack的看法
现在的前端网页功能丰富,特别是SPA(single page web application 单页应用)技术流行后,JavaScript的复杂度增加和需要一大堆依赖包,还需要解决Scss,Less......新增样式的扩展写法的编译工作。
webpack是一个模块打包工具,可以使用它管理项目中的模块依赖,并编译输出模块所需的静态文件。它可以很好地管理、打包开发中所用到的HTML,CSS,JavaScript和静态文件(图片,字体)等,让开发更高效。对于不同类型的依赖,webpack有对应的模块加载器,而且会分析模块间的依赖关系,最后合并生成优化的静态资源。
2 webpack的基本功能和工作原理?
- 代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等
- 文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等
- 代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载
- 模块合并:在采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件
- 自动刷新:监听本地源代码的变化,自动构建,刷新浏览器
- 代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过
- 自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。
前端为什么要进行打包和构建?
代码层面:
体积更小(Tree-shaking、压缩、合并),加载更快
编译高级语言和语法(TS、ES6、模块化、scss)
兼容性和错误检查(polyfill,postcss,eslint)
研发流程层面:
统一、高效的开发环境
统一的构建流程和产出标准
集成公司构建规范(提测、上线)
webpack的核心概念
Entry:入口,Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。告诉webpack要使用哪个模块作为构建项目的起点,默认为./src/index.js
output :出口,告诉webpack在哪里输出它打包好的代码以及如何命名,默认为./dist
Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
Loader:模块转换器,用于把模块原内容按照需求转换成新内容。
Plugin:扩展插件,在 Webpack 构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件的发生,在特定时机做对应的事情。
webpack构建过程
- 从entry里配置的module开始递归解析entry依赖的所有module
- 每找到一个module,就会根据配置的loader去找对应的转换规则
- 对module进行转换后,再解析出当前module依赖的module
- 这些模块会以entry为单位分组,一个entry和其所有依赖的module被分到一个组Chunk
- 最后webpack会把所有Chunk转换成文件输出
- 在整个流程中webpack会在恰当的时机执行plugin里定义的逻辑
webpack打包原理
将所有依赖打包成一个bundle.js,通过代码分割成单元片段按需加载
什么是webpack,与gulp,grunt有什么区别
- webpack是一个模块打包工具,可以递归地打包项目中的所有模块,最终生成几个打包后的文件。
- 区别:webpack支持代码分割,模块化(AMD,CommonJ,ES2015),全局分析
什么是entry,output?
- loader是用来告诉webpack如何转换某一类型的文件,并且引入到打包出的文件中。
- plugins(插件)作用更大,可以打包优化,资源管理和注入环境变量
什么是module,chunk,bundle?
bundle:是由webpack打包出来的文件
chunk:是指webpack在进行模块依赖分析的时候,代码分割出来的代码块
module:是开发中的单个模块
如何自动生成webpack配置?
可以用一些官方脚手架
- webpack-cli
- vue-cli
bash
// 首先安装
npm install -g @vue/cli
// 新建项目hello
vue create hello
- nuxt-cli
javascript
// 确保安装了npx,npx在npm5.2.0默认安装了
// 新建项目hello
npx create-nuxt-app hello
webpack如何配置单页面和多页面的应用程序?
- 单个页面
- module.exports = {
entry: './path/to/my/entry/file.js'
}
- 多页面应用程序
javascript
module.entrys = {
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js'
}
}
webpack-dev-server和http服务器如nginx有什么区别?
- webpack-dev-server使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,相比传统http服务器开发更加简单高效,
sourceMap
是一个映射关系,将打包后的文件隐射到源代码,用于定位报错位置
配置方式:
例如:devtool:'source-map'
加不同前缀意义:
inline:不生成映射关系文件,打包进main.js
cheap: 1.只精确到行,不精确到列,打包速度快 2.只管业务代码,不管第三方模块
module:不仅管业务代码,而且管第三方代码
eval:执行效率最快,性能最好
最佳实践:
开发环境:cheap-module-eval-source-map
线上环境:cheap-mudole-source-map
13、Loader机制的作用是什么?
webpack默认只能打包js文件,配置里的module.rules数组配置了一组规则,告诉 Webpack 在遇到哪些文件时使用哪些 Loader 去加载和转换打包成js。
注意:
use属性的值需要是一个由 Loader 名称组成的数组,Loader 的执行顺序是由后到前的;
每一个 Loader 都可以通过 URL querystring 的方式传入参数,例如css-loader?minimize中的minimize告诉css-loader要开启 CSS 压缩
ExtractTextPlugin插件的作用
ExtractTextPlugin插件的作用是提取出 JavaScript 代码里的 CSS 到一个单独的文件。
对此你可以通过插件的filename属性,告诉插件输出的 CSS 文件名称是通过[name]_[contenthash:8].css字符串模版生成的,里面的[name]代表文件名称,[contenthash:8]代表根据文件内容算出的8位 hash 值, 还有很多配置选项可以在ExtractTextPlugin的主页上查到。
15、Plugin(插件)的作用是什么?
Plugin 是用来扩展 Webpack 功能的,通过在构建流程里注入钩子实现,它给 Webpack 带来了很大的灵活性。
Webpack 是通过plugins属性来配置需要使用的插件列表的。plugins属性是一个数组,里面的每一项都是插件的一个实例,在实例化一个组件时可以通过构造函数传入这个组件支持的配置属性。
17、常见Plugins
HtmlWbpackPlugin自动在打包结束后生成html文件,并引入bundle.js
cleanwebPackPlugin打包自动删除上次打包文件
什么是模块热更新?
webpack的一个功能,可以使代码修改后不用刷新浏览器就自动更新,高级版的自动刷新浏览器
在应用过程中替换添加删出模块,无需重新加载整个页面,是高级版的自动刷新浏览器。
优点:只更新变更内容,以节省宝贵的开发时间。调整样式更加快速,几乎相当于在浏览器中更改样式
HMR热模块更新
借助webpack.HotModuleReplacementPlugin(),devServer开启hot
场景1:实现只刷新css,不影响js
场景2:js中实现热更新,只更新指定js模块
dev-server是怎么跑起来的
webpack-dev-server支持两种模式来自动刷新页面
- iframe模式(页面放在iframe中,当发送改变时重载)
无需额外配置,只要以这种格式url访问即可。http://localhost:8080/webpack-dev-server/index.html
- inline模式(将webpack-dev-server的客户端入口添加到bundle中)
inline模式下url不用发生变化,但启动inline模式分两种情况
javascript
// 以命令行启动webpack-dev-server有两种方式
// 方式1 在命令行中添加--inline命令
// 方式2 在webpack-config.js添加devServer:{inline: true}// 以node.js API启动有两种方式
// 方式1 添加webpack-dev-server/client?http://localhost:8080/到webpack配置的entry入口点
config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/");
// 将<script src="http://localhost:8080/webpack-dev-server.js"></script>添加到html文件中
使用过webpack里面哪些plugin和loader
loader
babel-loader: 将ES6+转移成ES5-
css-loader,style-loader:解析css文件,能够解释@import url()等
file-loader:直接输出文件,把构建后的文件路径返回,可以处理很多类型的文件
url-loader:打包图片
plugins:
- html-webpack-plugin: 压缩html
- clean-webpack-plugin: 打包器清理源目录文件,在webpack打包器清理dist目录
webpack中babel的实现
安装 npm i -D @babel-preset-env @babel-core babel-loader
- @babel-preset-env:可以让我们灵活设置代码目标执行环境
- @babel-core: babel核心库
- babel-loader: webpack的babel插件,让我们可以在webpack中运行babel
配置.babelrc
javascript
{
"presets": ['@babel/preset-env']
}
配置webpack.config.js
javascript
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {loader: 'babel-loader'}
}]
}
}
提取公用代码
javascript
module.exports = {
optimization: {
splitChunks: {
common: {
// 抽离公共代码
chunks: 'initial',
name: 'common', // 打包后的文件名
minChunks: 2, // 最小引用2次
minSize: 0 // 超出0字节就生成一个新包
},
styles: {
// 抽离公用代码
name: 'styles',
test: /\.css$/,
chunks: 'all',
minChunks: 2,
enforce: true
},
vender: {
// 抽离第三方插件
test: /node_modules/,
chunks: 'initial',
name: 'vendor', // 打包后的文件名
priority: 10 // 设置优先级,防止与自定义公共代码提取时被覆盖,不进行打包
}
}
}
}
什么是长缓存?在webpack中如何做到长缓存优化?
- 浏览器在用户访问页面的时候,为了加快加载速度会对用户访问的静态资源进行存储,但是每一次代码升级或更新都需要浏览器下载新的代码,最简单方便的方式就是引入新的文件名称。
- webpack中可以在output中指定chunkhash,并且分离经常更新的代码和框架代码。通过NameModulesPlugin或HashedModuleIdsPlugin使再次打包文件名不变。
什么是Tree-shaking?CSS可以Tree-shaking?
Tree-shaking是指在打包中取出那些引入了但在代码中没有被用到的死代码。webpack中通过uglifysPlugin来Tree-shaking JS。CSS需要使用purify-CSS
webpack-dev-server 和 http服务器的区别
webpack-dev-server使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,比传统的http服务对开发更加有效。
lazy loading(模块懒加载)
借助import()语法异步引入组件,实现文件懒加载:prefetch,preloading
webpack提倡多写异步代码,提升代码利用率,从而提升页面性能
先加载主业务文件,prefetch利用网络空闲时间,异步加载组件
ES stage 含义
stage-x:指处于某一阶段的js语言提案
Stage 0 - 设想(Strawman):只是一个想法,可能有 Babel插件。
Stage 1 - 建议(Proposal):这是值得跟进的。
Stage 2 - 草案(Draft):初始规范。
Stage 3 - 候选(Candidate):完成规范并在浏览器上初步实现。
Stage 4 - 完成(Finished):将添加到下一个年度版本发布中。
6、gulp/grunt 与 webpack的区别是什么?
三者都是前端构建工具,grunt和gulp在早期比较流行,现在webpack相对来说比较主流,不过一些轻量化的任务还是会用gulp来处理,比如单独打包CSS文件等。
grunt和gulp是基于任务和流(Task、Stream)的。
类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程。
webpack是基于入口的。
webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。
28道Webpack面试题及答案_油墨香^_^的博客-CSDN博客