资讯动态

Vue3 + Vite 单页应用改造多页应用:实战流程与踩坑记录

发布时间:2026/10/18 7:59:04 来源:尧图企业网站定制
纯Markdown输出从正文开始。开头部分前一阵子接了个活儿把公司一个 Vue 3 Vite 的单页应用改成多页应用。项目本身跑得挺稳但新需求来了要加一个独立的活动落地页还得让这个落地页单独发布、单独回滚不能跟着主应用一个版本走。这就逼着我去折腾单页面改多页面的改造方案。其实vue3vite单页面改多页面这个事说难不难说简单也有一堆细节坑。Vite 默认就是单页模式所有东西挂在一个 index.html 入口下要改成多页核心就是两条线一是给每个页面准备独立的 HTML 入口和 JS 入口二是在 vite.config.js 里把 rollupOptions.input 从单一入口改成多入口配置。但真正落地的时候路由模式、资源路径、构建分包、组件复用、部署回退这些环节都会冒出来每一步都可能翻车。这篇博文就把我从需求分析到改造上线整个过程的思路、操作步骤、踩过的坑整理出来给要干同样事情的同学一个可以直接参考的路线图。不管你是刚接手一个老项目要改结构还是新项目一开始就想用多页架构这篇文章都能帮上忙。1. 先想明白单页模式卡在哪多页模式又能解决什么1.1 单页应用的真实痛点单页应用SPA的模型很简单整个应用只有一个 index.html前端用路由去切换页面。Vue Router 接管了 URL 的变化组件动态渲染用户操作时页面不刷新体验很顺滑。但这个模型有两个隐藏问题平时不显眼需求一变就露馅。第一个问题是首屏负担。单页应用不管用户访问的是首页还是某个深层页面浏览器都必须先加载整个打包后的 JS 包至少包含路由表中所有页面组件对应的代码除非你做了按需加载。我一直记得一个项目主应用光 vendor 打包出来就 1MB 多活动页用户其实只需要看一个表单结果也要等整包 JS 下载完才能渲染出来。这在弱网情况下用户流失率非常明显。第二个问题是发布耦合格局固定。单页应用只有一个入口所以部署上天然是一起发布。哪怕你只是改了一个活动页的小按钮文案也要走一遍主应用的整体发布流程。这在小团队还能忍在业务方多、发布频率高的环境里就成了日常摩擦点。1.2 多页应用到底改变了什么多页应用MPA的核心差异是每一个页面都有自己独立的 HTML 文件、独立的 JS 入口和独立的构建产物。你在浏览器里访问 /home.html 和 /activity.html其实是两个完全独立的文档页面之间跳转是真正的浏览器导航不是前端路由切换。改成多页之后最直接的好处有三个每个页面按自己的依赖打包活动页可以做到非常轻量不用背上主应用的整套代码。每个页面可以独立发布、独立回滚。活动页出了线上问题单独回滚它的版本就行不影响主应用。如果某些页面面向不同用户群体比如 C 端落地页和 B 端管理后台它们的构建产物、部署位置甚至服务器配置都可以完全独立。1.3 判断你的项目该不该改不是所有单页项目都需要改成多页。我见过有人说多页架构性能好所以我要改但改了之后发现组件复用、状态管理、跳转动画都变麻烦了得不偿失。我的判断标准很简单你对照看一下场景特征建议页面之间跳转频繁需要保持组件状态不丢失维持单页不要改多页有独立的活动页/落地页要求首屏极快拆成多页页面独立构建不同模块由不同团队维护发布频率差异大拆成多页各自独立发布后台管理系统功能集中、长期在线单页更合适多页反而增加成本需要和现有服务端模板比如某些后端渲染框架集成多页是刚需不用犹豫我自己这次改造属于第四种场景之外的混合需求核心应用保留单页新增的活动页和独立登录页走多页。这种局部改造的路径比全量推翻重构要稳妥得多也是大部分项目最实际的切法。2. 改造前的准备盘点现状与规划目录结构2.1 先把自己的项目摸透动手改配置之前我强烈建议先花十分钟盘点一下原项目的现状。这个动作能帮你少走很多弯路。我在实际操作中主要看这么几项第一路由结构是什么样。原项目的路由模式是 history 还是 hash路由表有多少个页面哪些页面以后需要拆成独立入口。这个信息直接决定了后续路由层的处理方式我这次就是没提前注意这点后面在部署环节被坑了一道第 2 章会详细说。第二公共依赖有哪些。项目里用了哪些全局插件、状态管理库、UI 组件库、请求封装。改多页后这些公共资源要么打包成公共 chunk要么通过模块导入不能让每个页面都把整套代码重复打包一遍。第三环境变量怎么用。Vite 默认的 .env 文件是全局的多页模式下每个页面可能还需要不同的环境变量得提前想好归类。我建议用 import.meta.env 做页面级别的区分判断而不是改多个 .env 文件后面维护起来省心。2.2 目录结构规划单页为主、多页并存多页改造不一定非要把所有页面都变成独立入口。以我这次的经验来说最舒服的目录结构是主应用保持原样 新增 pages 目录放独立入口。改造后的目录结构大致长这样project ├── index.html # 主应用入口保持原样 ├── package.json ├── vite.config.js ├── .env # 公共环境变量 ├── src │ ├── main.js # 主应用 JS 入口 │ ├── App.vue │ ├── router │ │ └── index.js │ ├── components # 公共组件目录 │ │ ├── BaseButton.vue │ │ └── LoadingSpinner.vue │ ├── store │ │ └── index.js │ ├── api │ │ └── request.js │ └── pages # 独立多页目录改造新增 │ ├── activity │ │ ├── index.html │ │ ├── main.js │ │ └── App.vue │ └── login │ ├── index.html │ ├── main.js │ └── App.vue └── dist # 构建产物目录这个结构的好处是主应用代码一行不用动新增页面全部放在 pages 里每个子目录是一个自包含的 Vue 应用。想加新页面就复制一个目录改改配置想下线某个页面就把它从构建输入里删掉互不干扰。2.3 有一个容易忽略的决策页面入口 HTML 放哪里多页入口的 HTML 文件放哪里是一个很少有人讲但很重要的问题。Vite 的构建是以 HTML 文件为起点扫描依赖的这些 HTML 文件的位置会影响两个地方一是开发环境访问路径二是构建产物的输出目录。我尝试过两种放法第一种是把所有入口 HTML 放在项目根目录下和主应用的 index.html 平级。这样开发环境访问路径最干净比如访问 /activity.html 就能打开活动页。但项目根目录会越来越乱页面多了根本分不清哪个 HTML 是哪个页面的。第二种是每个页面目录里放自己的 index.html也就是上面目录结构那种写法。这样做的好处是页面归属清晰、方便维护但访问路径会变成 /pages/activity/index.html开发环境下路径比较长。我个人更推荐第二种因为项目长期维护的优先级高于那一点点路径的简洁性。如果你想缩短访问路径后面可以通过配置 base 或者部署层的 URL 重写来解决但不建议为了路径好看看牺牲目录的组织性。我在实际项目中用的就是第二种方案。并且在这里提醒一句pages 目录下的 HTML 要和主入口 index.html 区分开不要也叫 index.html 放在根目录那样 Vite 会直接混淆入口。3. 核心操作Vite 多页配置的落地步骤3.1 创建每个页面的 HTML 模板和 JS 入口多页应用最底层就是每个页面有一个 HTML 文件里面通过 script 标签引入自己的 JS 入口。这个入口 JS 负责创建 Vue 应用实例。以活动页为例pages/activity/index.html 内容大概是!DOCTYPE html html langzh-CN head meta charsetUTF-8 / meta nameviewport contentwidthdevice-width, initial-scale1.0 / title活动中心/title /head body div idapp/div script typemodule src./main.js/script /body /html重点看 script 那行src 指向的是相对于当前 HTML 文件的 ./main.js。这里绝对不能用 别名去写路径因为 HTML 文件的资源解析规则和 JS 里的 import 语法不一样Vite 虽然能在构建时处理一部分但写成相对路径最稳妥开发环境和构建环境都不会出错。这一点我后面会在构建产物路径那里细说。对应的 pages/activity/main.js 内容也很简单就是一个标准的 Vue 应用挂载过程import { createApp } from vue import App from ./App.vue createApp(App).mount(#app)如果你的多页页面还需要用路由、状态管理等插件就在这个入口里按需引入。每个页面入口都是独立的模块加载起点用不到的东西不去 import构建的时候自然就不会被打进包里。3.2 修改 vite.config.js配置多入口这一步是整个改造的心脏。Vite 底层的构建能力由 Rollup 提供我们只需要通过 build.rollupOptions.input 告诉它这个项目不止一个入口。示例配置如下import { defineConfig } from vite import vue from vitejs/plugin-vue import { resolve } from path export default defineConfig({ plugins: [vue()], resolve: { alias: { : resolve(__dirname, src) } }, build: { rollupOptions: { input: { main: resolve(__dirname, index.html), activity: resolve(__dirname, src/pages/activity/index.html), login: resolve(__dirname, src/pages/login/index.html) } } } })input 对象里的 keymain、activity、login会直接决定构建产物的 HTML 文件名所以命名要语义化一点。比如 activity 对应的产物就是 dist/activity.htmllogin 对应的就是 dist/login.html主应用则是 dist/index.html。这里有一个细节值得说一下如果你不配置 rollupOptions.inputVite 默认会把根目录下的 index.html 当作唯一入口。一旦你配置了多入口原来那个默认行为就失效了所以主应用的 index.html 也要明确写进 input 里否则主应用会直接消失。这是我当时犯的第二个低级错误差点把主应用搞没了。3.3 开发环境怎么访问多页面配置完成后启动 vite 开发服务默认访问 http://localhost:5173/ 还是主应用。要访问活动页URL 就是 http://localhost:5173/src/pages/activity/index.html。有同学可能觉得这个路径很长、不好记问能不能改成访问 /activity.html 就直接进活动页。可以把 HTML 文件放到项目根目录并命名为 activity.html然后修改 input 指向根目录文件就行。但我前面说过这个代价是根目录文件变乱长期维护不划算。如果只是在开发阶段想缩短路径还有另一种方式配置 vite 的 server 中间件把 /activity 请求重写到 /src/pages/activity/index.html。不过我个人不太推荐为了开发体验加这套额外逻辑毕竟真正部署上线后路径是部署层决定的开发环境那一点点不顺畅其实可以克服。3.4 第一次看构建产物时要注意什么配置改完可以先跑一次 npm run build 看看产出。正常的产物结构应该是dist ├── index.html ├── activity.html ├── login.html └── assets ├── index-[hash].js ├── activity-[hash].js ├── login-[hash].js └── vendor-[hash].js这时候你一眼就能看出一个问题活动页的 HTML 里引用的 JS 路径是什么形式。Vite 默认资源路径是绝对路径也就是 /assets/activity-xxx.js。如果你部署的时候应用不是放在域名根路径下而是放在某个子目录比如 /web/那这些绝对路径就会全部 404。解决方法是给 Vite 配一个 base。基础配置用相对路径的方式最省心export default defineConfig({ base: ./ // 其余配置不变 })base 设为 ./ 后构建产物的 HTML 里引用的资源路径会变成相对路径这样不管应用部署在根路径还是子目录资源都能正确加载。这个配置其实在单页应用里也建议开启但多页应用下如果不配会更容易翻车因为多个页面文件分布在不同的层级路径中路径问题会被放大。4. 路由与组件复用多页模式下的架构调整4.1 多页模式下的路由不简单把项目改成多页之后最容易出问题的不是构建配置而是路由模式。路由模式这件事如果不提前想清楚线上部署让你当场血压拉满。单页应用里的路由一般是 Vue Router 的 history 模式URL 形如 /home、/detail/123看起来很干净。这种模式下前端路由完全由浏览器端处理你访问 /detail/123 时实际上加载的还是 index.html 这个唯一入口然后 JS 内部去匹配路由。但是在多页应用里每个页面都是一个真实的 HTML 文件。如果活动页的部署路径是服务器上的一个普通文件而你的某个页面同时又想用 history 模式的路由就会出现一个尴尬情况页面内跳转没问题但用户刷新一下 /detail/123 这个路径服务器找不到对应的 HTML 文件直接 404。解决思路分两种第一种多页面内部尽量用 hash 模式路由URL 带 #。刷新时 hash 部分不会发给服务器只加载当前页面的 HTML绝对安全。代价是 URL 不够优雅。第二种服务器配置 rewrite 规则把所有路径重写到对应页面的 HTML。比如location /activity/ { try_files $uri $uri/ /activity.html; }这种方式更专业但需要你能够修改部署服务器的配置。如果部署环境是纯静态托管没有自定义改写能力那就只能老老实实退回 hash 路由。我的最终选择是主应用保留 history 模式独立的多页页面统一用 hash 模式。这样开发量最小线上又稳只是 URL 里多一个 # 号业务方可以接受。4.2 公共组件和 UI 库的复用方式改成多页后每个页面是独立应用组件不能像单页那样天然全局注册。比如原来在 main.js 里import BaseButton from ./components/BaseButton.vue app.component(BaseButton, BaseButton)改多页之后这个全局注册只对当前应用的实例生效。activity 页面的应用实例跑了另一套不会自动拿到这些全局组件。我在这次改造中的处理方式是把公共组件全部放在 src/components 目录每个多页入口根据自己的需要显式 import。类似import BaseButton from /components/BaseButton.vue然后页面组件里直接用或者把高频组件统一封装成一个公共插件文件在多个入口里复用同一个插件模块。封装公共插件的好处是不用每个文件写一堆 import。例如创建一个 src/common/index.jsimport BaseButton from /components/BaseButton.vue import LoadingSpinner from /components/LoadingSpinner.vue export default { install(app) { app.component(BaseButton, BaseButton) app.component(LoadingSpinner, LoadingSpinner) } }然后在 activity/main.js 里import { createApp } from vue import App from ./App.vue import common from /common createApp(App).use(common).mount(#app)多个页面入口都只需要两行代码就能获得一致的公共组件和全局配置。这个模式我用下来相当顺既避免了重复 import又不会让每个页面打包进用不到的组件。说起来这里有个打包层面的好处由于每个入口只是 import 自己用到的公共组件Vite/Rollup 在打包时会做 tree-shaking那些没被引用的组件不会进入这个页面的 chunk活动页可以做到非常轻。4.3 多页之间状态共享别指望 Pinia 全局互通单页应用里Pinia 的 store 可以在任意组件之间共享数据因为整个应用只有一个 JS 运行时store 实例是全局唯一的。但多页应用是多个独立 JS 实例A 页面里的 Pinia store 数据B 页面是拿不到的。我在初期改造时曾经天真地想在主应用登录后直接把 token 传给活动页的 store结果活动页一刷新数据就没了。实际业务中多页之间的共享需求主要就是两类登录状态和一些用户偏好设置。我的建议是持久化数据用 localStorage 或 sessionStorage。页面之间的通信可以用 storage 事件监听或者 URL 参数传值。不要试图跨页面操作对方的 Pinia store这种架构注定维持不住。具体到代码在活动页初始化时从 localStorage 读取登录态的示例// activity/main.js import { createApp } from vue import App from ./App.vue const token localStorage.getItem(token) const userInfo JSON.parse(localStorage.getItem(userInfo) || {}) // 把初始化数据作为 props 或者注入到全局属性里 createApp(App, { token, userInfo }).mount(#app)这样多页页面之间虽然 runtime 隔离但业务数据通过浏览器本地存储做通路实际用下来稳定性还不错。4.4 请求层和拦截器怎么统一如果你的项目里有一个全局的 axios 实例里面设置了请求拦截器、响应拦截器、错误处理、token 注入逻辑你肯定不希望每个页面入口都复制一份。把这个 axios 实例抽成一个独立的模块放在 src/api/request.js每个页面入口 import 同一个实例。这样公共的拦截逻辑集中管理各个页面的 API 调用保持一致的错误处理行为。一个小提示axios 实例本身是无状态工具可以被多个入口共享不涉及跨页面状态问题所以放心复用。这也算是多页改造里最省心的部分。5. 构建产物分析与性能优化5.1 构建产物结构检查改造完成后构建产物肯定比之前复杂。我发现很多人改完多页就直接上线了从不看 dist 里到底输出什么文件这是很大的隐患。改造后的产物应该是这样的典型结构dist ├── index.html ├── activity.html ├── login.html └── assets ├── index-3f2b9c1e.js ├── activity-8a1d4f2b.js ├── login-c9b2a8d3.js ├── vendor-vue-7d1e2a4c.js └── vendor-axios-2b1a9f3e.js我检查产物主要看三点第一每个页面的入口 JS 大小是否符合预期。活动页应该是很小的如果活动页入口 JS 超过 200KB说明公共代码抽离做得不够活动页把不需要的主应用代码打包进来了。第二页面的 HTML 引用路径是否正常。打开 dist/activity.html看 script 和 link 标签的 src/href 是绝对路径还是相对路径。如果出现了 /assets/xxx.js 这种写法但你的部署环境是子路径部署就要调整 base 配置。第三有没有重复的公共代码。比如两个页面各自的 chunk 里都包含了一份 vue-router 的源码说明你没有配置好公共依赖抽离这会让总体积明显变大。5.2 手动分包把公共依赖单独抽出来Vite 默认情况下会把一些公共模块提取成共享 chunk但不会精细控制。如果你希望更确定性地控制分包策略可以在 rollupOptions.output 里配置 manualChunks。我这次改造后做了一次手动分包把大厂公共依赖单独拆出来让浏览器能够更好地利用缓存Vue 全家桶长期不变拆分后再发布只改业务代码用户的缓存命中率会明显提高。配置参考import { defineConfig } from vite import vue from vitejs/plugin-vue import { resolve } from path export default defineConfig({ plugins: [vue()], base: ./, resolve: { alias: { : resolve(__dirname, src) } }, build: { rollupOptions: { input: { main: resolve(__dirname, index.html), activity: resolve(__dirname, src/pages/activity/index.html), login: resolve(__dirname, src/pages/login/index.html) }, output: { manualChunks: { vendor-vue: [vue, vue-router, pinia], vendor-axios: [axios] } } } } })配完 manualChunks 后有一个注意点如果两个入口页面同时依赖了 vue 和 axios这些公共依赖会被打包进 vendor-vue 和 vendor-axios 里入口 JS 会明显变小。如果你某个页面根本没用 axios那 vendor-axios 这个 chunk 不会生成。Rollup 的 tree-shaking 在分包之后仍然生效只有被引用到的模块才会真正输出。5.3 页面内部按需加载异步组件即使是多页页面内部也可能有大组件不急着加载的场景。比如活动页有一个数据大屏组件用了重型的图表库你不希望它拖慢首屏。在 Vue 3 里用 defineAsyncComponent 做异步组件import { defineAsyncComponent } from vue const BigChart defineAsyncComponent(() import(./components/BigChart.vue))这样 BigChart 会被单独拆成一个异步 chunk只有真正渲染到这个组件时才会去加载。多页模式下这个能力依然有效而且效果更明显因为活动页首屏资源本身就很轻多加一个异步组件也不会打乱构建结构。老规矩异步组件记得配置一个加载态不然用户等的时候页面空白体验很差。5.4 hash 策略统一使用 contenthash 提高缓存利用率Vite 默认会自动给构建产物加 hash但多页模式下你可以更细致地控制 hash 策略。我建议构建输出的文件名统一用内容 hash 模式也就是文件内容发生变化时 hash 才变。这样部署新版本时那些没改动的公共 chunk比如 vendor-vue文件名保持不变浏览器会继续使用本地缓存的旧文件不用重新下载。Vite 默认的行为其实就是内容 hash但如果你手动改了 assetsDir 或者自己写了输出文件名规则要小心别破坏了这一点。一般情况不用特别配置但最好检查一下产物的文件名 hash 是否在每次内容没变时保持稳定。6. 实操中遇到的典型问题与排查方案6.1 静态资源路径全部 404这个问题我第一次跑构建产物时就遇到了。部署到测试服务器的子目录后打开页面发现 JS、CSS 全部加载失败控制台报一堆 404。排查路径打开产物 HTML 看资源引用路径发现是绝对路径 /assets/xxx.js。这就是因为 base 没配。解决方案把 vite.config.js 里加上base: ./重新构建。改成相对路径后HTML 里的 script 和 link 路径自动变为相对路径部署到任意子目录都能找到资源。如果项目部署在 CDN 或独立域名根路径那是可以保持绝对路径的但相对路径显然是更通用的选择。建议从一开始就配好省得后面改来改去踩坑。6.2 页面刷新直接 404这个问题主要出在多页页面使用 history 路由时。用户在活动页内跳到了一个子路由比如 /activity/detail然后按了 F5 刷新服务器在 /activity/detail 路径下找不到对应的 HTML 文件于是返回 404。排查思路确认当前多页页面用的路由模式如果是 createWebHistory就要看部署层能做什么。解决方案有两个层次简单方案把多页页面内部的路由改成 createWebHashHistory刷新永远只访问 /activity.html不存在 404。复杂方案在 nginx 或者服务器中间件里加 rewrite 规则把 /activity/* 全部重写到 /activity.html。如果你能改 nginx 配置rewrite 是最干净的方案如果不能就老老实实 hash 模式。没有第三个完美方案不用纠结。6.3 开发环境访问多页面入口时出现无法加载模块的错误启动 vite 后访问 /src/pages/activity/index.html页面空白控制台报Failed to resolve import ./main.js这种情况通常是因为开发环境访问路径与实际文件路径不匹配。Vite 开发服务器对根目录有映射关系如果页面里的 script 路径写法和实际文件位置对不上就会出现模块解析失败。我排查后发现是因为 HTML 里写了相对路径 ./main.js但当前目录的实际情况不是预期的那个目录。解决办法就是把 script src 精确写成相对于当前 HTML 的路径比如 ./main.js 或者 ./main.js只要与实际文件结构对齐就没问题。注意不要用 别名去写 HTML 里的路径模块系统不会在 HTML 的 src 属性里展开别名。6.4 打包后两个页面各自打包了一份 Vue一个让我非常郁闷的问题是构建产物里每个页面的 JS 体积都很大。打开 dist/assets 一看每个页面的 chunk 都包含了一份完整 vue 运行时公共代码根本没有抽出来。排查过程我的 manualChunks 配置只写了 [vue, vue-router, pinia]但构建产物里这些公共依赖还是重复了。后来检查发现是配置里的 manualChunks 写错了位置把它放进了 build.rollupOptions而不是 output 下面。Rollup 的 manualChunks 必须放在 output 里才生效。另外还有一个坑如果某个页面根本没有引入 vue-router那 vendor-vue 里包含 vue-router 会导致公共 chunk 被这个页面加载但实际上完全可以不加载。这个问题的解法就是根据页面实际依赖来配置 manualChunks不要一股脑把全家桶塞进同一个 chunk。我最后把 vue-router 单独拆到了另一个 chunk才解决了页面加载不必要代码的问题。6.5 多页页面之间跳转页面刷新后状态丢失这是个业务层面的问题。活动页跳回主应用后再返回活动页发现活动页的状态被重置了用户之前填的表单数据没了。这个问题没有通用解法得根据数据保留需求去设计。我的方案是需要保留的表单数据在每次变化时同步写入 sessionStorage页面重新加载时从 sessionStorage 恢复。这个方案能覆盖大部分返回后别丢数据的场景。如果临时性的方案就是前端缓存数据敏感性要求不高的时候没问题。如果表单提交本身就很关键而且用户可能隔很长时间才回来那建议走服务端草稿保存前端只做恢复提示。6.6 常见问题排查速查表现象大概率原因解决措施构建后资源 404base 未配置或配置错误设置 base: ./刷新页面 404history 路由无 rewrite改 hash 路由或配置 rewrite页面 JS 体积异常大公共依赖重复打包配置 manualChunks开发环境部分页面打不开入口 HTML 路径写错检查 script src 相对路径多页间数据不同步store 全局不互通用 localStorage/sessionStorage组件样式在页面间重复加载公共样式被重复打包提取公共 chunk 或公共 CSS7. 我的改造心得与建议整个改造过程做完我最大的感受是vue3vite单页面改多页面技术实现本身不难难的是在改造前把哪些页面要拆、拆了之后路由怎么处理、公共代码怎么复用这些问题想清楚。如果一开始就有全局规划后面每一步都是很顺的配置工作如果边做边想那你就会像我一样反复在构建产物里发现问题来回改配置。有几个经验我想单独拿出来说。第一个是改造顺序。千万别一上来就动 vite.config.js。先把多页页面目录建好把 HTML、main.js、App.vue 都放好跑通一个最简单的多页入口确认开发环境能访问再改生产环境的构建配置。小步快跑每次只验证一个环节出问题时定位会快得多。第二个是公共代码抽离要适度。我一开始想追求极致把很多公共库包括一些比较大的工具库全部手动分包结果构建产物确实变小了但部署后因为公共 chunk 分散太多HTTPS 请求数暴增反而影响了加载速度。后来折中了一下只把 Vue 全家桶和 axios 这种核心库单独拆出来其他零散公共代码交给 Vite 自动分包机制处理。性能和可维护性之间要找到平衡点不要追求极致的理想分包。第三个是部署层的配合。多页应用上线前一定要和负责部署的同事确认好 rewrite 规则和静态资源缓存策略。如果你们的静态托管平台不支持自定义 rewrite那 hash 路由就是唯一选择。先确认部署能力再定技术方案顺序不能颠倒否则技术方案做得再漂亮部署环节落地不了一切白搭。第四个是别忽略构建产物的检查。每次改完配置都手动看一眼 dist 里生成的文件文件数量、各页面入口大小、公共 chunk 是否合理。这个习惯能帮你在上线前拦截大量问题而不是等用户反馈页面打不开了才开始排查。这次改造算是一次很典型的工程实践需求驱动架构调整小步迭代稳步上线。如果你也正在做类似的事情希望这份记录能帮你少踩几个坑。如果改造项目里有更特殊的场景比如页面数量特别多、要动态生成路由入口后续我再单独写一篇聊。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑