前端面试题----------------------webpack

1、什么是 webpack(必会)
        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 的热更新原理(必会)
        1、基本定义
        webpack 的热更新又称热替换(Hot Module Replacement),缩写为 HMR。这个机制可以
做到不用刷新浏览器而将新变更的模块替换掉旧的模块。
        2、核心定义
        2,1)HMR 的核心就是客户端从服务端拉去更新后的文件,准确的说是 chunk diff (chunk
需要更新的部分),实际上 WDS 与浏览器之间维护了一个 websocket,当本地资源发生变化时,
WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比
        2,2)客户端对比出差异后会向 WDS 发起 Ajax 请求来获取更改内容(文件列表、
hash), 这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该 chunk 的增量更新
        2,3)后续的部分(拿到增量更新之后如何处理?哪些状态该保留?哪些又需要更新?)
由 HotModulePlugin 来完成,提供了相关 API 以供开发者针对自身场景进行处理,像
react-hot-loader 和 vue-loader 都是借助这些 API 实现 HMR
5、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 更倾向于前端开发者的思路
6、有哪些常见的 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 代码
7、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 的实例,参数都
通过构造函数传入
8、webpack3 和 webpack4 的区别(必会)
        1、mode/–mode 参数,新增了 mode/--mode 参数来表示是开发还是生产 (development/production)
        2、Production,侧重于打包后的文件大小,development 侧重于 goujiansud
        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-extract-plugin,production 模式,增加 minimizer
9、分别介绍一下 bundle,chunk,module 的作用是什么(必 会)
        1、module:开发中的每一个文件都可以看作是 module,模块不局限于 js,也包含 css, 图片等
        2、chunk:表示代码块,一个 chunk 可以由多个模块组成
        3、bundle:最终打包完成的文件,一般就是和 chunk 一一对应的关系,bundle 就是对chunk 进行编译压缩打包等处理后的产出
10、如何利用 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 来代替
11、是否写过 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 方法
12、使用 webpack 开发时,你用过哪些可以提高效率的插件? (高薪常问)
        1、webpack-dashboard:可以更友好的展示相关打包信息。
        2、webpack-merge:提取公共配置,减少重复配置代码
        3、speed-measure-webpack-plugin:简称 SMP,分析出 webpack 打包过程中 Loader 和
Plugin 的耗时,有助于找到构建过程中的性能瓶颈
        4、size-plugin:监控资源体积变化,尽早发现问题
        5、HotModuleReplacementPlugin:模块热替换
14、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 体积大小,并降 低整体性能
15、请详细说明一下 Babel 编译的原理是什么?(高薪常问)
        大多数 JavaScript Parser 遵循 estree 规范,Babel 最初基于 acorn 项目(轻量级现JavaScript
        解析器) Babel 大概分为三大部分:
        1、解析:将代码转换成 AST
        2、词法分析:将代码(字符串)分割为 token 流,即语法单元成的数组
        3、语法分析:分析 token 流(上面生成的数组)并生成 AST,转换:访问 AST 的节点进行变
换操作生产新的 AST,taro 就是利用 babel 完成的小程序语法转换,生成:以新的 AST 为基础
生成代码
16、在生产环境下如何提升 webpack 优化构建速度(高薪常 问)
        1、优化 babel-loader(加缓存,加 hash)
        2、noParse(不去解析属性值代表的库的依赖)
        3、IgnorePlugin(忽略本地化内容,如引入了一个插件,只用到了中文语言包,打包的时候
把非中文语言包排除掉)
        4、happyPack(多进程进行打包)
        5、parallelUglifyPlugin(多进程打包 js,压缩,优化 js)
17、什么是长缓存?在 webpack 中如何做到长缓存优化?(高 薪常问)
        1、什么是长缓存
        浏览器在用户访问页面的时候,为了加快加载速度,会对用户访问的静态资源进行存
储,但是每一次代码升级或者更新,都需要浏览器去下载新的代码,最方便和最简单的更新方式
就是引入新的文件名称
        2、具体实现
        在 webpack 中,可以在 output 给出输出的文件制定 chunkhash,并且分离经常更新的代
码和框架代码,通过 NameModulesPlugin 或者 HashedModulesPlugin 使再次打包文件名不变
18、如何提高 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 来剔除多余代码
19、webpack 的占位符[hash],[chunkhash],[contenthash] 有什么 区别和联系(高薪常问)
        1、[hash]:是整个项目的 hash 值,其根据每次编译内容计算得到,每次编译之后都会生成
新的 hash,即修改任何文件都会导致所有文件的 hash 发生改变;在一个项目中虽然入口不同,
但是 hash 是相同的,hash 无法实现前端静态资源在浏览器上长缓存,这时候应该使用 chunkhash
        2、[chunkhash]:根据不同的入口文件(
entry)进行依赖文件解析,构建对应的 chunk,生成
相应的 hash,只要组成 entry 的模块文件没有变化,则对应 hash 也是不变的,所以一般项目优化
时,会将公共代码库拆分到一起,因为公共代码库代码变动较少的,使用 chunkhash 可以发挥最
长缓存的作用
        3、[contenthash]:使用 chunkhash 存在一个问题,当在一个 js 文件引入 css 文件,编译后他们的 hash 是相同的,而且,只要 js 文件内容发生改变,与其关联的 css 文件 hash 也会改变,针对这种情况,可以把 css 从 js 中抽离出来并使用 contenthash
20、怎么实现 webpack 的按需加载?什么是神奇注释?(高薪 常问)
        1、按需加载
        在 webpack 中,import 不仅仅是 ES6 module 的模块导入方式,还是一个类似 require 的
函数,我们可以通过 import('module')的方式引入一个模块,import()返回的是一个 Promise 对象;
使用 import()方式就可以实现 webpack 的按需加载
        2、神奇注释
        在 import()里可以添加一些注释,如定义该 chunk 的名称,要过滤的文件,指定引入
的文件等等,这类带有特殊功能的注释被称为神器注释
21、开发一个 jQuery 插件、vue 组件等,需要怎么配置 webpack (了解)
        如果打包的目的是生成一个共别人使用的库,那么可以使用 output.library 来指定库的名称库
的名称支持占位符与普通字符串。
        1、使用 output.library 确定了库的名称之后,还可以使用 output.libraryTarget 指定库打包出
来的规范。
        2、使用 output.externals 配置项去除输出的打包文件中依赖的某些第三方 js 模块(例如
jquery,vue 等)。这些被依赖的模块应该由使用者提供,而不应该包含再 js 库文件中
22、Babel 的 preset-env 是什么(了解)
        babel 的语法转换是通过强大的插件系统来支持的 babel 的插件分为两类:转换插件和语法
解析插件
        1、不同的语法对应着不同的转换插件,比如我们要将箭头函数转换成为 es5 的函数写法,
那么可以单独安装@babel/plugin-transform-arrow-functrions 插件
        2、如果不想一个个的添加插件,那么可以使用插件组合 preset(插件预设,插件组合更加
好理解一些),最常见的 preset 是@babel/preset-env
23、怎么配置单页应用?怎么配置多页应用?(了解)
        1、基本定义
        1.1)单页应用可以理解为 webpack 的标准模式,直接在 entry 中指定单页应用的入口
即可
        2.2)多页应用的话,可以使用 webpack 的 AutoWebPlugin 来完成简单自动化的构建,
但是前提是项目的目录结构必须遵守他预设的规范
        2、 配置方式
        多页应用中要注意的是:每个页面都有公共的代码,可以将这些代码抽离出来,避免
重复的加载,比如,每个页面都引用了同一套 css 样式表,随着业务的不断扩展,页面可能会不
断的追加,所以一定要让入口的配置足够灵活,避免每次添加新页面还需要修改构建配置
24、文件指纹是什么?怎么用?(了解)
        文件指纹是打包后输出的文件名的后缀
        1、Hash:和整个项目的构建相关,只要项目文件有修改,整个项目构建的 hash 值就会更
        2、Chunkhash:和 webpack 打包的 chunk 有关,不同的 entry 会生出不同 chunkhash
        3、Contenthash:根据文件内容来定义 hash,文件内容不变,则 contenthash 不变

你可能感兴趣的:(前端面试题,前端,webpack,javascript)