1. 对 webpack 的理解?解决了什么问题?
Webpack 是一个用于现代 Javascript 应用程序的静态模块打包工具
静态模块:在开发阶段,可以被 webpack 直接引用的资源。
webpack 能力:
1. 【 编译代码能力 】 ,提高效率,解决浏览器兼容问题;
2. 【 模块整合能力 】,提高性能,可维护性,解决浏览器频繁请求文件的问题;
3. 【 万物皆可模块能力 】,项目维护性增强,支持不同种类的前端模块类型,统一的模块化方案,所有资源文件的加载都可以通过代码控制。
2. webpack 构建流程?
1. 初始化流程: 从配置文件 和 Shell 语句中读取与合并参数,并初始化需要使用的插件和配置插件等执行环境所需要的参数
2.编译构建流程:从 Entry 发出,针对每个 Module 串行调用对应的 Loader 去翻译文件内容,再找到该 Module,递归的进行编译处理
3.输出流程: 对边以后的 Module 组合成 Chunk ( 代码块 ),把 Chunk 转换成文件,输出到文件系统
初始化 option ,开始编译 ,从 entry 开始递归的分析依赖,对每个依赖模块进行 build,对模块位置进行解析,开始构建某个模块,将 loader 加载完成的 module 进行编译,生成 AST ( 抽象语法树 ),遍历 AST ,当遇到 requir 等调用表达式是,收集依赖,所有的依赖 build 完成,开始优化,输出到 dist 目录
3. Webpack 中常见的 Loader ?解决了什么问题?
loader 用于对模块的 “源代码” 进行转换,在 import 或 “加载时” 预处理文件
4. Webpack 中常见的 Plugin ? 解决了什么问题?
Plugin 赋予 Webpack 各种灵活的功能,例如打包优化、资源管理、环境变量注入等,他们会运行在 Webpack 的不同阶段(钩子/ 生命周期),贯穿了 webpack 整个编译周期,目的在于解决 loader 无法实现的其他事
5. Webpack 说说 Loader 和 Plugin 的区别? 编写 Loader 、Plugin 思路?
区别:
- loader 运行在打包文件之前:实质是一个转换器,将 A 文件变成形成 B 文件,单纯的文件格式转换;
- plugin 在整个编译周期都起作用,在 Webpack 运行的生命周期中广播出许多事件, plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出的结果
编写 loader 需要遵循单一原则,每个 loader 只做一种“转义”工作。每个 loader 拿到的都是源文件内容(source),可以通过返回值的方式将处理后的内容输出,也可以调用 this.callback() 方法,将内容返回给 Webpack。还可以通过 this.async() 生成一个 callback 函数,再用这个 callback 将处理后的内容输出出去。也可以通过开发 loader 的工具函数集 ---- loader-utils
编写 plugin :通过监听特定事件
6. Webpack 的热更新是如何做到的? 原理是什么?
HMR ( Hot Module Replacement )
原理:
- 通过 webpack-dev-server 创建两个服务器: 提供静态资源的服务( Express )和 Socket 服务
- Express server 负责直接提供静态资源的服务 ( 打包后资源直接被浏览器请求和解析)
- Socket server 是一个 websocket 的长连接,双方可以互相通信
- 当 socket server监听到对应的模块发生变化时,会生成两个文件 .json ( manifest 文件 ) 和 .js ( unpdate chunk )
- 通过长连接,socket server 可以直接将这两个文件主动发送给客户端 ( 浏览器)
- 浏览器拿到两个新的文件后,通过 HMR runtime 机制,加载这两个文件,并且针对修改的模块进行更新
7. Webpack proxy 工作原理? 为什么能跨域?
proxy 工作原理: 实质利用 http-proxy-middleware 这个 http 代理中间件,实现请求转发给其他服务器
跨域:( 服务器和服务器之间请求数据并不会存在跨域行为,跨域行为是浏览器安全策略限制 )
在开发阶段, webpack-dev-server 会启动一个本地开发服务器,所以我们的应用在开发阶段是独立运行在 localhost 的一个端口上,而后端服务器有事运行在另外一个地址上。所以在开发阶段中,由于浏览器同源策略的原因,当本地访问后端就会出现跨域请求。
解决跨域: 当本地发送请求的时候,代理服务器响应该请求,并将请求转发到目标服务器上,目标服务器响应数据后再将数据返回给代理服务器,最终再由代理服务器将数据响应给本地。
8. 如何借助 Webpack 来优化前端性能
可以通过文件体积大小入手,其次还可通过分包的形式、减少http请求次数等方式,实现对前端性能的优化
-
JS、CSS、Html 代码 压缩
-
文件大小 压缩
-
图片 压缩
-
Tree Shaking ( 消除死代码 )
-
代码分离
-
内联 chunk
9.如何提高 Webpack 的构建速度?
主要可以从优化搜索时间、缩小文件搜索范围、减少不必要的编译等方面入手
- 优化 loader 配置 ( 通过配置
include
、exclude
、test属性来匹配文 ) - 合理使用 resolve.extensions
- 优化 resolve.modules ( 第三方模块的绝对路径,以减少寻找 )
- 优化 resolve.alias (
alias
给一些常用的路径起一个别名,例如:@) - 使用 DLLPlugin 插件
- 使用 cache-loader
- terser 启动多线程
- 合理使用 sourceMap
10. 与 Webpack 类似的工具还有哪些
- Rollup ( Vue、React 和 Three.js )
- Parcel ( 零配置、傻瓜式 )
- Snowpack ( 闪电般快速,较为复杂、Webpack 和 Parcel 的替代方案)
Webpack 的优势:
- 智能解析: 对 CommonJS、AMD、ES6 的语法做了兼容
- 万物模块: 对 js、css、图片等资源文件都支持打包
- 开箱即用: 集成 HRM、Tree-Shaking 等功能
- 代码分割: 可以将代码切割成不同的 chunk,实现按需加载,降低了初始化时间
- 插件系统: 具有强大的 Plugin 接口,具有更好的灵活性和扩展性
- 易于调试:支持 ScoureUrls 和 ScoureMap
- 快速运行: Webpack 使用异步 IO 并具有多级缓存,这使得 Webpack 很快且在增量编译上更加快
- 生态环境好:社区更丰富,出现问题更容易解决
11. webpack 常用字段
- main:定义了 npm 包的入口文件
- mudule: 定义了 npm 包的 ESM 规范的入口文件
- browser: 定义了 npm 包在 browser 环境下的入口文件