目录
3、webpack 的构建流程是什么?从读取配置到输出文件这 个过程尽量说全(必会)
4、webpack 与 grunt、gulp 的不同?(必会)
5、有哪些常见的 Loader?他们是解决什么问题的?(必会)
9、是否写过 Loader 和 Plugin?描述一下编写 loader 或 plugin 的思路?(高薪常问)
11、source map 是什么?生产环境怎么用?(高薪常问)
12、请详细说明一下 Babel 编译的原理是什么?(高薪常问)
2、词法分析:将代码(字符串)分割为 token 流,即语法单元成的数组
13、在生产环境下如何提升 webpack 优化构建速度(高薪 常问)
14、什么是长缓存?在 webpack 中如何做到长缓存优化? (高薪常问)
16、怎么实现 webpack 的按需加载?什么是神奇注释?(高
webpack
1、什么是 webpack(必会)
1、基本定义
wbpack 是一个打包模块化 javascript 的工具,在 webpack 里一切文件皆模块,通过 loader 转换文件,通过 plugin 注入钩子,最后输出由多个模块组合成的文件,webpack 专注构建模块化项目,webpack 可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript 模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript 等),并将其打包为合适的格式以供浏览器使用
2、webpack 的优点是什么?(必会)
1、专注于处理模块化的项目,能做到开箱即用,一步到位
2、通过 plugin 扩展,完整好用又不失灵活
3、使用场景不局限于 web 开发
4、社区庞大活跃,经常引入紧跟时代发展的新特性,能为大多数场景找到已有的开源扩展
5、提供了更好的开发体验
3、webpack 的构建流程是什么?从读取配置到输出文件这 个过程尽量说全(必会)
webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:
1、初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数
2、开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译
3、确定入口:根据配置中的 entry 找出所有的入口文件
4、编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
5、完成模块编译:在经过第 4 步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系
6、输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk, 再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会
7、输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统,在以上过程中,webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 webpack 提供的 API 改变 webpack的运行结果
4、webpack 与 grunt、gulp 的不同?(必会)
1、三者之间的区别
三者都是前端构建工具,grunt 和 gulp 在早期比较流行,现在 webpack 相对来说比较主流,不过一些轻量化的任务还是会用 gulp 来处理,比如单独打包 CSS 文件等
1,1)grunt 和 gulp 是基于任务和流(Task、Stream)的。类似 jQuery,找到一个(或 一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个 web 的构建流程。
1,2)webpack 是基于入口的。webpack 会自动地递归解析入口所需要加载的所有资 源文件,然后用不同的 Loader 来处理不同的文件,用 Plugin 来扩展 webpack 功能。
2、构建思路的区别
2,1)gulp 和 grunt 需要开发者将整个前端构建过程拆分成多个`Task`,并合理控制所 有`Task`的调用关系
2,2)webpack 需要开发者找到入口,并需要清楚对于不同的资源应该使用什么Loader 做何种解析和加工
3、 从知识背景区别
3,1)gulp 更像后端开发者的思路,需要对于整个流程了如指掌
3,2)webpack 更倾向于前端开发者的思路
5、有哪些常见的 Loader?他们是解决什么问题的?(必会)
1、file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
2、url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去
3、source-map-loader:加载额外的 Source Map 文件,以方便断点调试
4、image-loader:加载并且压缩图片文件
5、babel-loader:把 ES6 转换成 ES5
6、css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
7、style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS
8、eslint-loader:通过 ESLint 检查 JavaScript 代码
6、Loader 和 Plugin 的不同?(必会)
1、不同的作用
1,1)Loader 直译为"加载器"。webpack 将一切文件视为模块,但是 webpack 原生是 只能解析 js 文件,如果想将其他文件也打包的话,就会用到 loader。 所以 Loader 的作用是让webpack 拥有了加载和解析非 JavaScript 文件的能力。
1,2)Plugin 直译为"插件",Plugin 可以扩展 webpack 的功能,让 webpack 具有更多的灵活性。 在 webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 webpack 提供的 API 改变输出结果
2、不同的用法
2,1)Loader 在 module.rules 中配置,也就是说他作为模块的解析规则而存在。 类型 为数组,每一项都是一个 Object,里面描述了对于什么类型的文件(test),使用什么加载 (loader)和使用的参数(options)
2,2)Plugin 在 plugins 中单独配置。 类型为数组,每一项是一个 plugin 的实例,参 数都通过构造函数传入
7、webpack3 和 webpack4 的区别(必会)
1、mode/–mode 参数,新增了 mode/--mode 参数来表示是开发还是生产
(development/production)
2、Production,侧重于打包后的文件大小,development 侧重于构建
3、移除 loaders,必须使用 rules(在 3 版本的时候 loaders 和 rules 是共存的但是到 4 的 时候只允许使用 rules
4、移除了 CommonsChunkPlugin (提取公共代码),用 optimization.splitChunks, optimization.runtimeChunk 来代替
5、支持 es6 的方式导入 JSON 文件,并且可以过滤无用的代码
let jsonData = require('./data.json')
import jsonData from './data.json'
import { first } from './data.json' // 打包时只会把 first 相关的打进去
6、升级 happypack 插件(happypack 可以进行多线程加速打包)ExtractTextwebpackPlugin 调整,建议选用新的 CSS 文件提取 kiii 插件 mini-css-extractplugin,production 模式,增加 minimizer
8、如何利用 webpack 来优化前端性能(高薪常问)
1、压缩代码。uglifyJsPlugin 压缩 js 代码, mini-css-extract-plugin 压缩 css 代码
2、利用 CDN 加速,将引用的静态资源修改为 CDN 上对应的路径,可以利用 webpack 对于 output 参数和 loader 的 publicpath 参数来修改资源路径
3、删除死代码(tree shaking),css 需要使用 Purify-CSS
4、提取公共代码。webpack4 移除了 CommonsChunkPlugin (提取公共代码),用optimization.splitChunks 和 optimization.runtimeChunk 来代替
9、是否写过 Loader 和 Plugin?描述一下编写 loader 或 plugin 的思路?(高薪常问)
1、基本定义
Loader 像一个"翻译官"把读到的源文件内容转义成新的文件内容,并且每个 Loader 通过链式操作,将源文件一步步翻译成想要的样子。
2、 编写思路
2.1)编写 Loader 时要遵循单一原则,每个 Loader 只做一种"转义"工作, 每个 Loader 的拿到的是源文件内容(source),可以通过返回值的方式将处理后的内容输出,也可以调用 this.callback()方法,将内容返回给 webpack,还可以通过 this.async()生成一个 callback函数,再用这个 callback 将处理后的内容输出出去,此外 webpack 还为开发者准备了开发loader 的工具函数集——loader-utils
2.2)相对于 Loader 而言,Plugin 的编写就灵活了许多, webpack 在运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 webpack 提供的 API 改变输出结果
3、 编写注意事项
3.1)Loader 支持链式调用,所以开发上需要严格遵循“单一职责”,每个 Loader只负责自己需要负责的事情
3.2)Loader 运行在 node.js 中,我们可以调用任意 node.js 自带的 API 或者安装第三方模块进行调用
3.3)webpack 传给 Loader 的原内容都是 UTF-8 格式编码的字符串,当某些场景下 Loader 处理二进制文件时,需要通过 exports.raw = true 告诉 webpack 该 Loader 是否需要二进制数据
3.4)尽可能的异步化 Loader,如果计算量很小,同步也可以
3.5)Loader 是无状态的,我们不应该在 Loader 中保留状态
3.6)使用 loader-utils 和 schema-utils 为我们提供的实用工具
3.7)加载本地 Loader 方法
10、使用 webpack 开发时,你用过哪些可以提高效率的插 件?(高薪常问)
1、webpack-dashboard:可以更友好的展示相关打包信息。
2、webpack-merge:提取公共配置,减少重复配置代码
3、speed-measure-webpack-plugin:简称 SMP,分析出 webpack 打包过程中 Loader和 Plugin 的耗时,有助于找到构建过程中的性能瓶颈
4、size-plugin:监控资源体积变化,尽早发现问题
5、HotModuleReplacementPlugin:模块热替换
11、source map 是什么?生产环境怎么用?(高薪常问)
1、基本定义
source map 是将编译、打包、压缩后的代码映射回源代码的过程。打包压缩后的代码 不具备良好的可读性,想要调试源码就需要 soucre map
2、具体使用
map 文件只要不打开开发者工具,浏览器是不会加载的,线上环境一般有三种处理方案
2.1)hidden-source-map:借助第三方错误监控平台 Sentry 使用
2.2)nosources-source-map:只会显示具体行数以及查看源代码的错误栈,安全性比 sourcemap 要高一些
2.3)sourcemap:通过 nginx 设置将 .map 文件只对白名单开放(公司内网)
注意:避免在生产中使用 inline- 和 eval-,因为它们会增加 bundle 体积大小,并降低整体性能
12、请详细说明一下 Babel 编译的原理是什么?(高薪常问)
大多数 JavaScript Parser 遵循 estree 规范,Babel 最初基于 acorn 项目(轻量级现代JavaScript 解析器) Babel 大概分为三大部分:
1、解析:将代码转换成 AST
2、词法分析:将代码(字符串)分割为 token 流,即语法单元成的数组
3、语法分析:分析 token 流(上面生成的数组)并生成 AST,转换:访问 AST 的节点进行变换操作生产新的 AST,taro 就是利用 babel 完成的小程序语法转换,生成:以新的 AST 为基
础生成代码
13、在生产环境下如何提升 webpack 优化构建速度(高薪 常问)
1、优化 babel-loader(加缓存,加 hash)
2、noParse(不去解析属性值代表的库的依赖)
3、IgnorePlugin(忽略本地化内容,如引入了一个插件,只用到了中文语言包,打包的时候把非中文语言包排除掉)
4、happyPack(多进程进行打包)
5、parallelUglifyPlugin(多进程打包 js,压缩,优化 js)
14、什么是长缓存?在 webpack 中如何做到长缓存优化? (高薪常问)
1、什么是长缓存
浏览器在用户访问页面的时候,为了加快加载速度,会对用户访问的静态资源进行存储,但是每一次代码升级或者更新,都需要浏览器去下载新的代码,最方便和最简单的更新方式就是引入新的文件名称
2、具体实现
在 webpack 中,可以在 output 给出输出的文件制定 chunkhash,并且分离经常更新的代码和框架代码,通过 NameModulesPlugin 或者 HashedModulesPlugin 使再次打包文件名不变
15、如何提高 webpack 的构建速度?(高薪常问)
在多入口情况下,使用 CommonsChunkPlugin 来提取公共代码
1、通过 externals 配置来提取常用库
2、利用 DllPlugin 和 DllReferencePlugin 预编译资源模块 通过 DllPlugin 来对那些我们引用但是绝对不会修改的 npm 包来进行预编译,再通过 DllReferencePlugin 将预编译的模块加载进来。
3、使用 Happypack 实现多线程加速编译
4、使用 webpack-uglify-parallel 来提升 uglifyPlugin 的压缩速度。 原理上 webpack-uglify-parallel 采用了多核并行压缩来提升压缩速度
5、使用 Tree-shaking 和 Scope Hoisting 来剔除多余代码
16、怎么实现 webpack 的按需加载?什么是神奇注释?(高
薪常问)
1、按需加载
在 webpack 中,import 不仅仅是 ES6 module 的模块导入方式,还是一个类似 require的函数,我们可以通过 import('module')的方式引入一个模块,import()返回的是一个 Promise对象;使用 import()方式就可以实现 webpack 的按需加载
2、神奇注释
在 import()里可以添加一些注释,如定义该 chunk 的名称,要过滤的文件,指定引入的文件等等,这类带有特殊功能的注释被称为神器注释