@dlzn-ui/vite-config 1.63.0 → 1.66.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.
@@ -1,19 +0,0 @@
1
- import { basename } from 'node:path'
2
- import { upperFirst } from '@dlzn-ui/node-utils'
3
- import { globSync } from 'tinyglobby'
4
-
5
- export default (root: string) => {
6
- const piniaStoreKeys: string[] = []
7
- const files = globSync('src/store/modules/*.ts', { cwd: root })
8
-
9
- files.forEach((p) => {
10
- piniaStoreKeys.push(basename(p, '.ts'))
11
- })
12
-
13
- const customerImport: Record<string, [string, string][]> = {}
14
-
15
- piniaStoreKeys.forEach((key) => {
16
- customerImport[`@/store/modules/${key}`] = [['default', `use${upperFirst(key)}Store`]]
17
- })
18
- return customerImport
19
- }
package/commonConfig.ts DELETED
@@ -1,36 +0,0 @@
1
- import type { UserConfig } from 'vite'
2
- import tailwindcss from '@tailwindcss/vite'
3
- import vue from '@vitejs/plugin-vue'
4
- import vueJsx from '@vitejs/plugin-vue-jsx'
5
- import browserslist from 'browserslist'
6
- import { browserslistToTargets } from 'lightningcss'
7
- import tailwindAutoReference from 'vite-plugin-vue-tailwind-auto-reference'
8
-
9
- interface Options {
10
- tailwindAutoReferenceEntry: string
11
- }
12
-
13
- export default (options: Options): UserConfig => {
14
- const { tailwindAutoReferenceEntry } = options
15
-
16
- return {
17
- clearScreen: false, // 设为 false 可以避免 Vite 清屏而错过在终端中打印某些关键信息
18
- css: {
19
- lightningcss: {
20
- // https://cn.vitejs.dev/config/shared-options#css-lightningcss
21
- targets: browserslistToTargets(browserslist('>= 0.25%')),
22
- },
23
- transformer: 'lightningcss', // 开发/构建时怎么转译 CSS
24
- },
25
- plugins: [
26
- tailwindAutoReference(tailwindAutoReferenceEntry), // It must be registered before tailwindcss() official plugin!
27
- tailwindcss(),
28
- vue({
29
- // features: {
30
- // optionsAPI: false, // 不能删掉,tdesign 内部使用到了
31
- // },
32
- }),
33
- vueJsx(),
34
- ],
35
- }
36
- }
@@ -1,144 +0,0 @@
1
- import type { IncomingMessage, ServerResponse } from 'node:http'
2
- import type { Connect, Plugin, ViteDevServer } from 'vite'
3
- import fs from 'node:fs/promises'
4
- import { resolve } from 'node:path'
5
-
6
- const ENDPOINT = '/__dev__/save-folder-alias'
7
- const OUTPUT_FILE_WATCH_IGNORE = '**/folder-alias.json'
8
- const SKIP_COMPONENTS = new Set(['Layout', 'ParentView'])
9
-
10
- type FolderAliasMap = Record<string, { description: string }>
11
- interface ResRouterItem {
12
- children?: ResRouterItem[]
13
- component: string
14
- meta: {
15
- title: string
16
- }
17
- path: string
18
- }
19
-
20
- /** 开发环境将 getRouters 转为 folder-alias.json 并写入项目根目录 */
21
- export default function devSaveFolderAlias(root: string): Plugin {
22
- const OUTPUT_FILE = resolve(root, 'folder-alias.json')
23
-
24
- return {
25
- apply: 'serve',
26
- // Vite 对插件 config() 的返回值会做深度合并(mergeConfig)
27
- // 交给 chokidar ignored,避免写入触发 HMR / 整页重载
28
- config() {
29
- return {
30
- server: {
31
- watch: {
32
- ignored: [OUTPUT_FILE_WATCH_IGNORE],
33
- },
34
- },
35
- }
36
- },
37
- configureServer(server) {
38
- server.middlewares.use(ENDPOINT, (req, res, next) => {
39
- void handleSaveFolderAlias(req, res, next, server, OUTPUT_FILE)
40
- })
41
- },
42
- name: 'dev-save-folder-alias',
43
- }
44
- }
45
-
46
- async function handleSaveFolderAlias(
47
- req: IncomingMessage,
48
- res: ServerResponse,
49
- next: Connect.NextFunction,
50
- server: ViteDevServer,
51
- outPutFilePath: string,
52
- ) {
53
- try {
54
- const body = await readBody(req)
55
- const data = JSON.parse(body) as ResRouterItem[]
56
- const content = `${JSON.stringify(toFolderAlias(data), null, 2)}\n`
57
- const resSuccess = () => {
58
- res.statusCode = 200
59
- res.setHeader('Content-Type', 'application/json')
60
- res.end(JSON.stringify({ file: outPutFilePath, ok: true }))
61
- }
62
-
63
- try {
64
- const prev = await fs.readFile(outPutFilePath, 'utf8')
65
-
66
- if (prev === content) {
67
- resSuccess()
68
- return
69
- }
70
- } catch {
71
- // 文件不存在时继续写入
72
- }
73
-
74
- await fs.writeFile(outPutFilePath, content, 'utf8')
75
- server.config.logger.info(`[dev-save-folder-alias] written → ${outPutFilePath}`)
76
- resSuccess()
77
- } catch (error) {
78
- const message = error instanceof Error ? error.message : String(error)
79
-
80
- res.statusCode = 500
81
- res.setHeader('Content-Type', 'application/json')
82
- res.end(JSON.stringify({ message, ok: false }))
83
- server.config.logger.error(`[dev-save-folder-alias] ${message}`)
84
- }
85
- }
86
-
87
- function readBody(req: IncomingMessage): Promise<string> {
88
- return new Promise((resolve, reject) => {
89
- const chunks: string[] = []
90
-
91
- req.setEncoding('utf8')
92
- req.on('data', (chunk: string) => {
93
- chunks.push(chunk)
94
- })
95
- req.on('end', () => {
96
- resolve(chunks.join(''))
97
- })
98
- req.on('error', reject)
99
- })
100
- }
101
-
102
- function toFolderAlias(routers: ResRouterItem[]): FolderAliasMap {
103
- const result: FolderAliasMap = {}
104
- const walk = (items: ResRouterItem[], level = 0) => {
105
- for (const item of items) {
106
- const title = item.meta.title
107
-
108
- if (title !== '') {
109
- const component = item.component
110
-
111
- if (!SKIP_COMPONENTS.has(component)) {
112
- result[`src/views/${component.split('___')[0]}.vue`] = { description: title }
113
-
114
- const arr = component.split('/')
115
-
116
- arr.forEach((_, index) => {
117
- if (index === arr.length - 1) {
118
- return
119
- }
120
-
121
- const key = `src/views/${arr.slice(0, index + 1).join('/')}`
122
- const description = [
123
- ...new Set([result[key]?.description, title].filter(Boolean)),
124
- ].join('、')
125
-
126
- result[key] = {
127
- description:
128
- index === 0
129
- ? (routers.find((r) => r.path === arr[0])?.meta.title ?? description)
130
- : description,
131
- }
132
- })
133
- }
134
- }
135
-
136
- if (item.children !== undefined && item.children.length > 0) {
137
- walk(item.children, level + 1)
138
- }
139
- }
140
- }
141
-
142
- walk(routers)
143
- return result
144
- }
package/index.ts DELETED
@@ -1,309 +0,0 @@
1
- import type * as http from 'node:http'
2
- import type { ConfigEnv, ProxyOptions, UserConfig } from 'vite'
3
- import { posix, resolve } from 'node:path'
4
- import AutoImport from 'unplugin-auto-import/vite'
5
- import ElementPlus from 'unplugin-element-plus/vite'
6
- import Components from 'unplugin-vue-components/vite'
7
- import { loadEnv, mergeConfig } from 'vite'
8
- import { parseLoadedEnv } from 'vite-plugin-env-parse'
9
- import { createHtmlPlugin } from 'vite-plugin-html'
10
- import VueRouter from 'vue-router/vite'
11
- import aliasElementPlus from './aliasElementPlus.ts'
12
- import autoImportStoreList from './autoImportStores.ts'
13
- import baseConfigFn from './commonConfig.ts'
14
- import tDesignAutoImportResolve from './tDesignResolve.ts'
15
- import vitePlugins from './vitePlugins.ts'
16
-
17
- type Arrayable<T> = Array<T> | T
18
- interface Options {
19
- autoImportResolvers?: Array<
20
- UnwrapArrayable<UnwrapArrayable<NonNullable<Parameters<typeof AutoImport>[0]['resolvers']>>>
21
- >
22
- autoImports?: Array<NonNullable<UnwrapArrayable<Parameters<typeof AutoImport>[0]['imports']>>>
23
- root: string // vite.config.ts 的地址
24
- }
25
- type UnwrapArrayable<T> = T extends Arrayable<infer U> ? U : never
26
-
27
- function bypass(
28
- req: http.IncomingMessage,
29
- res: http.ServerResponse | undefined,
30
- options: ProxyOptions,
31
- ): void {
32
- if (
33
- req.url !== undefined &&
34
- options.rewrite !== undefined &&
35
- typeof options.target === 'string' &&
36
- res !== undefined
37
- ) {
38
- const reqUrl = req.url
39
- const proxyUrl = new URL(options.rewrite(reqUrl), options.target).href
40
-
41
- res.setHeader('X-Res-ProxyUrl', proxyUrl) // 查看真实的请求地址
42
- }
43
- }
44
-
45
- function needPort(target: string): boolean {
46
- return target.startsWith('http://192.')
47
- }
48
-
49
- export default (_env: ConfigEnv, options: Options): UserConfig => {
50
- const { command, mode } = _env
51
- const resolvePath = (p: string) => resolve(options.root, p)
52
- const envDir = 'env'
53
- const env = parseLoadedEnv(loadEnv(mode, envDir)) as {
54
- VITE_API_PROXY_PORT_ARRAY: Array<[string, number]>
55
- VITE_APP_ID: string
56
- VITE_APP_NAME?: string
57
- VITE_BASE_URL?: string
58
- VITE_FORCE_PWD_CHANGE?: boolean
59
- VITE_PROXY_TARGET: string | string[]
60
- VITE_USE_LOGIN_CAPTCHA?: boolean
61
- }
62
- const {
63
- VITE_API_PROXY_PORT_ARRAY,
64
- VITE_APP_ID,
65
- VITE_APP_NAME = '',
66
- VITE_BASE_URL = '/',
67
- VITE_FORCE_PWD_CHANGE = true,
68
- VITE_PROXY_TARGET: viteProxyTarget,
69
- VITE_USE_LOGIN_CAPTCHA = true,
70
- } = env
71
- const VITE_PROXY_TARGET = Array.isArray(viteProxyTarget) ? viteProxyTarget : [viteProxyTarget]
72
-
73
- console.log({
74
- command,
75
- mode,
76
- VITE_API_PROXY_PORT_ARRAY,
77
- VITE_APP_ID,
78
- VITE_APP_NAME,
79
- VITE_BASE_URL,
80
- VITE_FORCE_PWD_CHANGE,
81
- VITE_PROXY_TARGET,
82
- VITE_USE_LOGIN_CAPTCHA,
83
- })
84
-
85
- const isProduction = mode === 'production'
86
- const getProxyTarget = (index: number, port: number) => {
87
- const target = VITE_PROXY_TARGET.length > 1 ? VITE_PROXY_TARGET[index] : VITE_PROXY_TARGET[0]
88
-
89
- return needPort(target) ? `${target}:${port}` : target
90
- }
91
-
92
- return mergeConfig(
93
- baseConfigFn({
94
- tailwindAutoReferenceEntry: 'node_modules/dlzn-ui/assets/css/tailwindcss-entry.css',
95
- }),
96
- {
97
- build: {
98
- rolldownOptions: {
99
- output: {
100
- minify: {
101
- codegen: true, //
102
- compress: {
103
- dropConsole: true, // 默认 false
104
- // dropDebugger: true, // 默认 true
105
- },
106
- mangle: true, // 变量名混淆
107
- },
108
- },
109
- },
110
- },
111
- define: {
112
- VITE_API_PREFIX_ARRAY: JSON.stringify(VITE_API_PROXY_PORT_ARRAY.map(([prefix]) => prefix)),
113
- VITE_APP_ID: JSON.stringify(VITE_APP_ID),
114
- VITE_APP_NAME: JSON.stringify(VITE_APP_NAME),
115
- VITE_BASE_URL: JSON.stringify(VITE_BASE_URL),
116
- VITE_FORCE_PWD_CHANGE: JSON.stringify(VITE_FORCE_PWD_CHANGE),
117
- VITE_USE_LOGIN_CAPTCHA: JSON.stringify(VITE_USE_LOGIN_CAPTCHA),
118
- },
119
- // envDir, // 将 env 文件里面的变量注入到 import.meta.env 里面
120
- optimizeDeps: {
121
- include: [
122
- 'tdesign-vue-next/dist/tdesign.min.js',
123
- 'path-browserify',
124
- 'lodash-es',
125
- 'pinia-plugin-persistedstate',
126
- 'alova',
127
- 'alova/fetch',
128
- 'alova/vue',
129
- '@iconify/vue',
130
- '@formkit/auto-animate',
131
- '@formkit/auto-animate/vue',
132
- 'dayjs',
133
- 'dayjs/plugin/customParseFormat.js',
134
- 'dayjs/plugin/isSameOrBefore.js',
135
- 'dayjs/plugin/timezone.js',
136
- 'dayjs/plugin/utc.js',
137
- 'wordcloud',
138
- 'echarts/charts',
139
- 'echarts/components',
140
- 'echarts/core',
141
- 'echarts/renderers',
142
- '@tdesign-vue-next/chat',
143
- 'vue-echarts',
144
- 'dompurify',
145
- 'cron-parser',
146
- 'cronstrue',
147
- 'cronstrue/locales/zh_CN',
148
- 'quartzcron',
149
- '@bprogress/core',
150
- 'element-plus',
151
- 'element-plus/es/components/config-provider/style/css',
152
- 'element-plus/es/locale/lang/zh-cn',
153
- 'element-plus/es/components/date-picker/style/css',
154
- 'element-plus/es/components/scrollbar/style/css',
155
- 'color',
156
- 'dlzn-ui',
157
- ],
158
- },
159
- plugins: [
160
- // envParse({
161
- // dtsPath: 'types/env.d.ts',
162
- // }),
163
- createHtmlPlugin({
164
- entry: `/src/main.${isProduction ? 'prod' : 'dev'}.ts`, // 必须绝对路径,否则类似system/log/operlog 二级页面打不开
165
- inject: {
166
- data: {
167
- appId: VITE_APP_ID,
168
- mode: isProduction ? 'prod' : 'dev',
169
- title: VITE_APP_NAME,
170
- },
171
- ejsOptions: {
172
- views: ['node_modules/dlzn-ui/ejs'],
173
- },
174
- },
175
- minify: true,
176
- // 相对消费方 root,closeBundle 整理 HTML 时比绝对路径更稳
177
- template: 'node_modules/dlzn-ui/index.html',
178
- }),
179
- VueRouter({
180
- dts: 'types/typed-router.d.ts',
181
- }),
182
- ElementPlus({}),
183
- AutoImport({
184
- // 用于自动导入 函数/工具库 的 API
185
- // function modifyDefaultExportsAlias(imports, options) {
186
- // if (options.defaultExportByFilename) imports.forEach((i) => {
187
- // if (i.name === "default") i.as = i.from.split("/").pop()?.split(".")?.shift() ?? i.as;
188
- // });
189
- // return imports;
190
- // }
191
- // defaultExportByFilename: false, // 默认为 false
192
- dirs: ['src/plugins/autoImport', 'src/bus/autoImport', 'src/hooks'],
193
- dirsScanOptions: {
194
- types: false, // Enable auto import the types under the directories
195
- },
196
- dts: 'types/auto-imports.d.ts',
197
- // dtsMode: 'overwrite', // overwrite the whole existing .d.ts file with the new type definitions.
198
- imports: [
199
- 'vue',
200
- 'vue-router',
201
- 'pinia',
202
- '@vueuse/core',
203
- {
204
- from: 'alova/client',
205
- imports: ['useRequest', 'useWatcher', 'usePagination'],
206
- },
207
- {
208
- from: '@/plugins/others/directive.ts',
209
- imports: ['checkPermissions'],
210
- },
211
- {
212
- from: 'dlzn-ui/utils',
213
- imports: ['formatNumber', 'isFalsy', 'stringDisplay'],
214
- },
215
- {
216
- '@/plugins/alova/index.ts': [['default', 'alovaInst']],
217
- },
218
- {
219
- from: '@/components/tDesignReset/TForm/index.ts',
220
- imports: ['FormItem', 'FormInstance', 'FormExposed'],
221
- type: true,
222
- },
223
- {
224
- from: '@/components/tDesignReset/TTable/index.ts',
225
- imports: ['TableCol', 'CellRenderContext'],
226
- type: true,
227
- },
228
- {
229
- from: '@/components/autoImport/TPageList/index.ts',
230
- imports: ['PageListProps'],
231
- type: true,
232
- },
233
- autoImportStoreList(options.root),
234
- ...(options.autoImports ?? []),
235
- ],
236
- resolvers: [
237
- ...(options.autoImportResolvers ?? []),
238
- ...tDesignAutoImportResolve({
239
- isProduction,
240
- root: options.root,
241
- }),
242
- ],
243
- vueTemplate: true, // 允许插件扫描 Vue 文件的 <template> 部分,并自动导入在模板表达式中使用的 API
244
- }),
245
- Components({
246
- deep: false,
247
- // 用于自动导入 Vue 组件
248
- dts: 'types/components.d.ts',
249
- resolvers: [
250
- ...(options.autoImportResolvers ?? []),
251
- ...tDesignAutoImportResolve({
252
- isProduction,
253
- root: options.root,
254
- }),
255
- ],
256
- // syncMode: 'overwrite',
257
- }),
258
- ...vitePlugins({ isProduction, root: options.root }),
259
- ],
260
- resolve: {
261
- alias: [
262
- {
263
- find: '@',
264
- replacement: resolvePath('src'), // 使用绝对路径(官方推荐)
265
- },
266
- {
267
- find: 'img', // 路径以 img 开头
268
- replacement: resolvePath('src/assets/images'),
269
- },
270
- ...(isProduction
271
- ? []
272
- : [
273
- {
274
- // find 为正则时只替换匹配段,必须用 ^...$ 匹配完整 id
275
- // 同时覆盖裸导入与已 resolve 的绝对路径
276
- find: /^.*tdesign-vue-next[/\\]es[/\\].*\.css$/,
277
- replacement: resolvePath('src/plugins/tdesign-vue-next-for-dev/empty.css'),
278
- },
279
- ]),
280
- ...aliasElementPlus(options.root),
281
- ],
282
- // https://cn.vitejs.dev/guide/performance.html#reduce-resolve-operations
283
- // 不建议忽略自定义导入类型的扩展名(例如:.vue),因为它会影响 IDE 和类型支持。
284
- extensions: ['.ts', '.mjs', '.js'], // js 和 mjs 打包chat包时需要
285
- },
286
- root: options.root,
287
- server: {
288
- // vite preview 也会走该代理
289
- host: '0.0.0.0', // 可以用ip访问
290
- open: false,
291
- port: VITE_API_PROXY_PORT_ARRAY[0][1] + 1000,
292
- proxy: Object.fromEntries(
293
- VITE_API_PROXY_PORT_ARRAY.map(([prefix, port], index) => [
294
- `${posix.join(VITE_BASE_URL, prefix)}/`,
295
- {
296
- bypass,
297
- changeOrigin: true,
298
- rewrite: (p) => {
299
- return VITE_BASE_URL === '/' ? p : p.replace(new RegExp(VITE_BASE_URL), '')
300
- },
301
- target: getProxyTarget(index, port),
302
- },
303
- ]),
304
- ),
305
- strictPort: true,
306
- },
307
- } satisfies UserConfig,
308
- )
309
- }
package/tDesignResolve.ts DELETED
@@ -1,105 +0,0 @@
1
- import type AutoImport from 'unplugin-auto-import/vite'
2
- import path from 'node:path'
3
- import { TDesignResolver } from '@tdesign-vue-next/auto-import-resolver'
4
- import { globSync } from 'tinyglobby'
5
-
6
- export default (options: { isProduction: boolean; root: string }) => {
7
- const { isProduction, root } = options
8
- const tDesignResetComponentsSubFolderFiles = globSync('src/components/tDesignReset/*/Index.vue', {
9
- cwd: root,
10
- })
11
- const tDesignResetComponentsSubFolderName = tDesignResetComponentsSubFolderFiles.map((file) => {
12
- return path.basename(path.dirname(file))
13
- })
14
- const autoImportComponentsSubFolderFiles = globSync('src/components/autoImport/*/Index.vue', {
15
- cwd: root,
16
- })
17
- const autoImportComponentsSubFolderName = autoImportComponentsSubFolderFiles.map((file) => {
18
- return path.basename(path.dirname(file))
19
- })
20
-
21
- return [
22
- {
23
- resolve: (name: string) => {
24
- if (['TCard'].includes(name)) {
25
- return {
26
- from: 'dlzn-ui',
27
- name,
28
- }
29
- }
30
-
31
- if (
32
- ['Icon', 'TBaseTable', 'TDateRangePicker', 'TEnhancedTable', 'TPrimaryTable'].includes(
33
- name,
34
- )
35
- ) {
36
- return
37
- }
38
-
39
- if (tDesignResetComponentsSubFolderName.includes(name)) {
40
- return {
41
- from: `@/components/tDesignReset/${name}/Index.vue`,
42
- name: 'default',
43
- }
44
- }
45
-
46
- if (autoImportComponentsSubFolderName.includes(name)) {
47
- return {
48
- from: `@/components/autoImport/${name}/Index.vue`,
49
- name: 'default',
50
- }
51
- }
52
-
53
- // const xxx = _${compo} 自动导入
54
- if (
55
- tDesignResetComponentsSubFolderName
56
- .map((n) => {
57
- const sliceName = n.slice(1)
58
-
59
- return `_${sliceName === 'Table' ? 'EnhancedTable' : sliceName}`
60
- })
61
- .includes(name)
62
- ) {
63
- return {
64
- as: name,
65
- from: isProduction ? 'tdesign-vue-next' : '@/plugins/tdesign-vue-next-for-dev',
66
- name: name.slice(1),
67
- }
68
- }
69
-
70
- const result = (
71
- TDesignResolver({
72
- library: 'vue-next',
73
- resolveIcons: false, // 禁用 https://tdesign.tencent.com/icons TDesign 图标独立站点 的图标
74
- }) as {
75
- resolve: (name: string) =>
76
- | undefined
77
- | {
78
- from: string
79
- name: string
80
- }
81
- }
82
- ).resolve(name)
83
-
84
- if (result !== undefined) {
85
- return {
86
- from: isProduction ? result.from : '@/plugins/tdesign-vue-next-for-dev',
87
- name: result.name,
88
- }
89
- }
90
- },
91
- type: 'component',
92
- },
93
- {
94
- resolve: (name: string) => {
95
- if (name === 'Loading') {
96
- return {
97
- from: isProduction ? 'tdesign-vue-next' : '@/plugins/tdesign-vue-next-for-dev',
98
- name: 'LoadingDirective',
99
- }
100
- }
101
- },
102
- type: 'directive',
103
- },
104
- ] satisfies Parameters<typeof AutoImport>[0]['resolvers']
105
- }
package/vitePlugins.ts DELETED
@@ -1,82 +0,0 @@
1
- import type { Plugin } from 'vite'
2
- import { webUpdateNotice } from '@plugin-web-update-notification/vite'
3
- import { visualizer } from 'rollup-plugin-visualizer'
4
- import { compression } from 'vite-plugin-compression2'
5
- import viteImagemin from 'vite-plugin-imagemin'
6
- // import vueDevTools from 'vite-plugin-vue-devtools'
7
- import devSaveFolderAlias from './devSaveFolderAlias.ts'
8
-
9
- export default (options: { isProduction: boolean; root: string }): Plugin[] => {
10
- const { isProduction, root } = options
11
-
12
- if (isProduction) {
13
- return [
14
- (viteImagemin as unknown as typeof viteImagemin.default)({
15
- gifsicle: {
16
- // https://github.com/imagemin/imagemin-gifsicle
17
- colors: 256, // 指定 GIF 图像调色板(颜色表)的最大颜色数量, 可丢弃一些颜色达到更大的优化效果
18
- interlaced: false, // 渐进式加载效果
19
- optimizationLevel: 2, // 中的优化级别
20
- },
21
- mozjpeg: {
22
- quality: 50, // 图片质量(0-100)
23
- },
24
- optipng: {
25
- optimizationLevel: 3, // 压缩过程中尝试的优化策略和强度(0-7)
26
- },
27
- pngquant: {
28
- quality: [0.65, 0.8], // 压缩后的图片质量范围[最小, 最大]
29
- speed: 4,
30
- },
31
- svgo: {
32
- datauri: 'base64', // 'base64'|'enc'|'unenc' 指定如何将 SVG 转换为 Data URI 格式
33
- js2svg: {
34
- // 控制 SVG 输出的格式
35
- indent: 4, // 缩进空格数
36
- pretty: false, // 是否美化输出格式
37
- },
38
- multipass: false, // 是否启用多遍优化: false 表示只进行单遍优化,true 会重复优化直到无法进一步优化, 设置为 true 的话可能优化的更大
39
- plugins: [
40
- {
41
- name: 'preset-default',
42
- },
43
- ],
44
- },
45
- webp: {
46
- quality: 80, // 图片质量(0-100)
47
- },
48
- }),
49
- compression(),
50
- visualizer({
51
- filename: 'node_modules/.cache/visualizer/report.html',
52
- open: true,
53
- }),
54
- webUpdateNotice({
55
- hiddenDefaultNotification: true,
56
- logVersion: false,
57
- }),
58
- ] as Plugin[]
59
- } else {
60
- return [
61
- // vueDevTools()
62
- {
63
- configureServer(server) {
64
- const { printUrls } = server
65
-
66
- server.printUrls = () => {
67
- if (server.resolvedUrls !== null) {
68
- server.resolvedUrls.local = []
69
- server.resolvedUrls.network = server.resolvedUrls.network.filter((url) =>
70
- url.includes('192.168.'),
71
- )
72
- }
73
-
74
- printUrls()
75
- }
76
- },
77
- name: 'filter-vite-server-urls',
78
- },
79
- devSaveFolderAlias(root),
80
- ]
81
- }
82
- }