@gsc-basic/vite-config 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +138 -0
- package/dist/index.d.ts +174 -0
- package/dist/index.js +415 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# @gsc-basic/vite-config
|
|
2
|
+
|
|
3
|
+
> Vite Config for GSC Basic Team
|
|
4
|
+
|
|
5
|
+
**DO NOT use it in your own project if you don't know what it's for**
|
|
6
|
+
|
|
7
|
+
这是团队内部封装的 Vite 配置集合,提供一组约定的插件、别名、构建与开发相关的默认配置,并暴露一个 `defineConfig` 工厂用于在项目中快速引入和定制配置。
|
|
8
|
+
|
|
9
|
+
**主要功能**
|
|
10
|
+
|
|
11
|
+
- 集成 Vue 3、JSX 支持
|
|
12
|
+
- 支持 UnoCSS、Icons 自动安装与组件解析
|
|
13
|
+
- 可选的压缩(gzip/brotliCompress),并支持生成 tarball
|
|
14
|
+
- 内置 HTML 注入(title / meta / 部署环境变量)
|
|
15
|
+
- 可选依赖分析、构建信息注入、二维码、mock 开发服务等
|
|
16
|
+
|
|
17
|
+
**导出**
|
|
18
|
+
|
|
19
|
+
- `defineConfig`: 用于创建 Vite 配置的工厂函数,接受一个返回应用层配置和 Vite 原生配置的异步函数。
|
|
20
|
+
|
|
21
|
+
快速浏览代码导出位置:`packages/vite-config/src/index.ts`。
|
|
22
|
+
|
|
23
|
+
## 安装
|
|
24
|
+
|
|
25
|
+
此包在 monorepo 中以 workspace 形式存在。如果你在外部项目使用(内部使用场景优先),请确保安装其 peer/dependencies:`vite`、`unocss`、`@vitejs/plugin-vue` 等。
|
|
26
|
+
|
|
27
|
+
示例(使用 pnpm):
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
pnpm add -D @gsc-basic/vite-config
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 快速开始
|
|
34
|
+
|
|
35
|
+
在你的项目根目录下创建 `vite.config.ts`,并使用 `defineConfig`:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { defineConfig } from '@gsc-basic/vite-config';
|
|
39
|
+
|
|
40
|
+
export default defineConfig(async (config) => {
|
|
41
|
+
return {
|
|
42
|
+
application: {
|
|
43
|
+
appInfo: {
|
|
44
|
+
pkg: { name: 'my-app', version: '0.0.1' },
|
|
45
|
+
lastBuildTime: new Date().toISOString(),
|
|
46
|
+
},
|
|
47
|
+
base: '/',
|
|
48
|
+
serverPort: 3000,
|
|
49
|
+
devtools: true,
|
|
50
|
+
// 更多配置参考ApplicationOptions
|
|
51
|
+
},
|
|
52
|
+
vite: {
|
|
53
|
+
// 额外的 Vite 原生配置会被 merge 到默认配置上
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## DefineConfig 与配置结构
|
|
60
|
+
|
|
61
|
+
`defineConfig` 接受一个可选的异步函数(类型 `DefineConfig`),该函数接收 Vite 的 `ConfigEnv` 并返回一个对象:
|
|
62
|
+
|
|
63
|
+
- `application`:应用级别的自定义选项(参见下文 `ApplicationOptions`)。
|
|
64
|
+
- `vite`:原生 `vite` 的 `UserConfig`,会与默认配置合并(`mergeConfig`)。
|
|
65
|
+
|
|
66
|
+
### ApplicationOptions(常用字段说明)
|
|
67
|
+
|
|
68
|
+
- `appInfo`: 任意对象,会注入到 `__APP_INFO__`,可用于 banner 或运行时读取。
|
|
69
|
+
- `base`: 应用公共路径(默认 `/`)。
|
|
70
|
+
- `serverPort`: 本地开发端口(默认 `8080`)。
|
|
71
|
+
- `openPage`: 启动时是否自动打开浏览器(默认 true)。
|
|
72
|
+
- `devtools`: 开启 `vite-plugin-vue-devtools`(开发模式)。
|
|
73
|
+
- `injectMetadata`: 注入构建元数据(使用 `unplugin-info`)。
|
|
74
|
+
- `analyzer`: 使用 `vite-bundle-analyzer`(默认在 dev 开启)。
|
|
75
|
+
- `unocss`: 开启 UnoCSS 支持。
|
|
76
|
+
- `iconify`: 自动安装并使用 `unplugin-icons`。
|
|
77
|
+
- `svgIcon`: 开启内置 SVG 图标处理(配置 `svgIconOptions`)。
|
|
78
|
+
- `compress`: 在构建阶段开启资源压缩(gzip/brotli)。
|
|
79
|
+
- `compressOptions`: 压缩插件的额外选项(`compressList`, `tarballResult`, `deleteOriginalAssets`)。
|
|
80
|
+
- `html`: 注入 HTML(title、meta、部署环境变量)。
|
|
81
|
+
- `i18n`: 启用 `@intlify/unplugin-vue-i18n`。
|
|
82
|
+
- `license`: 在构建产物中注入 package 信息的 banner。
|
|
83
|
+
- `legacy`: 使用 `@vitejs/plugin-legacy` 处理旧浏览器兼容(构建时可选)。
|
|
84
|
+
- `updateNotice`: 显示前端更新通知(web update notification)。
|
|
85
|
+
- `qrcode`: 在开发模式显示二维码(vite-plugin-qrcode)。
|
|
86
|
+
- `mock`: 启用 `vite-plugin-mock-dev-server`(开发模式)。
|
|
87
|
+
- `turboConsole`: 在开发模式使用 `unplugin-turbo-console`。
|
|
88
|
+
|
|
89
|
+
还有其他字段请参考 `packages/vite-config/src/typing.ts`。
|
|
90
|
+
|
|
91
|
+
补充说明以下字段:
|
|
92
|
+
|
|
93
|
+
- `showProxyLog`: 是否在开发或 preview 模式下显示代理请求日志(默认为 false)。
|
|
94
|
+
- `proxyConfig`: 代理配置数组,元素类型 `ProxySettingItem`,包含 `prefix`(匹配前缀)、`target`(代理目标地址)、`rewrite`(是否重写前缀)。此配置会被 `createProxy` 工具转换为 Vite `server.proxy` 配置。
|
|
95
|
+
- `showPreviewProxyLog`: 是否在 `vite preview` 模式下显示代理日志。
|
|
96
|
+
- `previewProxyConfig`: 与 `proxyConfig` 类似,但用于 `preview` 模式。
|
|
97
|
+
- `lessModifyVars`: 如果项目使用 Less,可通过此对象传入 Less 变量覆盖(例如主题色、字体等),该对象会被写入 `css.preprocessorOptions.less.modifyVars`。
|
|
98
|
+
- `themeToken`: 用于注入(或生成)主题相关 token 的对象,例如 `{ colorPrimary: '#00a' }`,会被 `unplugin-info` 等插件作为元数据注入或在 update-notice 插件中被引用作为 primaryColor。
|
|
99
|
+
- `prefixClass`: 用于 SVG 插件或样式前缀的字符串(例如 `lenovo`),会被传给 SVG 相关插件用于 DOM id 或 class 前缀。
|
|
100
|
+
- `appTitle`: 应用标题,默认用于 HTML 注入的 `<title>`。
|
|
101
|
+
|
|
102
|
+
## 插件说明与可配置项
|
|
103
|
+
|
|
104
|
+
- Vue & JSX:`@vitejs/plugin-vue` + `@vitejs/plugin-vue-jsx`(自动启用)。
|
|
105
|
+
- UnoCSS:通过 `unocss/vite` 启用,选项 `unocss: true/false`。
|
|
106
|
+
- Icons(unplugin-icons):通过 `iconify: true/false` 开启并自动安装图标。
|
|
107
|
+
- SVG 图标(unplugin-svg-component):通过 `svgIcon` 和 `svgIconOptions` 配置。默认 `iconDir` 为 `src/assets/icons`,`prefixClass` 默认为 `lenovo`。
|
|
108
|
+
- Compress(vite-plugin-compression2):`compressOptions.compressList` 可传入 `["gzip","brotliCompress"]`,`tarballResult` 将在打包后生成 tarball,`deleteOriginalAssets` 可删除原始资源。
|
|
109
|
+
- HTML 注入:`application.appTitle` 与 `application.appInfo` 会被注入到 index.html,且会写入一个部署环境的全局变量(由常量 `DEPLOY_ENV_NAME` 控制)。
|
|
110
|
+
- Analyzer:使用 `vite-bundle-analyzer`,接口 `configAnalyzerPlugin(title, port)`。
|
|
111
|
+
- Update Notice:`@plugin-web-update-notification/vite`,在构建或运行时展示更新提示。
|
|
112
|
+
|
|
113
|
+
## 示例:开启构建压缩与生成 tarball
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { defineConfig } from '@gsc-basic/vite-config';
|
|
117
|
+
|
|
118
|
+
export default defineConfig(async () => ({
|
|
119
|
+
application: {
|
|
120
|
+
appInfo: { pkg: { name: 'demo', version: '1.0.0' }, lastBuildTime: new Date().toISOString() },
|
|
121
|
+
isBuild: true,
|
|
122
|
+
compress: true,
|
|
123
|
+
compressOptions: {
|
|
124
|
+
compressList: ['gzip', 'brotliCompress'],
|
|
125
|
+
tarballResult: true,
|
|
126
|
+
deleteOriginalAssets: false,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
}));
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 常见问题
|
|
133
|
+
|
|
134
|
+
- Q: 如何自定义 Vite 原生配置?
|
|
135
|
+
A: 在 `defineConfig` 返回对象中通过 `vite` 字段传入,库会用 `mergeConfig` 将其与内置的默认配置合并。
|
|
136
|
+
|
|
137
|
+
- Q: 如何修改 SVG 图标目录?
|
|
138
|
+
A: 在 `application.svgIconOptions.iconDir` 中传入自定义相对路径,如 `src/assets/my-icons`。
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import * as vite from 'vite';
|
|
2
|
+
import { ConfigEnv, UserConfig, PluginOption } from 'vite';
|
|
3
|
+
|
|
4
|
+
interface CompressOptions {
|
|
5
|
+
compressList?: Array<'gzip' | 'brotliCompress'>;
|
|
6
|
+
tarballResult?: boolean;
|
|
7
|
+
deleteOriginalAssets?: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface SvgIconOptions {
|
|
10
|
+
iconDir?: string;
|
|
11
|
+
preserveColorDir?: string;
|
|
12
|
+
componentName?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 通用插件配置选项
|
|
16
|
+
* @description 所有插件共用的基础配置
|
|
17
|
+
*/
|
|
18
|
+
interface CommonPluginOptions {
|
|
19
|
+
/**
|
|
20
|
+
* 是否为构建模式
|
|
21
|
+
*/
|
|
22
|
+
isBuild?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* 是否开启开发工具
|
|
25
|
+
* @default false
|
|
26
|
+
*/
|
|
27
|
+
devtools?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* 环境变量
|
|
30
|
+
* @description 自定义环境变量
|
|
31
|
+
*/
|
|
32
|
+
env?: Record<string, any>;
|
|
33
|
+
/**
|
|
34
|
+
* 是否注入元数据
|
|
35
|
+
* @default true
|
|
36
|
+
*/
|
|
37
|
+
injectMetadata?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* 是否开启依赖分析
|
|
40
|
+
* @default false
|
|
41
|
+
* @description 使用 vite-bundle-analyzer 分析依赖
|
|
42
|
+
*/
|
|
43
|
+
analyzer?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* 是否开启UnoCSS支持
|
|
46
|
+
* @default true
|
|
47
|
+
*/
|
|
48
|
+
unocss?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* 图标自动安装选项
|
|
51
|
+
* @description 配置图标自动安装功能
|
|
52
|
+
* @default true
|
|
53
|
+
*/
|
|
54
|
+
iconify?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* 是否开启 SVG 图标支持
|
|
57
|
+
* @default true
|
|
58
|
+
*/
|
|
59
|
+
svgIcon?: boolean;
|
|
60
|
+
svgIconOptions?: SvgIconOptions;
|
|
61
|
+
/**
|
|
62
|
+
* 是否开启压缩
|
|
63
|
+
* @default false
|
|
64
|
+
* @description 支持 gzip 和 brotli 压缩
|
|
65
|
+
*/
|
|
66
|
+
compress?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* 压缩类型
|
|
69
|
+
* @default ['gzip']
|
|
70
|
+
* @description 可选的压缩类型
|
|
71
|
+
*/
|
|
72
|
+
compressOptions?: CompressOptions;
|
|
73
|
+
/**
|
|
74
|
+
* 是否开启 HTML 插件
|
|
75
|
+
* @default true
|
|
76
|
+
*/
|
|
77
|
+
html?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* 是否开启国际化
|
|
80
|
+
* @default false
|
|
81
|
+
*/
|
|
82
|
+
i18n?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* 是否注入版权信息
|
|
85
|
+
* @default true
|
|
86
|
+
*/
|
|
87
|
+
license?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* 是否开启 legacy 支持
|
|
90
|
+
* @default false
|
|
91
|
+
*/
|
|
92
|
+
legacy?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* 是否显示更新通知
|
|
95
|
+
* @default true
|
|
96
|
+
*/
|
|
97
|
+
updateNotice?: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* 是否生成二维码
|
|
100
|
+
* @default false
|
|
101
|
+
*/
|
|
102
|
+
qrcode?: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* 是否开启模拟数据
|
|
105
|
+
* @default true
|
|
106
|
+
*/
|
|
107
|
+
mock?: boolean;
|
|
108
|
+
/**
|
|
109
|
+
* 是否开启 Turbo Console
|
|
110
|
+
* @default true
|
|
111
|
+
*/
|
|
112
|
+
turboConsole?: boolean;
|
|
113
|
+
}
|
|
114
|
+
interface ProxySettingItem {
|
|
115
|
+
prefix: string;
|
|
116
|
+
target: string;
|
|
117
|
+
rewrite?: boolean;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* 应用配置选项类型
|
|
121
|
+
*/
|
|
122
|
+
interface ApplicationOptions extends CommonPluginOptions {
|
|
123
|
+
appInfo: Record<string, any>;
|
|
124
|
+
base?: string;
|
|
125
|
+
serverPort?: number;
|
|
126
|
+
openPage?: boolean;
|
|
127
|
+
showProxyLog?: boolean;
|
|
128
|
+
proxyConfig?: ProxySettingItem[];
|
|
129
|
+
showPreviewProxyLog?: boolean;
|
|
130
|
+
previewProxyConfig?: ProxySettingItem[];
|
|
131
|
+
lessModifyVars?: Record<string, string>;
|
|
132
|
+
themeToken?: Record<string, string>;
|
|
133
|
+
prefixClass?: string;
|
|
134
|
+
appTitle?: string;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* 应用配置定义函数类型(默认暂不支持library模式)
|
|
138
|
+
* @description 用于定义应用构建配置
|
|
139
|
+
*/
|
|
140
|
+
type DefineConfig = (config?: ConfigEnv) => Promise<{
|
|
141
|
+
/** 应用插件配置 */
|
|
142
|
+
application?: ApplicationOptions;
|
|
143
|
+
/** Vite 配置 */
|
|
144
|
+
vite?: UserConfig;
|
|
145
|
+
}>;
|
|
146
|
+
|
|
147
|
+
declare function createVitePlugins(options: ApplicationOptions): PluginOption[];
|
|
148
|
+
|
|
149
|
+
declare const OUTPUT_DIR = "dist";
|
|
150
|
+
declare const DEPLOY_ENV_NAME = "__DEPLOY_ENV_NAME__";
|
|
151
|
+
|
|
152
|
+
declare function defineConfig(config?: DefineConfig): vite.UserConfigFnPromise;
|
|
153
|
+
|
|
154
|
+
declare function generateProjectInfo(includeLogo?: boolean, { pkg }?: {
|
|
155
|
+
pkg?: Record<string, string>;
|
|
156
|
+
}): string;
|
|
157
|
+
interface ProxyItem {
|
|
158
|
+
prefix: string;
|
|
159
|
+
target: string;
|
|
160
|
+
rewrite?: boolean;
|
|
161
|
+
}
|
|
162
|
+
interface ProxyOptions {
|
|
163
|
+
[prefix: string]: {
|
|
164
|
+
target: string;
|
|
165
|
+
changeOrigin: boolean;
|
|
166
|
+
ws: boolean;
|
|
167
|
+
rewrite: (path: string) => string;
|
|
168
|
+
secure?: boolean;
|
|
169
|
+
configure?: (proxy: any) => void;
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
declare function createProxy(list: ProxyItem[], showProxyLog?: boolean): ProxyOptions;
|
|
173
|
+
|
|
174
|
+
export { type ApplicationOptions, type CommonPluginOptions, type CompressOptions, DEPLOY_ENV_NAME, type DefineConfig, OUTPUT_DIR, type ProxyItem, type ProxyOptions, type ProxySettingItem, type SvgIconOptions, createProxy, createVitePlugins, defineConfig, generateProjectInfo };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
// src/plugins/index.ts
|
|
2
|
+
import { random } from "lodash-es";
|
|
3
|
+
import vue from "@vitejs/plugin-vue";
|
|
4
|
+
import vueJsx from "@vitejs/plugin-vue-jsx";
|
|
5
|
+
import legacy from "@vitejs/plugin-legacy";
|
|
6
|
+
import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite";
|
|
7
|
+
import banner from "vite-plugin-banner";
|
|
8
|
+
import { qrcode } from "vite-plugin-qrcode";
|
|
9
|
+
import { mockDevServerPlugin } from "vite-plugin-mock-dev-server";
|
|
10
|
+
import Info from "unplugin-info/vite";
|
|
11
|
+
import turboConsole from "unplugin-turbo-console/vite";
|
|
12
|
+
import devTools from "vite-plugin-vue-devtools";
|
|
13
|
+
import unoCSS from "unocss/vite";
|
|
14
|
+
import Icons from "unplugin-icons/vite";
|
|
15
|
+
import IconsResolver from "unplugin-icons/resolver";
|
|
16
|
+
import Components from "unplugin-vue-components/vite";
|
|
17
|
+
|
|
18
|
+
// src/constant.ts
|
|
19
|
+
var OUTPUT_DIR = "dist";
|
|
20
|
+
var DEPLOY_ENV_NAME = "__DEPLOY_ENV_NAME__";
|
|
21
|
+
|
|
22
|
+
// src/plugins/html.ts
|
|
23
|
+
function configHtmlPlugin(title = "GSC Scaffolding", appInfo) {
|
|
24
|
+
return {
|
|
25
|
+
name: "html-injection",
|
|
26
|
+
transformIndexHtml(html) {
|
|
27
|
+
const revisedContent = `${appInfo.lastBuildTime}(v${appInfo.pkg.version})`;
|
|
28
|
+
return html.replace(
|
|
29
|
+
"</head>",
|
|
30
|
+
`<title>${title}</title>
|
|
31
|
+
<meta name="revised" content="${revisedContent}" />
|
|
32
|
+
<script>window.${DEPLOY_ENV_NAME} = "@DEPLOY__ENV";</script>
|
|
33
|
+
</head>`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/plugins/compress.ts
|
|
40
|
+
import { compression, tarball } from "vite-plugin-compression2";
|
|
41
|
+
function configCompressPlugin(options) {
|
|
42
|
+
const {
|
|
43
|
+
compressList = [],
|
|
44
|
+
// 可选值: 'gzip' | 'brotliCompress'
|
|
45
|
+
tarballResult = false,
|
|
46
|
+
// 是否压缩后为所有资源创建一个 tarball
|
|
47
|
+
deleteOriginalAssets = false
|
|
48
|
+
// 是否删除原有资源
|
|
49
|
+
} = options;
|
|
50
|
+
const plugins = [];
|
|
51
|
+
if (compressList.length > 0) {
|
|
52
|
+
plugins.push(
|
|
53
|
+
compression({
|
|
54
|
+
algorithms: compressList,
|
|
55
|
+
deleteOriginalAssets,
|
|
56
|
+
skipIfLargerOrEqual: false,
|
|
57
|
+
exclude: [/\.(br)$/, /\.(gz)$/]
|
|
58
|
+
})
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
if (tarballResult && plugins.length > 0) {
|
|
62
|
+
plugins.push(tarball());
|
|
63
|
+
}
|
|
64
|
+
return plugins;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/plugins/svgIcons.ts
|
|
68
|
+
import path from "path";
|
|
69
|
+
import unpluginSvgComponent from "unplugin-svg-component/vite";
|
|
70
|
+
function configSvgIconsPlugin({
|
|
71
|
+
prefixClass = "lenovo",
|
|
72
|
+
iconDir = "src/assets/icons",
|
|
73
|
+
componentName = "SvgIcon",
|
|
74
|
+
preserveColorDir
|
|
75
|
+
}) {
|
|
76
|
+
const options = {
|
|
77
|
+
treeShaking: false
|
|
78
|
+
// 因为涉及动态引入,所以默认关闭
|
|
79
|
+
};
|
|
80
|
+
if (preserveColorDir) {
|
|
81
|
+
options.preserveColor = path.resolve(process.cwd(), preserveColorDir);
|
|
82
|
+
}
|
|
83
|
+
return unpluginSvgComponent({
|
|
84
|
+
iconDir: [path.resolve(process.cwd(), iconDir)],
|
|
85
|
+
projectType: "vue",
|
|
86
|
+
vueVersion: 3,
|
|
87
|
+
dts: false,
|
|
88
|
+
componentName,
|
|
89
|
+
prefix: void 0,
|
|
90
|
+
symbolIdFormatter: (svgName, prefix) => {
|
|
91
|
+
const nameArr = svgName.split("/");
|
|
92
|
+
if (prefix) {
|
|
93
|
+
nameArr.unshift(prefix);
|
|
94
|
+
}
|
|
95
|
+
return nameArr.join("-").replace(/\.svg$/, "");
|
|
96
|
+
},
|
|
97
|
+
componentStyle: "width: 1em;height: 1em;fill: currentColor;vertical-align: -0.125em;",
|
|
98
|
+
svgSpriteDomId: `${prefixClass}-svg-dom`,
|
|
99
|
+
domInsertionStrategy: "dynamic"
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// src/plugins/analyzer.ts
|
|
104
|
+
import { analyzer } from "vite-bundle-analyzer";
|
|
105
|
+
function configAnalyzerPlugin(title = "", port = 8080) {
|
|
106
|
+
return analyzer({
|
|
107
|
+
reportTitle: `${title} Analyzer`,
|
|
108
|
+
analyzerMode: "server",
|
|
109
|
+
analyzerPort: port + 200,
|
|
110
|
+
openAnalyzer: true
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/plugins/updateNotice.ts
|
|
115
|
+
import { webUpdateNotice } from "@plugin-web-update-notification/vite";
|
|
116
|
+
function configUpdateNotice({ base, primaryColor }) {
|
|
117
|
+
return webUpdateNotice({
|
|
118
|
+
checkInterval: 30 * 60 * 1e3,
|
|
119
|
+
checkOnWindowFocus: true,
|
|
120
|
+
checkImmediately: false,
|
|
121
|
+
// 这个逻辑放到设置完成语言之后
|
|
122
|
+
checkOnLoadFileError: true,
|
|
123
|
+
hiddenDefaultNotification: false,
|
|
124
|
+
logVersion: false,
|
|
125
|
+
// notificationProps,
|
|
126
|
+
notificationConfig: {
|
|
127
|
+
primaryColor
|
|
128
|
+
},
|
|
129
|
+
injectFileBase: base ?? "/"
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/utils/index.ts
|
|
134
|
+
import ansis from "ansis";
|
|
135
|
+
import { regexpMap } from "@gsc-basic/utils";
|
|
136
|
+
var bannerLogo = ` / /
|
|
137
|
+
/ / ___ __ ___ ___
|
|
138
|
+
/ / //___) ) // ) ) // ) ) || / / // ) )
|
|
139
|
+
/ / // // / / // / / || / / // / /
|
|
140
|
+
/ /____/ / ((____ // / / ((___/ / ||/ / ((___/ /`;
|
|
141
|
+
function generateProjectInfo(includeLogo = true, { pkg } = {}) {
|
|
142
|
+
return `/**
|
|
143
|
+
${includeLogo ? `${bannerLogo}
|
|
144
|
+
` : ""} * name: ${pkg?.name}
|
|
145
|
+
* version: v${pkg?.version}
|
|
146
|
+
* description: ${pkg?.description}
|
|
147
|
+
* author: ${typeof pkg?.author === "string" ? pkg.author : pkg?.author && pkg.author.name || ""}
|
|
148
|
+
*/`;
|
|
149
|
+
}
|
|
150
|
+
function createProxy(list, showProxyLog = false) {
|
|
151
|
+
const proxy = {};
|
|
152
|
+
for (const item of list) {
|
|
153
|
+
let { prefix, target, rewrite } = item;
|
|
154
|
+
if (typeof rewrite === "undefined") {
|
|
155
|
+
rewrite = true;
|
|
156
|
+
}
|
|
157
|
+
const isHttps = regexpMap.httpsUrl.test(target);
|
|
158
|
+
proxy[prefix] = {
|
|
159
|
+
target,
|
|
160
|
+
changeOrigin: true,
|
|
161
|
+
ws: true,
|
|
162
|
+
rewrite: (path2) => {
|
|
163
|
+
if (rewrite) {
|
|
164
|
+
return path2.replace(new RegExp(`^${prefix}`), "");
|
|
165
|
+
}
|
|
166
|
+
return path2;
|
|
167
|
+
},
|
|
168
|
+
// https is require secure=false
|
|
169
|
+
...isHttps ? { secure: false } : {},
|
|
170
|
+
...showProxyLog ? {
|
|
171
|
+
configure: (proxy2) => {
|
|
172
|
+
proxy2.on("proxyRes", (proxyRes, req) => {
|
|
173
|
+
console.log(
|
|
174
|
+
"proxy: ",
|
|
175
|
+
ansis.red(req.originalUrl),
|
|
176
|
+
" ===> ",
|
|
177
|
+
ansis.green(proxyRes.client.servername + req.url)
|
|
178
|
+
);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
} : {}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
return proxy;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/plugins/index.ts
|
|
188
|
+
function createVitePlugins(options) {
|
|
189
|
+
const vitePlugins = [
|
|
190
|
+
vue({
|
|
191
|
+
template: {
|
|
192
|
+
compilerOptions: {
|
|
193
|
+
isCustomElement: (tag) => tag.startsWith("micro-app")
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}),
|
|
197
|
+
vueJsx()
|
|
198
|
+
];
|
|
199
|
+
const componentsResolvers = [];
|
|
200
|
+
if (options.unocss) {
|
|
201
|
+
vitePlugins.push(
|
|
202
|
+
unoCSS({
|
|
203
|
+
mode: "global"
|
|
204
|
+
})
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
if (options.iconify) {
|
|
208
|
+
vitePlugins.push(
|
|
209
|
+
Icons({
|
|
210
|
+
compiler: "vue3",
|
|
211
|
+
autoInstall: true
|
|
212
|
+
})
|
|
213
|
+
);
|
|
214
|
+
componentsResolvers.push(IconsResolver());
|
|
215
|
+
}
|
|
216
|
+
if (options.injectMetadata) {
|
|
217
|
+
vitePlugins.push(
|
|
218
|
+
Info({
|
|
219
|
+
/* 可以配置一些供项目中访问的元数据,数据将序列化为JSON格式 */
|
|
220
|
+
meta: { themeToken: options.themeToken },
|
|
221
|
+
package: {
|
|
222
|
+
dependencies: true,
|
|
223
|
+
devDependencies: true
|
|
224
|
+
}
|
|
225
|
+
})
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
if (options.i18n) {
|
|
229
|
+
vitePlugins.push(
|
|
230
|
+
VueI18nPlugin({
|
|
231
|
+
fullInstall: true,
|
|
232
|
+
runtimeOnly: true
|
|
233
|
+
})
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
if (options.isBuild) {
|
|
237
|
+
if (options.legacy) {
|
|
238
|
+
vitePlugins.push(
|
|
239
|
+
legacy({
|
|
240
|
+
targets: ["> 0.2%", "not dead", "not op_mini all"]
|
|
241
|
+
})
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
if (options.compress) {
|
|
245
|
+
vitePlugins.push(
|
|
246
|
+
...configCompressPlugin(options.compressOptions || {})
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
if (options.license) {
|
|
250
|
+
vitePlugins.push(
|
|
251
|
+
banner(generateProjectInfo(true, options.appInfo))
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
if (options.updateNotice) {
|
|
255
|
+
vitePlugins.push(configUpdateNotice({
|
|
256
|
+
base: options.base,
|
|
257
|
+
primaryColor: options.themeToken?.colorPrimary
|
|
258
|
+
}));
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
261
|
+
if (options.turboConsole) {
|
|
262
|
+
vitePlugins.push(
|
|
263
|
+
turboConsole({
|
|
264
|
+
server: {
|
|
265
|
+
port: (options.serverPort ?? 8080) + random(100, 1e3)
|
|
266
|
+
},
|
|
267
|
+
launchEditor: true
|
|
268
|
+
})
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
if (options.devtools) {
|
|
272
|
+
vitePlugins.push(
|
|
273
|
+
devTools({
|
|
274
|
+
launchEditor: "code"
|
|
275
|
+
// Visual Studio Code
|
|
276
|
+
})
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
if (options.qrcode) {
|
|
280
|
+
vitePlugins.push(qrcode());
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (options.svgIcon) {
|
|
284
|
+
const svgOpts = options.svgIconOptions ?? {};
|
|
285
|
+
vitePlugins.push(
|
|
286
|
+
configSvgIconsPlugin({
|
|
287
|
+
prefixClass: options.prefixClass,
|
|
288
|
+
iconDir: svgOpts.iconDir,
|
|
289
|
+
preserveColorDir: svgOpts.preserveColorDir
|
|
290
|
+
})
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
if (options.html) {
|
|
294
|
+
vitePlugins.push(
|
|
295
|
+
configHtmlPlugin(options.appTitle, options.appInfo)
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
if (options.mock) {
|
|
299
|
+
vitePlugins.push(mockDevServerPlugin({}));
|
|
300
|
+
}
|
|
301
|
+
if (options.analyzer) {
|
|
302
|
+
vitePlugins.push(configAnalyzerPlugin(options.appTitle, options.serverPort));
|
|
303
|
+
}
|
|
304
|
+
if (componentsResolvers.length > 0) {
|
|
305
|
+
vitePlugins.push(
|
|
306
|
+
Components({
|
|
307
|
+
resolvers: componentsResolvers
|
|
308
|
+
})
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
return vitePlugins;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// src/config/common.ts
|
|
315
|
+
import { resolve } from "path";
|
|
316
|
+
import { defineConfig, mergeConfig } from "vite";
|
|
317
|
+
import autoprefixer from "autoprefixer";
|
|
318
|
+
function pathResolve(dir) {
|
|
319
|
+
return resolve(process.cwd(), ".", dir);
|
|
320
|
+
}
|
|
321
|
+
function defineCommonConfig(configPromise) {
|
|
322
|
+
return defineConfig(async (config) => {
|
|
323
|
+
const { command } = config;
|
|
324
|
+
const options = await configPromise?.(config);
|
|
325
|
+
const {
|
|
326
|
+
application = {
|
|
327
|
+
appInfo: {},
|
|
328
|
+
devtools: false,
|
|
329
|
+
injectMetadata: true,
|
|
330
|
+
analyzer: true,
|
|
331
|
+
unocss: true,
|
|
332
|
+
iconify: true,
|
|
333
|
+
svgIcon: true,
|
|
334
|
+
compress: false,
|
|
335
|
+
html: true,
|
|
336
|
+
i18n: true,
|
|
337
|
+
license: true,
|
|
338
|
+
legacy: true,
|
|
339
|
+
updateNotice: true,
|
|
340
|
+
qrcode: false,
|
|
341
|
+
mock: true,
|
|
342
|
+
turboConsole: true
|
|
343
|
+
}
|
|
344
|
+
} = options || {};
|
|
345
|
+
const isBuild = command === "build";
|
|
346
|
+
const commonConfig = {
|
|
347
|
+
base: application.base ?? "/",
|
|
348
|
+
root: process.cwd(),
|
|
349
|
+
logLevel: "info",
|
|
350
|
+
resolve: {
|
|
351
|
+
alias: [
|
|
352
|
+
{
|
|
353
|
+
find: /@\//,
|
|
354
|
+
replacement: `${pathResolve("src")}/`
|
|
355
|
+
}
|
|
356
|
+
]
|
|
357
|
+
},
|
|
358
|
+
server: {
|
|
359
|
+
host: true,
|
|
360
|
+
port: application.serverPort ?? 8080,
|
|
361
|
+
open: application.openPage ?? true,
|
|
362
|
+
hmr: true,
|
|
363
|
+
proxy: createProxy(application.proxyConfig || [], application.showProxyLog ?? false),
|
|
364
|
+
headers: {
|
|
365
|
+
"Access-Control-Allow-Origin": "*"
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
preview: {
|
|
369
|
+
port: (application.serverPort ?? 8080) + 100,
|
|
370
|
+
proxy: createProxy(application.previewProxyConfig || [], application.showPreviewProxyLog ?? false)
|
|
371
|
+
},
|
|
372
|
+
esbuild: {
|
|
373
|
+
charset: "ascii"
|
|
374
|
+
},
|
|
375
|
+
build: {
|
|
376
|
+
outDir: "dist",
|
|
377
|
+
minify: "esbuild",
|
|
378
|
+
// 不用 gzip 压缩大小报告
|
|
379
|
+
reportCompressedSize: false,
|
|
380
|
+
chunkSizeWarningLimit: 5e3,
|
|
381
|
+
assetsInlineLimit: 1024
|
|
382
|
+
},
|
|
383
|
+
define: {
|
|
384
|
+
"__APP_INFO__": JSON.stringify(application.appInfo ?? {}),
|
|
385
|
+
"import.meta.vitest": "undefined"
|
|
386
|
+
},
|
|
387
|
+
css: {
|
|
388
|
+
preprocessorOptions: {
|
|
389
|
+
less: {
|
|
390
|
+
modifyVars: application.lessModifyVars || {},
|
|
391
|
+
javascriptEnabled: true
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
postcss: {
|
|
395
|
+
plugins: isBuild ? [autoprefixer()] : []
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
plugins: createVitePlugins({ ...application, isBuild })
|
|
399
|
+
};
|
|
400
|
+
return mergeConfig(commonConfig, options?.vite || {});
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// src/config/index.ts
|
|
405
|
+
function defineConfig2(config) {
|
|
406
|
+
return defineCommonConfig(config);
|
|
407
|
+
}
|
|
408
|
+
export {
|
|
409
|
+
DEPLOY_ENV_NAME,
|
|
410
|
+
OUTPUT_DIR,
|
|
411
|
+
createProxy,
|
|
412
|
+
createVitePlugins,
|
|
413
|
+
defineConfig2 as defineConfig,
|
|
414
|
+
generateProjectInfo
|
|
415
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gsc-basic/vite-config",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Vite Config for GSC Basic Service",
|
|
6
|
+
"author": "wangll47 <wangll47@lenovo.com>",
|
|
7
|
+
"license": "UNLICENSED",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://gitlab.xpaas.lenovo.com/tsd-basic/gsc-frontend-config.git"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"GSC Basic",
|
|
14
|
+
"Vite"
|
|
15
|
+
],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public",
|
|
18
|
+
"registry": "https://registry.npmjs.org/"
|
|
19
|
+
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"import": "./dist/index.js",
|
|
23
|
+
"require": "./dist/index.cjs"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"files": [
|
|
29
|
+
"./dist"
|
|
30
|
+
],
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@iconify/json": "^2.2.416",
|
|
33
|
+
"lodash-es": "^4.17.21",
|
|
34
|
+
"unocss": "^66.5.10",
|
|
35
|
+
"vite": "^7.2.6"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@intlify/unplugin-vue-i18n": "^11.0.1",
|
|
39
|
+
"@plugin-web-update-notification/vite": "^2.0.2",
|
|
40
|
+
"@vitejs/plugin-legacy": "^7.2.1",
|
|
41
|
+
"@vitejs/plugin-vue": "^6.0.2",
|
|
42
|
+
"@vitejs/plugin-vue-jsx": "^5.1.2",
|
|
43
|
+
"ansis": "^4.2.0",
|
|
44
|
+
"autoprefixer": "^10.4.22",
|
|
45
|
+
"unplugin-icons": "^22.5.0",
|
|
46
|
+
"unplugin-info": "^1.2.4",
|
|
47
|
+
"unplugin-svg-component": "^0.12.4",
|
|
48
|
+
"unplugin-turbo-console": "^2.3.0",
|
|
49
|
+
"unplugin-vue-components": "^30.0.0",
|
|
50
|
+
"vite-bundle-analyzer": "^1.2.3",
|
|
51
|
+
"vite-plugin-banner": "^0.8.1",
|
|
52
|
+
"vite-plugin-compression2": "^2.4.0",
|
|
53
|
+
"vite-plugin-mock-dev-server": "^2.0.5",
|
|
54
|
+
"vite-plugin-qrcode": "^0.3.0",
|
|
55
|
+
"vite-plugin-vue-devtools": "^8.0.5",
|
|
56
|
+
"@gsc-basic/utils": "1.2.6"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsup",
|
|
60
|
+
"outdated": "pnpm outdated",
|
|
61
|
+
"clean": "rimraf ./dist"
|
|
62
|
+
}
|
|
63
|
+
}
|