vite 构建实现增量更新

问题描述:

vite项目中,尽管每次只是部分文件更新,但构建之后,由于组件依赖关系,只要其中一个文件内容发生变化并且文件使用了[hash] 配置(相当于内容hash),其他文件的导入路径都会更新,导致内容变化,文件指纹也会变化。

解决思路:

vite 仓库相关 issue 和讨论 github.com/vitejs/vite...

主要是入口文件(entryFileNames)的路径名变化,影响绝大部分模块。 所以想要实现增量更新,这个入口文件名最好固定。

  1. 固定入口文件会导致浏览器缓存,整个应用都不再更新。
  2. 虽然可以在加载入口文件时加一个 query 时间戳。但是动态的组件中,对这个入口文件引用是不带query的,控制台会报错,页面会白屏。
  3. 要解决上面问题,就需要所有引用入口文件的地方,全部带上时间戳。可以借助 importmap 进行映射。实现一个 plugin,自动在入口文件后面拼接时间戳,同时在 head 头中注入 importmap。
ts 复制代码
entryFileNames: "assets/[name].main.js"
chunkFileNames: "assets/[name].[hash].js"
ts 复制代码
import type { Plugin } from 'vite'

export default function viteImportMapPlugin(): Plugin {
  return {
    name: 'html-entry-version-with-importmap',
    transformIndexHtml(html) {
      const version = Date.now()
      // 1. 给入口文件加 query
      const updatedHtml = html.replace(
        /(<script[^>]+src=")([^"]*main)(.js)"/,
        `$1$2.js?v=${version}"`
      )
      // 2. 在 HTML 中插入 importmap
      // 提取 main.js 路径(不带 query)
      const match = html.match(/<script[^>]+src="([^"]*main).js"/)
      if (!match) return updatedHtml
      const entryPath = match[1] + '.js'
      const entryWithVersion = `${entryPath}?v=${version}`
      const importmap = `\n  <script type="importmap">\n    {\n      "imports": {\n        "${entryPath}": "${entryWithVersion}"\n      }\n    }\n  </script>\n`
      // 3. 把 importmap 插入到 </head> 前
      return updatedHtml.replace('</head>', `${importmap}\n</head>`)
    }
  }
}

可能存在的问题:

  1. importmap 兼容性,如果浏览器不支持,需要使用 es-module-shims 进行 polyfill。并且这个文件需要写在头部,使用 async属性,因为 importmap 是静态映射表,加载完成后,无法热更新。
ts 复制代码
<script async src="/es-module-shims.min.js"></script>
  1. 不适合多入口文件(应该可搞),不支持 SSR等。
  2. 观察一段时间看看是否有副作用。

其他优化

  • 利用 manualChunks 进行三方包分割
相关推荐
前端开发爱好者44 分钟前
弃用 ESLint + Prettier!快 35 倍的 AI 格式化神器!
前端·javascript·vue.js
&白帝&1 小时前
vue2和vue3的对比
javascript·vue.js·ecmascript
骑驴看星星a2 小时前
Vue中的scoped属性
前端·javascript·vue.js
四月_h2 小时前
在 Vue 3 + TypeScript 项目中实现主题切换功能
前端·vue.js·typescript
qq_427506082 小时前
vue3写一个简单的时间轴组件
前端·javascript·vue.js
OpenTiny社区5 小时前
TinyEngine 2.8版本正式发布:AI能力、区块管理、Docker部署一键强化,迈向智能时代!
前端·vue.js·低代码
qfZYG5 小时前
Trae 编辑器在 Python 环境缺少 Pylance,怎么解决
前端·vue.js·编辑器
北辰浮光7 小时前
[Web数据控制]浏览器中cookie、localStorage和sessionStorage
前端·vue.js·typescript
用户841794814567 小时前
vue 如何使用 vxe-table 来实现跨表拖拽,多表联动互相拖拽数据
前端·vue.js
好好好明天会更好7 小时前
Vue中this.$options.data()是什么东西?
前端·vue.js