Files
oa-vue/vite.config.ts
赵忠林 a540b1fcb0 feat(house): 添加房源类型筛选功能
- 在 houseInfo 组件中新增 type 参数用于筛选房源类型
- 更新 houseInfoEdit 组件以支持传递和显示房源类型
- 修改接口模型增加 type 字段定义
- 调整页面布局及样式以适应新字段展示需求
- 配置开发环境 API 地址并更新相关组件请求路径
- 引入路由监听实现动态类型查询
- 优化表格行键值确保唯一性
- 更新系统设置中微信相关的域名配置为本地地址
- 修改文件上传接口地址为本地服务
- 调整项目库组件中的 ID 键名以匹配后端返回结构
- 移除冗余的表单字段声明提升代码整洁度
- 更新
2025-12-10 16:40:59 +08:00

230 lines
6.8 KiB
TypeScript

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import ViteCompression from 'vite-plugin-compression';
import ViteComponents from 'unplugin-vue-components/vite';
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers';
import { EleAdminResolver } from 'ele-admin-pro/lib/utils/resolvers';
import { DynamicAntdLess } from 'ele-admin-pro/lib/utils/dynamic-theme';
import { resolve } from 'path';
import { visualizer } from 'rollup-plugin-visualizer';
import { splitVendorChunkPlugin } from 'vite';
// 简化的智能端口管理(避免构建时模块解析问题)
function getSmartPort() {
try {
// 从环境变量获取基础配置
const basePort = parseInt(process.env.VITE_BASE_PORT || '3000');
const tenantId = process.env.VITE_TENANT_ID || '10411';
const environment = process.env.NODE_ENV || 'development';
// 简化的端口计算
let recommendedPort = basePort;
if (environment === 'development') {
// 开发环境:基础端口 + 租户偏移
const tenantOffset = (parseInt(tenantId) % 1000) * 10;
recommendedPort = basePort + tenantOffset;
} else if (environment === 'test') {
recommendedPort = basePort + 1000;
} else if (environment === 'production') {
recommendedPort = 8080; // 生产环境使用标准端口
}
console.log('🎯 智能端口计算:', {
environment,
tenantId,
basePort,
recommendedPort
});
return recommendedPort;
} catch (error) {
console.warn('⚠️ 端口计算失败,使用默认端口 3000:', error);
return 3000;
}
}
export default defineConfig(({ command }) => {
const isBuild = command === 'build';
// 智能端口配置(仅在开发模式下)
const smartPort = !isBuild ? getSmartPort() : undefined;
return {
// 在这里增加 base 写子路径
base: '/',
resolve: {
alias: {
'@/': resolve('src') + '/',
'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js'
}
},
// 智能服务器配置
server: {
port: smartPort || 3000,
host: '0.0.0.0', // 允许外部访问
open: true, // 自动打开浏览器
cors: true, // 启用 CORS
// 代理配置
proxy: {
'/api': {
target: process.env.VITE_API_URL || 'http://192.168.222.129:8000',
changeOrigin: true,
secure: false,
configure: (proxy, _options) => {
proxy.on('error', (err, _req, _res) => {
console.log('proxy error', err);
});
proxy.on('proxyReq', (proxyReq, req, _res) => {
console.log('Sending Request to the Target:', req.method, req.url);
});
proxy.on('proxyRes', (proxyRes, req, _res) => {
console.log('Received Response from the Target:', proxyRes.statusCode, req.url);
});
},
}
},
// 端口冲突时的处理
strictPort: false, // 允许自动选择其他端口
},
// 预览服务器配置(用于生产构建预览)
preview: {
port: smartPort ? smartPort + 1000 : 4173,
host: '0.0.0.0',
open: true,
cors: true,
strictPort: false,
},
plugins: [
vue({
script: {
defineModel: true,
propsDestructure: true
}
}),
// 组件按需引入
ViteComponents({
dts: false,
resolvers: [
AntDesignVueResolver({
importStyle: isBuild ? 'less' : false
}),
EleAdminResolver({
importStyle: isBuild ? 'less' : false
})
],
directoryAsNamespace: true
}),
// 代码分割
splitVendorChunkPlugin(),
// gzip 压缩
ViteCompression({
disable: !isBuild,
threshold: 10240,
algorithm: 'gzip',
ext: '.gz'
}),
// brotli 压缩
ViteCompression({
disable: !isBuild,
threshold: 10240,
algorithm: 'brotliCompress',
ext: '.br'
}),
// 打包分析
isBuild && visualizer({
filename: 'dist/stats.html',
open: false,
gzipSize: true,
brotliSize: true
})
].filter(Boolean),
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true,
plugins: [new DynamicAntdLess()],
modifyVars: {
// 组件样式开发环境全局引入生产环境按需引入
'style-entry-file': isBuild ? 'as-needed' : 'global-import'
}
}
}
},
optimizeDeps: {
include: [
'sortablejs',
'vuedraggable',
'echarts/core',
'echarts/charts',
'echarts/renderers',
'echarts/components',
'vue-echarts',
'echarts-wordcloud',
'xlsx',
'lodash-es',
'dayjs',
'crypto-js',
'js-md5',
'qrcode',
'nprogress'
],
exclude: ['@iconify/json']
},
build: {
target: 'es2015',
cssCodeSplit: true,
chunkSizeWarningLimit: 1000,
rollupOptions: {
output: {
// 手动分包
manualChunks: {
// Vue 生态
'vue-vendor': ['vue', 'vue-router', 'pinia'],
// UI 组件库
'ui-vendor': ['ant-design-vue', 'ele-admin-pro'],
// 工具库
'utils-vendor': ['lodash-es', 'dayjs', 'crypto-js', 'js-md5'],
// 图表库
'charts-vendor': ['echarts', 'vue-echarts', 'echarts-wordcloud'],
// 编辑器
'editor-vendor': ['tinymce', 'bytemd', 'md-editor-v3'],
// 文件处理
'file-vendor': ['xlsx', 'exceljs', 'file-saver', 'ali-oss']
},
// 文件命名
chunkFileNames: (chunkInfo) => {
const facadeModuleId = chunkInfo.facadeModuleId
? chunkInfo.facadeModuleId.split('/').pop().replace(/\.\w+$/, '')
: 'chunk';
return `js/${facadeModuleId}-[hash].js`;
},
assetFileNames: (assetInfo) => {
const info = assetInfo.name.split('.');
const ext = info[info.length - 1];
if (/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/i.test(assetInfo.name)) {
return `media/[name]-[hash].${ext}`;
}
if (/\.(png|jpe?g|gif|svg)(\?.*)?$/.test(assetInfo.name)) {
return `images/[name]-[hash].${ext}`;
}
if (/\.(woff2?|eot|ttf|otf)(\?.*)?$/i.test(assetInfo.name)) {
return `fonts/[name]-[hash].${ext}`;
}
return `assets/[name]-[hash].${ext}`;
}
}
},
// 压缩配置
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
pure_funcs: ['console.log']
}
}
}
};
});