最近准备找实习,总结一下项目中的重难点,这是实习系列的第一篇,我将更新这个系列直到找到实习。
目录
问题二:除了转义之外,webpack还做了哪些工作?为什么要做这些工作?
依赖解析阶段(Dependency Resolution Phase):
webpack打包
问题一:webpack等构建工具产生的原因和背景
1.为什么
1)浏览器无法直接解析的文件
- TypeScript(.ts):需编译为 JavaScript。
- 现代浏览器支持大部分 ES6+ 语法(如 let、async/await),但旧浏览器(如 IE11)可能需要转译(通过 Babel)
- SASS/LESS(.scss/.less):需编译为 CSS。
- Vue/React 单文件组件(.vue/.jsx):需通过构建工具(如 vue-loader、babel)转换。
- 非标准或自定义文件,如 .txt、.md、.yaml 等需通过 JavaScript 读取并手动处理。
- 服务端脚本,如 .php、.py、.node 需后端服务器处理。
2)哪些方法处理这些文件,来让浏览器接收?
首先明确,必须使用构建工具,如webpack,vite等,此外可以选择一些轻量级构建工具esbuild 和 swc 是超快的 JavaScript/TypeScript 编译器,可以替代 Webpack 进行构建。
3)webpack的输入输出是什么?
输入:原项目文件,如js,less,vue,file,png等
输出:浏览器可以处理的文件,如es5语法的js文件,css(vue文件会被拆分成html,css和js文件)
2.webpack是如何做到的?
通过loader转义
(转义不会改变依赖关系,也不会进行代码分割,代码分隔是用SplitChunksPlugin实现的)
问题二:除了转义之外,webpack还做了哪些工作?为什么要做这些工作?
1.构建依赖图
这是webpack开始处理文件的第一步,根据入口文件层层递归import/require语句,生成依赖图
(依赖分析阶段就已经过滤掉了用不到的文件)
2.使用根据依赖图顺序,使用loader进行转义
3.代码优化阶段:通过代码分割、摇树等
4.输出文件到指定目录
总结:初始化-构建依赖图-编译-优化-输出
5.执行阶段与钩子函数
-
初始化阶段(Initialization Phase):
读取和解析 Webpack 配置文件(webpack.config.js 或 webpack.config.ts)。
初始化 Compiler 实例,设置各种参数和插件。
钩子函数:compile(触发时机:在 Webpack 开始编译之前触发。)
-
依赖解析阶段(Dependency Resolution Phase):
从入口文件(Entry File)开始,解析代码中的模块依赖关系。
递归解析 import、require 等语句,构建出整个项目的依赖图。
这个阶段的主要工作是确定哪些模块需要被打包,以及它们之间的依赖关系。
钩子函数:
compilation(触发时机:每次创建新的编译(Compilation)对象时触发(如文件变化后重新构建)。)
make(触发时机:开始构建模块依赖图之前。)
-
编译阶段(Compilation Phase):
根据依赖图,将每个模块的内容加载到内存中。
使用 Loader 对模块进行转换(如将 TypeScript 转换为 JavaScript,或处理 CSS 文件)。
这个阶段的输出是经过 Loader 处理后的模块内容。
钩子函数:
buildModule(触发时机:在模块被构建前触发(Loader 转译之前)。)
succeedModule(触发时机:模块成功构建后(Loader 转译完成)。)
-
优化阶段(Optimization Phase):
对模块进行优化,例如代码压缩、提取公共模块、分割代码等。
使用 Plugin(如 UglifyJsPlugin、CommonsChunkPlugin 等)进行进一步的优化。
钩子函数:
optimize(触发时机:依赖图构建完成后,开始优化之前。)
optimizeChunks(触发时机:优化 Chunk 拆分时(如 SplitChunksPlugin 工作前)。)
-
输出阶段(Emit Phase):
将优化后的模块内容打包成最终的输出文件(如 bundle.js)。
将生成的文件写入到输出目录中。
钩子函数:
emit(触发时机:在资源写入输出目录之前。)
afterEmit(触发时机:资源已写入磁盘后。)
-
收尾阶段:
钩子函数:
done(触发时机:构建完全结束(成功或失败)。)
failed(触发时机:构建失败时。)
问题三:代码分割(分包)有什么好处?
如果不用代码分割,对于公共模块/第三方库,只要用到一次就打包一次,使用代码分割将公共模块单独提取出来。