完善架构,修改很多地方
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vite-plugin-nacos",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.3",
|
||||
"description": "Vite 插件,实现Nacos服务注册与发现插件,用于模块联邦",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@@ -8,17 +8,18 @@
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc -w",
|
||||
"prepublishOnly": "npm run build"
|
||||
"build": "tsc",
|
||||
"prepublishOnly": "npm run build",
|
||||
"push": "npm run build && npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "^5.6.2",
|
||||
"nacos": "^2.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.5.2",
|
||||
"typescript": "~5.8.3",
|
||||
"vite": "^7.1.6"
|
||||
"@types/node": "^24.6.1",
|
||||
"typescript": "~5.9.3",
|
||||
"vite": "^7.1.7"
|
||||
},
|
||||
"keywords": [
|
||||
"nacos",
|
||||
@@ -27,4 +28,4 @@
|
||||
],
|
||||
"author": "",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@@ -1,56 +1,96 @@
|
||||
// 从插件实现文件导入
|
||||
export * from './vite-plugin-nacos';
|
||||
export * from './utils';
|
||||
import { log } from 'console';
|
||||
import { nacosServiceManage } from './nacosServiceManage';
|
||||
import { mergeConfig } from 'vite';
|
||||
|
||||
export const init = async (env: Record<string, string>) => {
|
||||
const nacos = await nacosServiceManage.create({
|
||||
serverList: env.VITE_NACOS_ADDRESS,
|
||||
serviceName: env.VITE_SERVER_NAME,
|
||||
port: Number(env.VITE_SERVER_PORT)
|
||||
});
|
||||
const serverList = env.VITE_NACOS_ADDRESS;
|
||||
const serviceName = env.VITE_SERVER_NAME;
|
||||
const port = Number(env.VITE_SERVER_PORT);
|
||||
|
||||
if (env.VITE_SERVER_NAME === "main-app") {
|
||||
log("不需要服务发现,进行配置发现...")
|
||||
|
||||
const baseUrl = await nacos.getConfig("baseUrl", "DEFAULT_GROUP")
|
||||
const baseUrlConfig = baseUrl ? JSON.parse(baseUrl) : {};
|
||||
baseUrlConfig.httpTimeOut = await nacos.getConfig("httpTimeOut", "DEFAULT_GROUP")
|
||||
|
||||
// 将新配置处理一下,需要 JSON.stringify
|
||||
const customizeEnv: Record<string, Record<string, string>> = { define: {} };
|
||||
Object.keys(baseUrlConfig).forEach(key => {
|
||||
customizeEnv.define[`import.meta.env.VITE_${key.toUpperCase()}`] = JSON.stringify(baseUrlConfig[key]);
|
||||
});
|
||||
|
||||
// 将老配置处理一下,需要 JSON.stringify
|
||||
const existingDefine: Record<string, Record<string, string>> = { define: {} }
|
||||
Object.keys(env).forEach(key => {
|
||||
existingDefine.define[`import.meta.env.${key}`] = JSON.stringify(env[key])
|
||||
})
|
||||
|
||||
return mergeConfig(existingDefine, customizeEnv)
|
||||
|
||||
} else {
|
||||
log("进行服务发现,获取依赖模块的地址...")
|
||||
let modelName = []
|
||||
for (const key in env) {
|
||||
if (key.includes("VITE_MODEL_")) modelName.push(env[key])
|
||||
}
|
||||
|
||||
const modelUrl: Record<string, string> = {}
|
||||
|
||||
if (modelName.length !== 0) {
|
||||
for (const val of modelName) modelUrl[`VITE_MODEL_${val.replace("app-", "").toUpperCase()}_URL`] = await nacos.find(val)
|
||||
}
|
||||
|
||||
log("modelUrl: ", modelUrl)
|
||||
return modelUrl
|
||||
if (!serverList || !serviceName || Number.isNaN(port)) {
|
||||
throw new Error('[vite-plugin-nacos] 缺少必要环境变量:VITE_NACOS_ADDRESS / VITE_SERVER_NAME / VITE_SERVER_PORT');
|
||||
}
|
||||
|
||||
const nacos = await nacosServiceManage.create({
|
||||
serverList,
|
||||
serviceName,
|
||||
port
|
||||
});
|
||||
|
||||
const isMain = serviceName === 'main-app';
|
||||
|
||||
if (isMain) {
|
||||
console.log('[vite-plugin-nacos] 不需要服务发现,进行配置发现...');
|
||||
|
||||
// 并发获取配置并稳健解析
|
||||
const [baseUrlRaw, httpTimeOut] = await Promise.all([
|
||||
nacos.getConfig('baseUrl', 'DEFAULT_GROUP'),
|
||||
nacos.getConfig('httpTimeOut', 'DEFAULT_GROUP')
|
||||
]);
|
||||
|
||||
let baseUrlConfig: Record<string, any> = {};
|
||||
if (baseUrlRaw) {
|
||||
try {
|
||||
baseUrlConfig = JSON.parse(baseUrlRaw);
|
||||
} catch (e) {
|
||||
console.warn('[vite-plugin-nacos] baseUrl 配置不是有效 JSON,忽略解析,使用空对象');
|
||||
baseUrlConfig = {};
|
||||
}
|
||||
}
|
||||
if (typeof httpTimeOut !== 'undefined' && httpTimeOut !== null) {
|
||||
baseUrlConfig.httpTimeOut = httpTimeOut;
|
||||
}
|
||||
|
||||
// 将新配置处理成 define,需要 JSON.stringify
|
||||
const customizeEnv = Object.keys(baseUrlConfig).reduce<Record<string, string>>((acc, key) => {
|
||||
acc[`import.meta.env.VITE_${key.toUpperCase()}`] = JSON.stringify(baseUrlConfig[key]);
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// 将现有 env 处理成 define,需要 JSON.stringify
|
||||
const existingDefine = Object.keys(env).reduce<Record<string, string>>((acc, key) => {
|
||||
acc[`import.meta.env.${key}`] = JSON.stringify(env[key]);
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// 使用 mergeConfig 合并 define 字段
|
||||
const merged = mergeConfig({ define: existingDefine }, { define: customizeEnv });
|
||||
|
||||
await closeAllNacos(serviceName);
|
||||
return merged;
|
||||
}
|
||||
|
||||
// 非主模块:进行服务发现
|
||||
console.log('[vite-plugin-nacos] 进行 配置发现,获取依赖模块的地址...');
|
||||
const modelNames: string[] = [];
|
||||
for (const key in env) {
|
||||
if (key.includes('VITE_MODEL_') && env[key]) {
|
||||
modelNames.push(env[key]);
|
||||
}
|
||||
}
|
||||
|
||||
// 去重
|
||||
const uniqueModelNames = Array.from(new Set(modelNames));
|
||||
const modelUrl: Record<string, string> = {};
|
||||
|
||||
|
||||
if (uniqueModelNames.length > 0) {
|
||||
const results = await Promise.all(uniqueModelNames.map(async (val) => {
|
||||
const url = await nacos.getConfig(val, 'DEFAULT_GROUP');
|
||||
const envKey = `VITE_MODEL_${val.replace('app-', '').toUpperCase()}_URL`;
|
||||
return [envKey, url] as const;
|
||||
}));
|
||||
for (const [k, v] of results) modelUrl[k] = v;
|
||||
}
|
||||
|
||||
}
|
||||
console.log('[vite-plugin-nacos] modelUrl: ', modelUrl);
|
||||
await closeAllNacos("other-model");
|
||||
return modelUrl;
|
||||
}
|
||||
|
||||
/** 手动关闭所有 Nacos 客户端(提供给外部在需要时调用) */
|
||||
export async function closeAllNacos(serviceName: string) {
|
||||
await nacosServiceManage.destroyAll();
|
||||
}
|
||||
|
||||
@@ -37,12 +37,12 @@ export class nacosServiceManage {
|
||||
const configKey = this.getConfigKey(option);
|
||||
|
||||
if (this.instanceMap.has(configKey)) {
|
||||
logger.log(`[nacos-federation] 已存在 ${ option.serviceName } 的Nacos实例,直接复用`);
|
||||
logger.log(`[nacos-federation] 已存在 ${option.serviceName} 的Nacos实例,直接复用`);
|
||||
return this.instanceMap.get(configKey)!;
|
||||
}
|
||||
|
||||
const instance = new nacosServiceManage(option);
|
||||
await instance.initClient();
|
||||
// await instance.initClient();
|
||||
await instance.initConfig();
|
||||
|
||||
this.instanceMap.set(configKey, instance);
|
||||
@@ -65,7 +65,7 @@ export class nacosServiceManage {
|
||||
*/
|
||||
private static getConfigKey(option: RegisterOptions): string {
|
||||
const namespace = option.namespace || 'public';
|
||||
return `${ option.serverList }-${ namespace }-${ option.serviceName }`;
|
||||
return `${option.serverList}-${namespace}-${option.serviceName}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +90,7 @@ export class nacosServiceManage {
|
||||
async getConfig(dataId: string, group: string = "DEFAULT_GROUP") {
|
||||
const res = await this.configClient.getConfig(dataId, group)
|
||||
console.log()
|
||||
console.log(`${ chalk.blue('[nacos-cluster-federation] 配置发现:') }\n ${ chalk.green('➜') } ${ chalk.green(dataId) } 的配置为: ${ chalk.green(res) }`)
|
||||
console.log(`${chalk.blue('[nacos-cluster-federation] 配置发现:')}\n ${chalk.green('➜')} ${chalk.green(dataId)} 的配置为: ${chalk.green(res)}`)
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ export class nacosServiceManage {
|
||||
const instances = await this.nacosClient.getAllInstances(serviceName);
|
||||
// console.log("instances: ", instances);
|
||||
if (instances.length === 0) {
|
||||
throw new Error(`[nacos-federation] 未发现服务 ${ serviceName } 的实例`);
|
||||
throw new Error(`[nacos-federation] 未发现服务 ${serviceName} 的实例`);
|
||||
}
|
||||
return formatServiceUrl(instances[0].ip, instances[0].port);
|
||||
}
|
||||
@@ -128,7 +128,7 @@ export class nacosServiceManage {
|
||||
await this.nacosClient.registerInstance(serviceName, { port, ip })
|
||||
logger.log()
|
||||
logger.log(chalk.blue("[nacos-cluster-federation] 服务注册:"))
|
||||
logger.log(` ${ chalk.green('➜') } ${ chalk.green(serviceName) } (${ formatServiceUrl(ip, port) }) 已注册到配置中心!`);
|
||||
logger.log(` ${chalk.green('➜')} ${chalk.green(serviceName)} (${formatServiceUrl(ip, port)}) 已注册到配置中心!`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,16 +136,44 @@ export class nacosServiceManage {
|
||||
*/
|
||||
public async destroy() {
|
||||
const configKey = nacosServiceManage.getConfigKey(this.initOptions);
|
||||
// 注销Nacos服务实例
|
||||
const { serviceName, port } = this.initOptions;
|
||||
const ip = getLocalIP();
|
||||
// @ts-ignore
|
||||
await this.nacosClient.deregisterInstance(serviceName, { ip, port });
|
||||
logger.log(`[nacos-federation] 服务 ${ serviceName } 已从Nacos注销`);
|
||||
// 注销 Nacos 命名客户端(如已初始化)
|
||||
try {
|
||||
if (this.nacosClient) {
|
||||
const { serviceName, port } = this.initOptions;
|
||||
const ip = getLocalIP();
|
||||
// @ts-ignore
|
||||
await this.nacosClient.deregisterInstance(serviceName, { ip, port });
|
||||
// @ts-ignore
|
||||
if (typeof this.nacosClient.close === 'function') {
|
||||
// @ts-ignore
|
||||
await this.nacosClient.close();
|
||||
}
|
||||
logger.log(`[nacos-federation] 服务 ${serviceName} 已从Nacos注销`);
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn('[nacos-federation] deregister warn:', e);
|
||||
}
|
||||
|
||||
// 关闭配置客户端(如已初始化)
|
||||
try {
|
||||
if (this.configClient && typeof (this.configClient as any).close === 'function') {
|
||||
await (this.configClient as any).close();
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn('[nacos-federation] configClient close warn:', e);
|
||||
}
|
||||
|
||||
// 从缓存中移除实例
|
||||
nacosServiceManage.instanceMap.delete(configKey);
|
||||
}
|
||||
|
||||
|
||||
/** 销毁所有实例:用于构建结束/进程退出时清理 */
|
||||
public static async destroyAll(): Promise<void> {
|
||||
const tasks: Promise<any>[] = [];
|
||||
for (const [, instance] of nacosServiceManage.instanceMap) {
|
||||
tasks.push(instance.destroy().catch(err => logger.warn('[nacos-federation] destroyAll warn:', err)));
|
||||
}
|
||||
await Promise.allSettled(tasks);
|
||||
nacosServiceManage.instanceMap.clear();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import { loadEnv, Plugin, UserConfig } from 'vite';
|
||||
import { NacosConfigClient, NacosNamingClient } from 'nacos';
|
||||
import { getLocalIP, dependModel, formatServiceUrl } from './utils';
|
||||
import { getLocalIP } from './utils';
|
||||
import chalk from 'chalk';
|
||||
|
||||
const logger = console;
|
||||
@@ -39,51 +38,12 @@ export function reg(options?: Partial<RegisterOptions>): Plugin {
|
||||
strictPort: true,
|
||||
cors: true
|
||||
},
|
||||
// TODO dist 上线到服务器后,http://192.168.31.101:1301/ 会出问题
|
||||
// http(https)://前端运行的服务器所在ip/前端模块名
|
||||
base: `${env.VITE_PREFIX}${getLocalIP()}:${env.VITE_SERVER_PORT}/${baseUrl}`
|
||||
// base: `${env.VITE_PREFIX}${getLocalIP()}:${env.VITE_SERVER_PORT}/${baseUrl}`
|
||||
base: `/${baseUrl}`
|
||||
};
|
||||
},
|
||||
async configResolved(config) {
|
||||
const env = config.env;
|
||||
|
||||
// const registerOptions: RegisterOptions = {
|
||||
// serverList: env.VITE_NACOS_ADDRESS || options?.serverList!,
|
||||
// serviceName: env.VITE_SERVER_NAME || options?.serviceName!,
|
||||
// port: Number(env.VITE_SERVER_PORT || options?.port),
|
||||
// namespace: options?.namespace || 'public'
|
||||
// };
|
||||
//
|
||||
// // 验证必要配置
|
||||
// if (!registerOptions.serverList) {
|
||||
// throw new Error('[nacos-cluster-federation] 缺少Nacos服务列表配置,请设置VITE_NACOS_ADDRESS环境变量或插件选项');
|
||||
// }
|
||||
//
|
||||
// if (!registerOptions.serviceName) {
|
||||
// throw new Error('[nacos-cluster-federation] 缺少服务名称配置,请设置VITE_SERVER_NAME环境变量或插件选项');
|
||||
// }
|
||||
// if (!registerOptions.port) {
|
||||
// throw new Error('[nacos-cluster-federation] 缺少服务端口配置,请设置VITE_SERVER_PORT环境变量或插件选项');
|
||||
// }
|
||||
|
||||
// // 初始化Nacos实例
|
||||
// nacosInstance = await nacosServiceManage.create(registerOptions);
|
||||
//
|
||||
// const baseUrl = await nacosInstance.getConfig("baseUrl", "DEFAULT_GROUP")
|
||||
// const baseUrlConfig = baseUrl ? JSON.parse(baseUrl) : {};
|
||||
//
|
||||
// baseUrlConfig.httpTimeOut = await nacosInstance.getConfig("httpTimeOut", "DEFAULT_GROUP")
|
||||
//
|
||||
//
|
||||
// const customizeEnv: Record<string, string> = {};
|
||||
// Object.keys(baseUrlConfig).forEach(key => {
|
||||
// const envKey = `import.meta.env.VITE_${ key.toUpperCase() }`;
|
||||
// customizeEnv[envKey] = JSON.stringify(baseUrlConfig[key]);
|
||||
// });
|
||||
//
|
||||
// // @ts-ignore
|
||||
// Object.assign(config.define, customizeEnv);
|
||||
// Logs(env)
|
||||
},
|
||||
async closeBundle() {
|
||||
// // 服务关闭时注销Nacos实例
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import { nacosServiceManage } from "./src";
|
||||
|
||||
const main = async () => {
|
||||
const nacos = new nacosServiceManage.create({})
|
||||
}
|
||||
Reference in New Issue
Block a user