import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import legacy from '@vitejs/plugin-legacy' import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { NaiveUiResolver } from 'unplugin-vue-components/resolvers' // 机房电脑的 Chrome 是 105 一档,比 plugin-legacy 的现代基线(chrome>=105)正好压线, // 但比 vite 8 的默认构建 target(chrome111)低。所以这个插件必须留着:它同时管两件事 // —— 把 build.target 压到 chrome105/es2020,再给现代产物补 core-js 的 API polyfill。 // // 下面这份清单是 `modernPolyfills: true` 自动探测出来的 49 项,抄下来写死:自动探测要 // 对每个产物跑一遍 Babel 扫描,构建从 3 秒涨到 12 秒。**升级前端依赖后重新审计一次**: // 临时把下面的 modernPolyfills 改成 true,再 DEBUG=vite:legacy bun run build // (写死清单时它只回显这份清单,不会重新探测) // 少一项就是老机器上一个静默的 TypeError(这批缺的大多是 Chrome 110+ 的 // Array.prototype.toSorted / Set 运算 / 迭代器辅助)。 const polyfills = [ 'es.array-buffer.detached', 'es.array-buffer.transfer', 'es.array-buffer.transfer-to-fixed-length', 'es.array.includes', 'es.array.push', 'es.array.to-reversed', 'es.array.to-sorted', 'es.array.to-spliced', 'es.iterator.constructor', 'es.iterator.drop', 'es.iterator.every', 'es.iterator.filter', 'es.iterator.find', 'es.iterator.flat-map', 'es.iterator.for-each', 'es.iterator.map', 'es.iterator.reduce', 'es.iterator.some', 'es.iterator.take', 'es.iterator.to-array', 'es.json.parse', 'es.json.stringify', 'es.map.get-or-insert', 'es.map.get-or-insert-computed', 'es.regexp.escape', 'es.regexp.flags', 'es.set.difference.v2', 'es.set.intersection.v2', 'es.set.is-disjoint-from.v2', 'es.set.is-subset-of.v2', 'es.set.is-superset-of.v2', 'es.set.symmetric-difference.v2', 'es.set.union.v2', 'es.typed-array.to-reversed', 'es.typed-array.to-sorted', 'es.typed-array.with', 'es.uint8-array.set-from-base64', 'es.uint8-array.set-from-hex', 'es.uint8-array.to-base64', 'es.uint8-array.to-hex', 'es.weak-map.get-or-insert', 'es.weak-map.get-or-insert-computed', 'esnext.array.group', 'web.dom-exception.stack', 'web.url-search-params.delete', 'web.url-search-params.has', 'web.url-search-params.size', 'web.url.can-parse', 'web.url.parse', ] export default defineConfig(() => { // 开发时一律指向本机后端(apps/api,3000)。 // **必须写 IP,不能写 localhost**:api 用 Bun.serve 起,只绑 IPv4 的 // 0.0.0.0:3000,而 Node 解析 localhost 时 ::1 排在前面。别的项目的 dev server // 一旦占着 [::1]:3000,两边端口不冲突(一个 v4 一个 v6,谁都不报错), // 浏览器发出的 /api/* 就整个落到那个站上 —— 表现是后台一进就被弹回首页。 const backend = { target: 'http://127.0.0.1:3000', changeOrigin: true, } return { plugins: [ vue(), // 不做 SystemJS 双构建,只给现代产物注入 polyfill;modernTargets 不写, // 用插件自带的基线(chrome>=105 / firefox>=106 / safari>=16.4),正好是机房那档。 legacy({ renderLegacyChunks: false, modernPolyfills: polyfills, }), AutoImport({ imports: [ 'vue', 'vue-router', '@vueuse/core', 'pinia', { 'naive-ui': ['useDialog', 'useMessage', 'useNotification', 'useLoadingBar'], }, { from: 'naive-ui', imports: [ 'DataTableColumn', 'FormRules', 'FormItemRule', 'SelectOption', 'UploadCustomRequestOptions', 'UploadFileInfo', 'MenuOption', 'DropdownDividerOption', 'DropdownOption', ], type: true, }, ], dts: './src/auto-imports.d.ts', }), Components({ resolvers: [NaiveUiResolver()], dts: './src/components.d.ts', }), ], envPrefix: 'PUBLIC_', resolve: { // 别名(utils / oj / admin / shared)只在 tsconfig.app.json 的 paths 写一份, // 这里直接读它。tsconfig.json 是 references 空壳也没关系,会顺着找过去(实测) tsconfigPaths: true, }, server: { port: 5173, proxy: { // 只有这三段过后端,和生产的 Caddy 认的是同一套(docker/Caddyfile), // 别在这里加代理规则而不同步改 Caddyfile。 '/api': backend, '/public': backend, '/ws': { ...backend, ws: true }, }, }, } })