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 进行三方包分割
相关推荐
天意pt24 分钟前
Blog-SSR 系统操作手册(v1.0.0)
前端·vue.js·redis·mysql·docker·node.js·express
清风ai明月1 小时前
在vue3中Promise是什么
vue.js
毕设源码-邱学长1 小时前
【开题答辩全过程】以 基于VUE的打车系统的设计与实现为例,包含答辩的问题和答案
前端·javascript·vue.js
麦麦大数据1 小时前
J009 美食推荐可视化大数据系统vue+springboot
vue.js·spring boot·mysql·推荐算法·美食·可视化分析·沙箱支付
rfidunion2 小时前
springboot+VUE+部署(1。新建项目)
java·vue.js·spring boot
Irene19912 小时前
在 Vue 中使用 TypeScript 的几种方式
vue.js·typescript
hhcccchh3 小时前
学习vue第八天 Vue3 模板语法和内置指令 - 简单入门
前端·vue.js·学习
yyf198905253 小时前
Vue 框架相关中文文献
前端·javascript·vue.js
粥里有勺糖3 小时前
开发一个美观的 VitePress 图片预览插件
前端·vue.js·vitepress
鹏多多4 小时前
jsx/tsx使用cssModule和typescript-plugin-css-modules
前端·vue.js·react.js