|
@@ -1,31 +1,104 @@
|
|
|
-import GenerateConfig from 'unplugin-config/vite';
|
|
|
+import colors from 'picocolors';
|
|
|
+import { readPackageJSON } from 'pkg-types';
|
|
|
import { type PluginOption } from 'vite';
|
|
|
|
|
|
import { getEnvConfig } from '../utils/env';
|
|
|
-import { strToHex } from '../utils/hash';
|
|
|
+import { createContentHash } from '../utils/hash';
|
|
|
|
|
|
const GLOBAL_CONFIG_FILE_NAME = '_app.config.js';
|
|
|
-
|
|
|
-const OUTPUT_DIR = 'dist';
|
|
|
-export async function createConfigPluginConfig(
|
|
|
- shouldGenerateConfig: boolean,
|
|
|
-): Promise<PluginOption> {
|
|
|
- const config = await getEnvConfig();
|
|
|
-
|
|
|
- const APP_NAME = strToHex(config?.VITE_GLOB_APP_TITLE ?? '__APP');
|
|
|
-
|
|
|
- return GenerateConfig({
|
|
|
- appName: APP_NAME,
|
|
|
- envVariables: {
|
|
|
- prefix: 'VITE_GLOB_',
|
|
|
+const PLUGIN_NAME = 'app-config';
|
|
|
+
|
|
|
+async function createAppConfigPlugin({
|
|
|
+ root,
|
|
|
+ isBuild,
|
|
|
+}: {
|
|
|
+ root: string;
|
|
|
+ isBuild: boolean;
|
|
|
+}): Promise<PluginOption> {
|
|
|
+ let publicPath: string;
|
|
|
+ let source: string;
|
|
|
+ if (!isBuild) {
|
|
|
+ return {
|
|
|
+ name: PLUGIN_NAME,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ const { version = '' } = await readPackageJSON(root);
|
|
|
+
|
|
|
+ return {
|
|
|
+ name: PLUGIN_NAME,
|
|
|
+ async configResolved(_config) {
|
|
|
+ const appTitle = _config?.env?.VITE_GLOB_APP_TITLE ?? '';
|
|
|
+
|
|
|
+ publicPath = _config.base;
|
|
|
+ source = await getConfigSource(appTitle);
|
|
|
},
|
|
|
- configFile: {
|
|
|
- generate: shouldGenerateConfig,
|
|
|
- fileName: GLOBAL_CONFIG_FILE_NAME,
|
|
|
- outputDir: OUTPUT_DIR,
|
|
|
+ async transformIndexHtml(html) {
|
|
|
+ publicPath = publicPath.endsWith('/') ? publicPath : `${publicPath}/`;
|
|
|
+
|
|
|
+ const appConfigSrc = `${
|
|
|
+ publicPath || '/'
|
|
|
+ }${GLOBAL_CONFIG_FILE_NAME}?v=${version}-${createContentHash(source)}`;
|
|
|
+
|
|
|
+ return {
|
|
|
+ html,
|
|
|
+ tags: [
|
|
|
+ {
|
|
|
+ tag: 'script',
|
|
|
+ attrs: {
|
|
|
+ src: appConfigSrc,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ };
|
|
|
},
|
|
|
- htmlInjection: {
|
|
|
- decodeEntities: true,
|
|
|
+ async generateBundle() {
|
|
|
+ try {
|
|
|
+ this.emitFile({
|
|
|
+ type: 'asset',
|
|
|
+ fileName: GLOBAL_CONFIG_FILE_NAME,
|
|
|
+ source,
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log(colors.cyan(`✨configuration file is build successfully!`));
|
|
|
+ } catch (error) {
|
|
|
+ console.log(
|
|
|
+ colors.red('configuration file configuration file failed to package:\n' + error),
|
|
|
+ );
|
|
|
+ }
|
|
|
},
|
|
|
- });
|
|
|
+ };
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ * Get the configuration file variable name
|
|
|
+ * @param env
|
|
|
+ */
|
|
|
+const getVariableName = (title: string) => {
|
|
|
+ function strToHex(str: string) {
|
|
|
+ const result: string[] = [];
|
|
|
+ for (let i = 0; i < str.length; ++i) {
|
|
|
+ const hex = str.charCodeAt(i).toString(16);
|
|
|
+ result.push(('000' + hex).slice(-4));
|
|
|
+ }
|
|
|
+ return result.join('').toUpperCase();
|
|
|
+ }
|
|
|
+ return `__PRODUCTION__${strToHex(title) || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, '');
|
|
|
+};
|
|
|
+
|
|
|
+async function getConfigSource(appTitle: string) {
|
|
|
+ const config = await getEnvConfig();
|
|
|
+ const variableName = getVariableName(appTitle);
|
|
|
+ const windowVariable = `window.${variableName}`;
|
|
|
+
|
|
|
+ let source = `${windowVariable}=${JSON.stringify(config)};`;
|
|
|
+ source += `
|
|
|
+ Object.freeze(${windowVariable});
|
|
|
+ Object.defineProperty(window, "${variableName}", {
|
|
|
+ configurable: false,
|
|
|
+ writable: false,
|
|
|
+ });
|
|
|
+ `.replace(/\s/g, '');
|
|
|
+ return source;
|
|
|
+}
|
|
|
+
|
|
|
+export { createAppConfigPlugin };
|