提交 | 用户 | age
|
6890dd
|
1 |
import colors from 'picocolors'; |
V |
2 |
import { readPackageJSON } from 'pkg-types'; |
5e9946
|
3 |
import { type PluginOption } from 'vite'; |
6890dd
|
4 |
|
5e9946
|
5 |
import { getEnvConfig } from '../utils/env'; |
V |
6 |
import { createContentHash } from '../utils/hash'; |
|
7 |
|
|
8 |
const GLOBAL_CONFIG_FILE_NAME = '_app.config.js'; |
|
9 |
const PLUGIN_NAME = 'app-config'; |
|
10 |
|
|
11 |
async function createAppConfigPlugin({ |
|
12 |
root, |
|
13 |
isBuild, |
|
14 |
}: { |
|
15 |
root: string; |
|
16 |
isBuild: boolean; |
|
17 |
}): Promise<PluginOption> { |
|
18 |
let publicPath: string; |
|
19 |
let source: string; |
|
20 |
if (!isBuild) { |
|
21 |
return { |
|
22 |
name: PLUGIN_NAME, |
|
23 |
}; |
|
24 |
} |
|
25 |
const { version = '' } = await readPackageJSON(root); |
|
26 |
|
|
27 |
return { |
|
28 |
name: PLUGIN_NAME, |
|
29 |
async configResolved(_config) { |
aedb8e
|
30 |
let appTitle = _config?.env?.VITE_GLOB_APP_TITLE ?? ''; |
0347c8
|
31 |
appTitle = appTitle.replace(/\s/g, '_').replace(/-/g, '_'); |
5e9946
|
32 |
publicPath = _config.base; |
V |
33 |
source = await getConfigSource(appTitle); |
|
34 |
}, |
|
35 |
async transformIndexHtml(html) { |
|
36 |
publicPath = publicPath.endsWith('/') ? publicPath : `${publicPath}/`; |
|
37 |
|
|
38 |
const appConfigSrc = `${ |
|
39 |
publicPath || '/' |
7e0456
|
40 |
}${GLOBAL_CONFIG_FILE_NAME}?v=${version}-${createContentHash(source)}`; |
5e9946
|
41 |
|
V |
42 |
return { |
|
43 |
html, |
|
44 |
tags: [ |
|
45 |
{ |
|
46 |
tag: 'script', |
|
47 |
attrs: { |
|
48 |
src: appConfigSrc, |
|
49 |
}, |
|
50 |
}, |
|
51 |
], |
|
52 |
}; |
|
53 |
}, |
|
54 |
async generateBundle() { |
|
55 |
try { |
|
56 |
this.emitFile({ |
|
57 |
type: 'asset', |
|
58 |
fileName: GLOBAL_CONFIG_FILE_NAME, |
|
59 |
source, |
|
60 |
}); |
|
61 |
|
|
62 |
console.log(colors.cyan(`✨configuration file is build successfully!`)); |
|
63 |
} catch (error) { |
|
64 |
console.log( |
|
65 |
colors.red('configuration file configuration file failed to package:\n' + error), |
|
66 |
); |
|
67 |
} |
|
68 |
}, |
|
69 |
}; |
|
70 |
} |
|
71 |
|
|
72 |
/** |
|
73 |
* Get the configuration file variable name |
|
74 |
* @param env |
|
75 |
*/ |
|
76 |
const getVariableName = (title: string) => { |
a4e70b
|
77 |
function strToHex(str: string) { |
L |
78 |
const result: string[] = []; |
|
79 |
for (let i = 0; i < str.length; ++i) { |
|
80 |
const hex = str.charCodeAt(i).toString(16); |
|
81 |
result.push(('000' + hex).slice(-4)); |
|
82 |
} |
|
83 |
return result.join('').toUpperCase(); |
|
84 |
} |
|
85 |
|
|
86 |
return `__PRODUCTION__${strToHex(title) || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, ''); |
5e9946
|
87 |
}; |
V |
88 |
|
|
89 |
async function getConfigSource(appTitle: string) { |
|
90 |
const config = await getEnvConfig(); |
|
91 |
const variableName = getVariableName(appTitle); |
|
92 |
const windowVariable = `window.${variableName}`; |
|
93 |
// Ensure that the variable will not be modified |
|
94 |
let source = `${windowVariable}=${JSON.stringify(config)};`; |
|
95 |
source += ` |
|
96 |
Object.freeze(${windowVariable}); |
|
97 |
Object.defineProperty(window, "${variableName}", { |
|
98 |
configurable: false, |
|
99 |
writable: false, |
|
100 |
}); |
|
101 |
`.replace(/\s/g, ''); |
|
102 |
return source; |
|
103 |
} |
|
104 |
|
|
105 |
export { createAppConfigPlugin }; |