| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- import path from 'node:path'
- import { defineConfig, loadEnv } from 'vite'
- import detectPort from 'detect-port'
- import vue from '@vitejs/plugin-vue'
- import vueJsx from '@vitejs/plugin-vue-jsx'
- import AutoImport from 'unplugin-auto-import/vite'
- import Components from 'unplugin-vue-components/vite'
- import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
- import { createStyleImportPlugin, VxeTableResolve } from 'vite-plugin-style-import'
- import Unocss from 'unocss/vite'
- import { lazyImport, VxeResolver } from 'vite-plugin-lazy-import'
- import { createProjectShellAliases, resolveProjectShellComponentsDir } from './vite.shell-aliases'
- const DEFAULT_BACKEND_TARGET = 'http://127.0.0.1:8086'
- /**
- * Docker 开发会把 VITE_BASE_PATH 设为 host.docker.internal;若宿主机直接 pnpm dev 仍残留
- * .env.development.local,代理会连不上并导致登录页「服务器错误」。非 Docker 时自动回退本机地址。
- */
- function resolveViteBackendTarget(rawTarget: string | undefined): string {
- const target = (rawTarget || DEFAULT_BACKEND_TARGET).trim()
- const isDockerDev = process.env.DOCKER_DEV === '1' || process.env.DOCKER_DEV === 'true'
- if (!isDockerDev && target.includes('host.docker.internal')) {
- console.warn(
- `[vite] VITE_BASE_PATH=${target} 仅适用于 Docker 容器内;已回退代理至 ${DEFAULT_BACKEND_TARGET}`
- )
- return DEFAULT_BACKEND_TARGET
- }
- return target
- }
- export default defineConfig(async ({ mode }) => {
- const DEFAULT_PORT = 9012
- const env = loadEnv(mode, process.cwd(), '')
- const backendTarget = resolveViteBackendTarget(env.VITE_BASE_PATH)
- const port = await detectPort(DEFAULT_PORT)
- const shellComponentsDir = resolveProjectShellComponentsDir()
- const shellSrc = path.join(process.cwd(), 'node_modules/@fskj-admin/shell/src')
- const shellSrcPattern = new RegExp(shellSrc.replace(/[\\/]/g, '[\\\\/]'))
- return {
- base: '/',
- define: {
- 'import.meta.env.VITE_BASE_PATH': JSON.stringify(backendTarget)
- },
- plugins: [
- vue(),
- vueJsx(),
- Unocss(),
- AutoImport({
- imports: ['vue', 'vue-router', 'pinia', '@vueuse/core'],
- dts: 'src/auto-import.d.ts',
- // shell 与业务仓 SFC 均依赖 auto-import(ref/computed 等);须覆盖 alias 解析后的 shell 绝对路径
- include: [
- shellSrcPattern,
- /[\\/]node_modules[\\/]@fskj-admin[\\/]shell[\\/]/,
- /[\\/]src[\\/]/,
- /\.vue$/,
- /\.vue\?vue/,
- /\.vue\?vue&type=script/
- ],
- // 默认 exclude 含 /node_modules/,会跳过 npm 内 @fskj-admin/shell,导致 BasicLayout 等 computed 未注入
- exclude: [
- /[\\/]node_modules[\\/](?!.*@fskj-admin[\\/]shell[\\/])/,
- /[\\/]\.git[\\/]/
- ],
- viteOptimizeDeps: true
- }),
- Components({
- dirs: ['src/components', shellComponentsDir],
- extensions: ['vue'],
- dts: 'src/components.d.ts',
- // 与 AutoImport 一致:须处理 npm 内 @fskj-admin/shell 的 SFC,否则 platformops 等页
- // 使用的 BasicLeftTree / ProTable 等壳组件无法自动注入(Failed to resolve component)
- include: [
- shellSrcPattern,
- /[\\/]node_modules[\\/]@fskj-admin[\\/]shell[\\/]/,
- /[\\/]src[\\/]/,
- /\.vue$/,
- /\.vue\?vue/,
- /\.vue\?vue&type=script/
- ],
- exclude: [
- /[\\/]node_modules[\\/](?!.*@fskj-admin[\\/]shell[\\/])/,
- /[\\/]\.git[\\/]/
- ]
- }),
- createSvgIconsPlugin({
- iconDirs: [path.resolve(process.cwd(), 'src/assets/svg')],
- symbolId: 'icon-[dir]-[name]'
- }),
- createStyleImportPlugin({
- resolves: [VxeTableResolve()]
- }),
- lazyImport({
- resolvers: [
- VxeResolver({ libraryName: 'vxe-table' }),
- VxeResolver({ libraryName: 'vxe-pc-ui' })
- ]
- })
- ],
- css: {
- preprocessorOptions: {
- scss: {
- silenceDeprecations: ['legacy-js-api']
- }
- }
- },
- resolve: {
- alias: [
- {
- find: '@/components/form/ElImageUploadOne.vue',
- replacement: path.resolve(process.cwd(), 'src/components/form/ElImageUploadOne.vue')
- },
- {
- find: '@/components/form/ElImageUploadMore.vue',
- replacement: path.resolve(process.cwd(), 'src/components/form/ElImageUploadMore.vue')
- },
- {
- find: '@/components/form/ImageUploadTip.vue',
- replacement: path.resolve(process.cwd(), 'src/components/form/ImageUploadTip.vue')
- },
- {
- find: '@/components/form/ElEditor.vue',
- replacement: path.resolve(process.cwd(), 'src/components/form/ElEditor.vue')
- },
- {
- find: '@/components/layout/GlobalMainNav.vue',
- replacement: path.resolve(process.cwd(), 'src/components/layout/GlobalMainNav.vue')
- },
- {
- find: '@/utils/formatMainNavLabel',
- replacement: path.resolve(process.cwd(), 'src/utils/formatMainNavLabel.ts')
- },
- // pnpm + shell 源码直引时 dedupe 可能失效,须强制单例 pinia/vue-router
- {
- find: 'pinia',
- replacement: path.resolve(process.cwd(), 'node_modules/pinia/dist/pinia.mjs')
- },
- {
- find: 'vue-router',
- replacement: path.resolve(process.cwd(), 'node_modules/vue-router/dist/vue-router.mjs')
- },
- // xe-utils 当前安装版本无 es 构建,改走 dist UMD 构建
- {
- find: 'xe-utils',
- replacement: path.resolve(process.cwd(), 'node_modules/xe-utils/dist/xe-utils.umd.js')
- },
- // dayjs 主入口为 UMD(dayjs.min.js),element-plus ESM 需 default 导出
- {
- find: /^dayjs\/plugin\/(.+)\.js$/,
- replacement: path.resolve(process.cwd(), 'node_modules/dayjs/esm/plugin/$1/index.js')
- },
- {
- find: /^dayjs$/,
- replacement: path.resolve(process.cwd(), 'node_modules/dayjs/esm/index.js')
- },
- ...createProjectShellAliases()
- ],
- // monorepo + pnpm 下避免 pinia/vue 多实例,否则 getActivePinia() 报错
- dedupe: ['pinia', 'vue', 'vue-router', '@vue/runtime-core']
- },
- optimizeDeps: {
- exclude: [
- '@fskj-admin/shell',
- '@shell/router/appRouterHolder',
- '@shell/router/createAppRouter',
- '@shell/router/businessRouterExtension',
- '@shell/home/homeExtension',
- '@shell/bootstrap/createAdminApp',
- '@shell/router/platformOpsRouterExtension',
- '@shell/platformops/register',
- '@shell/platformops/essentialRoutes',
- '@shell/stores/user',
- '@shell/stores/router',
- '@shell/stores/menu',
- '@shell/stores/theme',
- '@shell/stores/permission',
- '@/stores/user',
- '@/stores/permission',
- '@shell/utils/utils'
- ],
- // shell 被 exclude 后其 CJS 依赖须单独预打包;与框架仓对齐,避免 dev 首次点「菜单配置」触发 optimized dependencies changed 整页刷新
- entries: [
- './index.html',
- './src/main.ts',
- './node_modules/@fskj-admin/shell/src/platformops/views/subsystem/index.vue',
- './node_modules/@fskj-admin/shell/src/platformops/views/subsystem/subsystemMenu.vue'
- ],
- include: [
- 'pinia',
- 'vue',
- 'vue-router',
- 'xe-utils',
- 'nprogress',
- 'lodash',
- 'jsencrypt',
- 'echarts',
- 'vue-cropper',
- 'splitpanes',
- '@element-plus/icons-vue',
- 'element-plus',
- 'vxe-table',
- 'vxe-pc-ui',
- '@vxe-ui/plugin-render-element'
- ],
- needsInterop: ['xe-utils', 'nprogress', 'lodash']
- },
- server: {
- host: '0.0.0.0',
- port,
- open: '/#/login',
- // dev 启动时预热应用维护/菜单配置相关 shell 页面,减少首次点击菜单配置时的依赖发现与 reload
- warmup: {
- clientFiles: [
- './src/main.ts',
- './node_modules/@fskj-admin/shell/src/platformops/views/subsystem/index.vue',
- './node_modules/@fskj-admin/shell/src/platformops/views/subsystem/subsystemMenu.vue',
- './node_modules/@fskj-admin/shell/src/platformops/views/subsystem/components/menuButton.vue',
- './node_modules/@fskj-admin/shell/src/platformops/views/subsystem/components/menuList.vue',
- './node_modules/@fskj-admin/shell/src/platformops/views/subsystem/components/menuForm.vue',
- './node_modules/@fskj-admin/shell/src/platformops/views/subsystem/components/menuPermission.vue'
- ]
- },
- proxy: {
- [env.VITE_BASE_API]: {
- target: backendTarget,
- changeOrigin: true
- // 勿 strip /admin:后端 jeesharp.web.adminPath=/admin,登录等白名单为 /admin/login
- }
- }
- },
- build: {
- chunkSizeWarningLimit: 1500
- }
- }
- })
|