前端面试-webpack系列(webpack真题总结)

422 阅读5分钟

1、前端为什么要进行打包和构建

代码层面

-- 体积更小(Tree-shaking,压缩,合并),加载更快

-- 编译高级语言和语法(TS,ES6+,模块化,sass等)

-- 兼容性和错误检查(polyfill,postcss,eslint)

研发流程

-- 统一、高效的开发环境

-- 统一的构建流程和产出标准

-- 集成公司构建规范(提测、上线等)

2、module、chunk、bundle的区别

-- module各个源码文件,webpack中一切皆模块

-- chunk多模块合成的一个代码产出块,如entry、import()、splitChunk等

-- bundle最终产出的文件,每个chunk打包完都会产生一个bundle

3、loader和plugin的区别

-- loader模块转换器,单纯文件转换的过程,如less -》css

-- plugin就是个扩展插件,针对的是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听ebpack打包过程中的某些节点,执行广泛的任务

4、常见的loader和plugin有哪些

loader:

-- babel-loader(语法转化)

-- style-loader、css-loader、postcss-loader、less-loader(样式处理的loader)

-- file-loader、url-loader(处理文件)(url-loader一般线上使用缓存等去优化构建)

-- thread-loader多进程构建

plugin:

-- HtmlWebpackPlugin(生成html模版)

-- MiniCssExtractPlugin(抽离公共css)

-- HappyPack多进程构建

-- parallelUglifyPlugin多进程压缩

-- HotModuleReplacementPlugin热跟新

-- DllPlugin分包

5、babel和webpack的区别

-- babel js新语法编译工具,不关心模块化

-- webpack 打包构建工具,是多个loader和plugin的集合

6、如何产出一个lib

output: {
	// lib文件名
	filename: 'lodash.js',
	// 输出lib到dist目录下
	path: disPath,
	// lib的全局变量名
	library: 'lodash'
}

7、babel-polypill和babel-runtime的区别

-- babel-polypill会污染全局,babel-runtime不会
-- 产出第三方lib要用babel-runtime

8、webpack如何实现懒加载

-- import()
-- 结合vue,react的异步组件
-- 结合vue-router,react-router异步加载路由

9、为何proxy不能被polyfill

-- class可以用function模拟

-- promise可以通过回调模拟

-- proxy无法用Object.defineProperty模拟

10、webpack性能优化方法

-- 使用高版本的webpack
-- 多线程/多实例构建:

​ happyPack(被后续版本弃用)、thread-loader

​ parallelUglifyPlugin多进程压缩js(不推荐使用,项目基本处于没人维护阶段)

-- 缩小打包作用域:

​ exclude/include(确定loader范围)

​ resolve.modules指明第三方模块的绝对路径(减少不必要的查找)

​ resolve.extensions尽可能减少后缀尝试的可能性

​ noParse对完全不需要解析的库进行忽略(不去解析但仍会打包到bundle中,注意被忽略的文件里面不应该包括import、require、define等语句)

​ IgnorePlugin(完全排除模块)

​ 合理利用alias

-- 充分利用缓存提升二次构建速度

​ 优化babel-loader

​ terser-webpack-plugin开启缓存

​ DllPlugin 动态链接库插件进行分包

11、webpack优化产出代码方法

-- 小图片base64位编码

-- bundle + hash

-- 懒加载

-- 提取公共代码

-- ignorePlugin

-- 使用cdn加速

-- 使用production(自动压缩代码和使用Tree-Shaking;注意:ES6 Module才能让tree-shaking生效;commonjs不行)

-- Scope Hosting

12、简述webpack的构建流程

Webpack 的运⾏流程是一个串⾏的过程,从启动到结束会依次执⾏以下流程 :

初始化参数:从配置⽂件和 Shell 语句中读取与合并参数,得出最终的参数

开始编译:⽤上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执⾏对象的 run ⽅法开始执⾏编译

确定⼊⼝:根据配置中的 entry 找出所有的⼊⼝⽂件

编译模块:从⼊⼝⽂件出发,调⽤所有配置的 Loader 对模块进⾏翻译,再找出该模块依赖的模块,再递归本步骤直到所有⼊⼝依赖的⽂件都经过了本步骤的处理

完成模块编译:在经过第 4 步使⽤ Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系

输出资源:根据⼊⼝和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的⽂件加⼊到输出列表,这步是可以修改输出内容的最后机会

输出完成:在确定好输出内容后,根据配置确定输出的路径和⽂件名,把⽂件内容写⼊到⽂件系统

在以上过程中,Webpack 会在特定的时间点⼴播出特定的事件,插件在监听到感兴趣的事件后会执⾏特定的逻辑,并且插件可以调⽤ Webpack 提供的 API 改变Webpack 的运⾏结果

13、简述babel的编译过程

Babel 是⼀个 JavaScript 编译器,是⼀个⼯具链,主要⽤于将采⽤ ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运⾏在当前和旧版本的浏览器或其他环境中。

Babel 本质上就是在操作 AST 来完成代码的转译。AST是抽象语法树(Abstract Syntax Tree, AST)如果想要了解更多,可以阅读和尝试:

​ -- 分析 AST :ASTexplorer.net

​ -- AST 规范:github.com/estree/estr…

Babel 的功能很纯粹,它只是⼀个编译器。⼤多数编译器的⼯作过程可以分为三部分:

​ -- 解析(Parse) :将源代码转换成更加抽象的表示⽅法(例如抽象语法树)。包括词法分析和语法分析。词法分析主要把字符流源代码(Char Stream)转换成令牌流( Token Stream),语法分析主要是将令牌流转换成抽象语法树(Abstract Syntax Tree,AST)。

​ -- 转换(Transform) :通过 Babel 的插件能⼒,对(抽象语法树)做⼀些特殊处理,将⾼版本语法的 AST 转换成⽀持低版本语法的 AST。让它符合编译器的期望,当然在此过程中也可以对 AST 的 Node 节点进⾏优化操作,⽐如添加、更新以及移除节点等。

-- ⽣成(Generate) :将 AST 转换成字符串形式的低版本代码,同时也能创建 Source Map 映射。

经过这三个阶段,代码就被 Babel 转译成功了。