提交 | 用户 | 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 };