跳到主要内容

谈谈webpack和vite

谈谈webpack和vite对比​

webpack和vite有很大的区别,比如在热更新、打包、预构建等

  • 打包方面:
    • webpack是对项目进行整体的打包,随着项目复杂增大,打包的速度也会变慢,而vite在开发环境中是利用浏览器ESModule按需加载,不会因为项目变大而变慢
  • 热更新和按需编译:
    • webpack:webpack通过webpack-dev-server等工具实现热更新,但在某些情况下需要重新编译和打包整个应用,因此可能会有一定的性能损耗。
    • Vite: Vite利用浏览器原生支持的ES模块特性,可以实现按需编译和热更新,因此具有更快的热更新速度和开发体验
  • 预构建:
    • vite使用了esbuild进行预构建,将依赖项转换为ES模块,以提高开发时的性能和体验。

vite的快体现在哪里?​

  • 快速的冷启动:
    • Vite 之所以快,借助了浏览器对 ESM规范的支持
    • vite不需要做 bundle 操作,即不需要构建
    • 模块之间的依赖关系的解析由浏览器实现
    • 文件的转换由 dev server 的 middlewares 实现并做缓存
  • 快速的热更新:
    • 由于 Vite 采用 unbundle 机制,所以 dev server 在监听到文件发生变化以后,只需要通过 websocket 连接通知浏览器去重新加载变化的文件,剩下的工作就交给浏览器去做
  • 按需编译:
    • Vite只编译需要的模块,而不是整体打包,这可以提高开发时的编译速度,尤其在项目规模较大时效果更为明显。
  • 预构建缓存:
    • Vite 将预构建的依赖项缓存到 node_modules/.vite ,避免重复编译打包
    • 什么情况会重新进行预构建?
      • 包管理的锁文件变化,例如 package-lock.json,yarn.lock,pnpm-lock.yaml
      • vite.config.js 中的相关字段
      • NODE_ENV 的值,预构建只针对开发环境

vite的缺点有吗,说说什么方面?​

  • 首屏性能 【首次启动加载慢】
    • 不对源文件做合并捆绑操作,导致大量的 http 请求;
    • dev server 运行期间对源文件做 resolve、load、transform、parse 操作;
    • 预构建、二次预构建操作也会阻塞首屏请求,直到预构建完成为止;

不过首屏性能差只发生在 dev server 启动以后第一次加载页面时发生。之后再 reload 页面时,首屏性能会好很多。原因是 dev server 会将之前已经完成转换的内容缓存起来

  • 懒加载性能
    • 和首屏一样,由于 unbundle 机制,动态加载的文件,需要做 resolve、load、transform、parse 操作,并且还有大量的 http 请求,导致懒加载性能也受到影响

如何优化?​

  • 可以通过 prefetch、持久化缓存等手段做优化
  • 减少http请求
  • 预构建:将第三方依赖代码的多个文件模块合并为一个模块,也是减少http请求
  • 代码分割
    • 做到按需加载、利用缓存

谈谈weppack打包过程​

  • 1、解析入口文件,分析内容, 获取AST抽象语法树
  • 2、找出所有依赖模块
  • 3、AST转化编码code
  • 4、递归解析所有依赖项、生成依赖关系图
  • 5、输出bundle

谈谈你是如何使用webpack​

配置webpack、优化webpack方案

参考create-react-app脚手架源码配置,里面集成了webpack的配置和优化

对webpack常规的配置,以及webpack的性能优化,如构建的速度进行优化、对包的体积大小优化、页面加载优化等

  • 比如比较常规的优化 (静态资源优化、图片优化、css压缩、js压缩)

    • 小图片的话 (小于5kb),进行base64格式产出
  • 代码分割/代码拆分,optimization.splitChunks

    • 提取公共模块, 移除了重复的依赖模块, 减轻了大小 (比如lodash)
      • 防止一些依赖包重复打包
    • 把第三方依赖包打包成vendor
      • 核心是把第三方依赖抽离出来,和业务代码js分开
      • 可以更好利用缓存,因为第三方库通常不会经常变化,可以利用缓存,减少了初始加载时间
        • 浏览器去请求资源的时候,会从缓存中获取vendor
  • 组件异步加载分包优化

    • 利用optimization.runtimeChunks 设置为true
      • 运行时代码单独打包出来
        • 对于异步加载的代码,在webpack中称为运行时代码
      • 如果不将它提取出来的话,每次修改这个异步加载的文件, app.js每次都会改变,导致浏览器缓存失效,如果提取出来之后,app.js就不会被影响到,只是runtime.js会发生改变
        • 但是也有个缺点:异步加载单独打包出来的runtime文件,浏览器需要请求,会增加http请求
        • 解决办法:可以把打包出来的runtime文件内联到index.html中,就不会增加http请求问题了
    • 组件按需加载 (异步加载)
      • 如react中, 利用lazy和Suspense
      • 如通过import('组件/库')来动态加载组件和库
  • css和js分离拆分

    • 利用mini-css-extract-plugin插件, 可以更好地利用缓存,CSS 文件的缓存,页面访问速度自然会加快
  • 持久化缓存提高构建速度,将缓存设置在文件系统中,存储在磁盘,下次构建利用缓存的构建内容

  • 配置cache, cache支持memory'|'filesystem, 默认是memory内存

    • 支持缓存设置为内存和文件系统
    • 内存肯定是比文件系统快,但是注意,内存缓存的话,也会损失可持久性,webpack关了就没了,而文件系统是一直存在在硬盘中
  • 一般设置 持久缓存会将缓存存储到文件系统磁盘中

  • 打包出来的文件加hash

    • 打包后的文件,加上hash,利用浏览器的缓存机制,那么在加载资源会从缓存中获取,就不用重新加载一遍新资源
      • 没有发生变化的文件,hash值不会变,就可以利用缓存
    • 推荐使用contenthash,文件内容发生变化,hash就会发生变化
  • 设置sideEffects,标记副作用

    • 如果代码存在副作用,不要被tree shaking掉,否则代码被删掉
    • 如一些全局的css,这些就是副作用
  • dll分包: 只需要一次构建就好,不需要每次都构建,完全没必要,会导致构建速度慢

  • 预加载优化

    • 通过组件异步加载打包优化
  • 预获取优化

    • 比如在页面A 可能要去B页面

你是怎么分析webpack的性能​

  • 使用了webpack构建编译速度测量的插件: speed-measure-webpack-plugin

    • 可查看构建编译所花费的时长
  • 当开启了cache缓存之后,构建速度效果是非常明显的,通过查看构建编译时间可以知道, 提升30倍的构建速度!

谈谈你是如何使用vite​

1、如何做配置vite

2、如何优化vite

如何优化vite

  • 预构建优化,针对开发环境
  • 网络优化,开启http2
  • 代码分割
    • manualChunks进行分包,是基于rollup
    • 把第三方依赖进行分包,vite默认代码分包,是单独打包在vendor中,而vendor随之项目复杂依赖的包越多会变得越大,需要自定义分包,把vendor拆出来
    • 提高了对第三方依赖包的缓存

谈谈vite预构建​

预构建仅适用于开发模式, 通过optimizeDeps开启预构建

  • 将非 ESM 格式的代码转换为符合 ESM 规范格式的代码;
  • 将第三方依赖代码的多个文件模块合并为一个模块,减少 http 请求数量
    • 比如lodash-es,里面内置了几百个模块,比如用了get方法,这个方法会依赖了很多工具函数,而每个import都会触发一次请求,导致触发了很多请求,大量的请求会造成网络阻塞,导致页面加载十分缓慢
      • 在进行依赖的预构建之后,lodash-es这个库的代码被打包成了一个文件,这样请求的数量会减少,页面加载也快了许多

Vite热更新为什么比Webpack热更新快?​

Webpack热更新运行机制:

​ Webpack会遍历你的应用程序中的所有文件,并启动一个开发服务器(Webpack-dev-server),然后将整个代码渲染到开发环境中。从entry入口文件开始,将其依赖的资源文件通过loader打包成一个文件夹,然后通过server传递到客户端运行;也正是因为这样的运行机制,也必将导致项目代码量增多,应用体积增大之后,Webpack热更新需要等待较久的时间才能反映到浏览器中;

​ Vite热更新运行机制:

​ Vite会在本地启动一个Vite Server服务,对于第三方依赖使用了速度更快的esbuild预构建,对于业务代码使用原生的ESM,访问这个服务,加载对应模块的服务端资源,绕过了构建打包过程,对请求的模块进行实时按需编译,热更新时仅需重新请求改动过的模块即可,而且热更新的速度不会随着模块增多而变慢

vite是直接启动开发服务器,请求哪个模块再对该模块进行实时编译。 而webpack会先打包, 然后再启动开发服务器。webpack打包过程中,会分析模块依赖、转换代码,编译代码

vite在启动的时候不需要打包,也就意味着不需要分析模块的依赖、不需要编译,因此启动速度非常快

​