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 进行三方包分割
相关推荐
tianzhiyi1989sq1 小时前
Vue3 Composition API
前端·javascript·vue.js
袋鱼不重2 小时前
手把手搭建Vue轮子从0到1:5. Ref 模块的实现
前端·vue.js·源码
JSON_L3 小时前
Vue 详情模块 4
前端·javascript·vue.js
裕波5 小时前
Vue 与 Vite 生态最新进展:迈向一体化与智能化的未来
前端·vue.js
ZoeLandia6 小时前
Webpack 搭建 Vue3 脚手架详细步骤
前端·vue.js·webpack
Sun_Smile7 小时前
Element-Plus二次封装el-form的ProForm表单组件,仿Antd Design Pro,json表单,联动表单,动态表单,源码可灵活定制和扩展
vue.js
VisuperviReborn10 小时前
打造自己的前端监控---前端错误监控
前端·javascript·vue.js
wayhome在哪10 小时前
面试造火箭 入职拧螺丝
vue.js·面试·jquery
雪中何以赠君别10 小时前
Vite + Axios + Nginx 环境变量与代理配置笔记
前端·javascript·vue.js