前端八股之工程化

Web前端八股文前端工程化
2025-03-12 - 20:00
四季橙子
2025-03-12 - 20:00

Git

1. 经常使用的git命令

git init                     // 新建 git 代码库
git add                      // 添加指定文件到暂存区
git rm                       // 删除工作区文件,并且将这次删除放入暂存区
git commit -m [message]      // 提交暂存区到仓库区
git branch                   // 列出所有分支
git checkout -b [branch]     // 新建一个分支,并切换到该分支
git status                   // 显示有变更文件的状态

2. git pullgit fetch的区别

git fetch只是将远程仓库的变化下载下来,并没有和本地分支合并。

git pull会将远程仓库的变化下载下来,并和当前分支合并。

3. git rebasegit merge的区别

git mergegit rebase都是用于分支合并,关键在commit记录的处理上不同:

  • git merge会新建一个新的commit对象,然后两个分支以前的commit记录都指向这个新commit记录。这种方法会保留之前每个分支的commit历史
  • git rebase会先找到两个分支的第一个共同的commit祖先记录,然后将提取当前分支这之后的所有commit记录,然后将这个commit记录添加到目标分支的最新提交后面。经过这个合并后,两个分支合并后的commit记录就变为了线性的记录了

Webpack

1. webpack与grunt、gulp的不同

Grunt、Gulp是**基于任务运⾏**的⼯具:它们会⾃动执⾏指定的任务,就像流⽔线,把资源放上去然后通过不同插件进⾏加⼯,它们包含活跃的社区,丰富的插件,能⽅便的打造各种⼯作流

Webpack是基于模块化打包的⼯具: ⾃动化处理模块,webpack把⼀切当成模块,当 webpack 处理应⽤程序时,它会递归地构建⼀个依赖关系图,其中包含应⽤程序需要的每个模块,然后将所有这些模块打包成⼀个或多个bundle

因此这是完全不同的两类⼯具,⽽现在主流的⽅式是⽤npm script代替Grunt、Gulp,npm script同样可以打造任务流

2. webpack、rollup优劣

webpack适⽤于⼤型复杂的前端站点构建: webpack有强⼤的loader和插件⽣态,打包后的⽂件实际上就是⼀个⽴即执⾏函数,这个⽴即执⾏函数接收⼀个参数,这个参数是模块对象,键为各个模块的路径,值为模块内容。⽴即执⾏函数内部则处理模块之间的引⽤,执⾏模块等,这种情况更适合⽂件依赖复杂的应⽤开发

rollup适⽤于基础库的打包,如vue、d3等: Rollup就是将各个模块打包进⼀个⽂件中,并且通过Tree-shaking来删除⽆⽤的代码,可以最⼤程度上降低代码体积,但是rollup没有webpack如此多的的如代码分割、按需加载等⾼级功能,其更聚焦于库的打包,因此更适合库的开发

3. 有哪些常⻅的Loader

  • file-loader:把⽂件输出到⼀个⽂件夹中,在代码中通过相对URL去引⽤输出的⽂件
  • url-loader:和file-loader类似,但是能在⽂件很⼩的情况下以base64的⽅式把⽂件内容注⼊到代码中去
  • source-map-loader:加载额外的Source Map⽂件,以⽅便断点调试
  • image-loader:加载并且压缩图⽚⽂件
  • babel-loader:把ES6转换成ES5
  • css-loader:加载CSS,⽀持模块化、压缩、⽂件导⼊等特性
  • style-loader:把CSS代码注⼊到JavaScript中,通过DOM操作去加载 CSS 注意:在Webpack中,loader的执行顺序是从右向左执行的。因为webpack选择了compose这样的函数式编程方式,这种方式的表达式执行是从右向左的

4. bundle,chunk,module是什么

  • bundle:是由webpack打包出来的⽂件;
  • chunk:代码块,⼀个chunk由多个模块组合⽽成,⽤于代码的合并和分割;
  • module:是开发中的单个模块,在webpack的世界,⼀切皆模块,⼀个模块对应⼀个⽂件,webpack会从配置的entry中递归开始找出所有依赖的模块。

5. Loader和Plugin的不同

不同的作⽤

Loader直译为"加载器"。Webpack将⼀切⽂件视为模块,但原生只能解析JS/JSON。Loader使webpack能加载和解析⾮JavaScript资源(如CSS/图片),​本质是文件转换器

Plugin直译为"插件"。Plugin通过钩⼦机制参与编译过程,​可修改输出产物、优化构建流程、注入环境变量等​(如DefinePlugin定义全局常量、HtmlWebpackPlugin生成HTML文件)。

不同的⽤法

Loader在module.rules中配置,也就是说他作为模块的解析规则⽽存在。 类型为数组,每⼀项都是⼀个Object⾥⾯描述了对于什么类型的⽂件(test),使⽤什么加载(loader)和使⽤的参数(options)

Plugin在plugins中单独配置。类型为数组,每⼀项是⼀个plugin的实例,参数都通过构造函数传⼊

6. webpack的构建流程

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

  1. 初始化参数:从配置⽂件和Shell语句中读取与合并参数,得出最终的参数;
  2. 开始编译:⽤上⼀步得到的参数初始化Compiler对象,加载所有配置的插件,执⾏对象的 run ⽅法开始执⾏编译;
  3. 确定⼊⼝:根据配置中的entry找出所有的⼊⼝⽂件;
  4. 编译模块:从⼊⼝⽂件出发,调⽤所有配置的Loader对模块进⾏翻译,再找出该模块依赖的模块,再递归本步骤直到所有⼊⼝依赖的⽂件都经过了本步骤的处理;
  5. 完成模块编译:在经过第4步使⽤Loader翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;
  6. 输出资源:根据⼊⼝和模块之间的依赖关系,组装成⼀个个包含多个模块的Chunk,再把每个Chunk转换成⼀个单独的⽂件加⼊到输出列表,这步是可以修改输出内容的最后机会;
  7. 输出完成:在确定好输出内容后,根据配置确定输出的路径和⽂件名,把⽂件内容写⼊到⽂件系统。

7. webpack的热更新是如何做到的?说明其原理?

核心流程(Webpack5优化版):

  1. 文件监听:基于watchOptions配置,通过轮询或系统API监听文件变化
  2. 增量编译: • 内存编译:将变更模块保存在内存中(避免磁盘IO) • 缓存复用:Webpack5的持久化缓存极大减少重复编译
  3. HMR Runtime通信: • 通过websocket(webpack-dev-server)或EventSource(webpack-hot-middleware)建立连接 • 增量更新协议:仅传输变更模块的hash标识而非完整文件
  4. 客户端处理: • HotModuleReplacementPlugin注入的runtime代码接收更新通知 • 发起JSONP请求获取最新模块代码(.hot-update.json.hot-update.js
  5. 模块热替换: • 比对依赖图:确定受影响的模块范围 • 执行module.hot.accept:应用新模块逻辑并保留应用状态 • 异常降级:HMR失败时自动回退到整页刷新

关键优化(Webpack5+):

快速 Hash 匹配:使用contenthash精确判断文件变更 • 增量编译缓存:通过filesystem缓存避免重复解析AST • Tree-shaking级更新:仅重新处理受影响模块的依赖链 • 模块联邦支持:支持跨应用的模块热替换(微前端场景)

原理解释简化版:当修改代码后,Webpack通过内存编译生成更新包,HMR Runtime像快递员一样把更新包发送给浏览器,浏览器像拼积木一样局部替换代码模块,同时保留应用状态(如Vue组件的data状态)。这整个过程通过Websocket和Hash校验实现高效通信。

Vite

1. 为什么Vite比Webpack快?

维度 Webpack Vite
启动方式 全量打包构建依赖图 按需编译 + 预构建缓存
HMR更新 整模块链重新打包 精准定位变更模块
构建工具 自建打包器 开发用ESM,生产用Rollup
编译语言 JS实现 利用esbuild用Go编写
模块处理 抽象依赖图 浏览器原生ESM解析

2. vite对比webpack,优缺点在哪

优点

  • 更快的冷启动:Vite借助了浏览器对ESM规范的支持,采取了与Webpack完全不同的unbundle机制
  • 更快的热更新:Vite采用unbundle机制,所以dev server在监听到文件发生变化以后,只需要通过ws连接通知浏览器去重新加载变化的文件,剩下的工作就交给浏览器去做了。

缺点

  • 开发环境下首屏加载变慢:由于unbundle机制,Vite首屏期间需要额外做其它工作。不过首屏性能差只发生在dev server启动以后第一次加载页面时发生。之后再reload页面时,首屏性能会好很多。原因是dev server会将之前已经完成转换的内容缓存起来
  • 开发环境下懒加载变慢:跟首屏加载变慢的原因一样。Vite在懒加载方面的性能也比Webpack差。由于unbundle机制,动态加载的文件,需要做resolve、load、transform、parse操作,并且还有大量的http请求,导致懒加载性能也受到影响。
  • webpack支持的更广。由于Vit 基于ES Module,所以代码中不可以使用CommonJs;webpack更多的关注兼容性, 而Vite关注浏览器端的开发体验。Vite目前生态还不如Webpack。

3. vite插件常见的hook有哪些?

  • config:可用于修改vite config,用户可以通过这个hook修改config;例如 vite-aliases这个插件可以帮助我们自动生成别名。它利用的就是这个钩子。
  • configResolved:在解析Vit 配置后调用,用于获取解析完毕的config,在这个 hook中不建议修改config。
  • configureServer:用于给dev server添加自定义middleware;例如vite-plugin-mock 插件就是在这个生命周期调用的
  • configurePreviewServer:与configureServer相同但是作为预览服务器。vite preview插件就是利用这个钩子。
  • transformIndexHtml:注入变量,用来转换HTML的内容。vite-plugin-html 插件可以帮助我们在html里注入变量,就是利用这个钩子
  • handleHotUpdate:执行自定义 HMR 更新处理
话题状态:正常
14