From ad605d2c9c1ebd0626ac62af2428485e67779a21 Mon Sep 17 00:00:00 2001 From: Hanric Date: Mon, 28 Oct 2024 17:51:50 +0800 Subject: [PATCH] chore: unify logger (#3121) --- .changeset/fast-apples-double.md | 17 ++++ packages/bridge/bridge-react/package.json | 1 + packages/bridge/bridge-react/src/utils.ts | 6 +- packages/bridge/bridge-shared/src/index.ts | 1 - packages/bridge/bridge-shared/src/logger.ts | 52 ----------- packages/bridge/vue3-bridge/package.json | 3 +- packages/bridge/vue3-bridge/src/utils.ts | 4 +- packages/data-prefetch/src/logger/index.ts | 6 +- .../dts-plugin/src/core/lib/DTSManager.ts | 10 +- packages/dts-plugin/src/plugins/DevPlugin.ts | 21 +++-- packages/dts-plugin/src/server/WebClient.ts | 5 +- packages/dts-plugin/src/server/utils/log.ts | 8 +- .../lib/container/ModuleFederationPlugin.ts | 3 +- .../runtime/ChildCompilationRuntimePlugin.ts | 11 ++- packages/managers/src/PKGJsonManager.ts | 4 +- packages/manifest/src/ManifestManager.ts | 14 +-- packages/manifest/src/StatsManager.ts | 10 +- packages/manifest/src/StatsPlugin.ts | 3 +- packages/manifest/src/logger.ts | 6 ++ packages/manifest/src/utils.ts | 6 +- packages/modernjs/src/cli/logger.ts | 6 ++ packages/modernjs/src/cli/ssrPlugin.ts | 5 +- packages/modernjs/src/cli/utils.ts | 5 +- packages/retry-plugin/package.json | 3 + packages/retry-plugin/src/constant.ts | 2 + packages/retry-plugin/src/fetch-retry.ts | 17 ++-- packages/retry-plugin/src/logger.ts | 6 ++ packages/retry-plugin/src/script-retry.ts | 14 +-- packages/rsbuild-plugin/src/cli/index.ts | 11 ++- packages/rsbuild-plugin/src/logger.ts | 5 + packages/runtime/src/module/index.ts | 4 +- packages/runtime/src/remote/index.ts | 3 +- packages/runtime/src/utils/logger.ts | 14 ++- packages/sdk/package.json | 3 + packages/sdk/rollup.config.js | 2 +- packages/sdk/src/env.ts | 19 +++- packages/sdk/src/logger.ts | 93 +++++++------------ packages/sdk/src/utils.ts | 4 +- pnpm-lock.yaml | 21 ++++- 39 files changed, 229 insertions(+), 199 deletions(-) create mode 100644 .changeset/fast-apples-double.md delete mode 100644 packages/bridge/bridge-shared/src/logger.ts create mode 100644 packages/manifest/src/logger.ts create mode 100644 packages/modernjs/src/cli/logger.ts create mode 100644 packages/retry-plugin/src/logger.ts create mode 100644 packages/rsbuild-plugin/src/logger.ts diff --git a/.changeset/fast-apples-double.md b/.changeset/fast-apples-double.md new file mode 100644 index 0000000000..444d16993a --- /dev/null +++ b/.changeset/fast-apples-double.md @@ -0,0 +1,17 @@ +--- +'@module-federation/bridge-shared': patch +'@module-federation/bridge-react': patch +'@module-federation/bridge-vue3': patch +'@module-federation/rsbuild-plugin': patch +'@module-federation/data-prefetch': patch +'@module-federation/retry-plugin': patch +'@module-federation/dts-plugin': patch +'@module-federation/enhanced': patch +'@module-federation/managers': patch +'@module-federation/manifest': patch +'@module-federation/modern-js': patch +'@module-federation/runtime': patch +'@module-federation/sdk': patch +--- + +chore: unified logger diff --git a/packages/bridge/bridge-react/package.json b/packages/bridge/bridge-react/package.json index f13932b18d..7ffd357bf2 100644 --- a/packages/bridge/bridge-react/package.json +++ b/packages/bridge/bridge-react/package.json @@ -40,6 +40,7 @@ "dependencies": { "@loadable/component": "^5.16.4", "@module-federation/bridge-shared": "workspace:*", + "@module-federation/sdk": "workspace:*", "react-error-boundary": "^4.0.13" }, "peerDependencies": { diff --git a/packages/bridge/bridge-react/src/utils.ts b/packages/bridge/bridge-react/src/utils.ts index 2db5fc3289..dc59ff7c5f 100644 --- a/packages/bridge/bridge-react/src/utils.ts +++ b/packages/bridge/bridge-react/src/utils.ts @@ -1,7 +1,9 @@ import React from 'react'; -import { Logger } from '@module-federation/bridge-shared'; +import { createLogger } from '@module-federation/sdk'; -export const LoggerInstance = new Logger('bridge-react'); +export const LoggerInstance = createLogger( + '[ Module Federation Bridge React ]', +); type typeReact = typeof React; diff --git a/packages/bridge/bridge-shared/src/index.ts b/packages/bridge/bridge-shared/src/index.ts index 9fc7bab8b6..825eade308 100644 --- a/packages/bridge/bridge-shared/src/index.ts +++ b/packages/bridge/bridge-shared/src/index.ts @@ -1,3 +1,2 @@ export type { RenderFnParams, ProviderParams } from './type'; -export { Logger } from './logger'; export { dispatchPopstateEnv } from './env'; diff --git a/packages/bridge/bridge-shared/src/logger.ts b/packages/bridge/bridge-shared/src/logger.ts deleted file mode 100644 index b9cc6e7107..0000000000 --- a/packages/bridge/bridge-shared/src/logger.ts +++ /dev/null @@ -1,52 +0,0 @@ -export class Logger { - private name: string; - private isDebugEnabled: boolean; - private color: string; - - constructor(name: string) { - this.name = name; - this.isDebugEnabled = false; - this.color = this.stringToColor(name); - - // Check if debug is enabled in the browser environment - if (typeof window !== 'undefined' && typeof localStorage !== 'undefined') { - this.isDebugEnabled = localStorage.getItem('debug') === 'true'; - } - - // Check if debug is enabled in the Node.js environment - if (typeof process !== 'undefined' && process.env) { - this.isDebugEnabled = process.env.DEBUG === 'true'; - } - } - - public log(...messages: any[]): void { - if (this.isDebugEnabled) { - const infoStyle = `color: ${this.color}; font-weight: bold`; - const logMessage = `%c[${this.name}]`; - const stack = - new Error().stack?.split('\n')[2]?.trim() || - 'Stack information not available'; - - if (typeof console !== 'undefined' && console.debug) { - console.debug(logMessage, infoStyle, ...messages, `\n (${stack})`); - - // if (this.isDebugEnabledStack) { - // console.log(`%c${stack}`, 'color: grey; font-style: italic;'); - // } - } - } - } - - private stringToColor(str: string): string { - let hash = 0; - for (let i = 0; i < str.length; i++) { - hash = str.charCodeAt(i) + ((hash << 5) - hash); - } - let color = '#'; - for (let i = 0; i < 3; i++) { - const value = (hash >> (i * 8)) & 0xff; - color += ('00' + value.toString(16)).substr(-2); - } - return color; - } -} diff --git a/packages/bridge/vue3-bridge/package.json b/packages/bridge/vue3-bridge/package.json index d9d4764135..071210b77d 100644 --- a/packages/bridge/vue3-bridge/package.json +++ b/packages/bridge/vue3-bridge/package.json @@ -31,7 +31,8 @@ "vue-router": "=3" }, "dependencies": { - "@module-federation/bridge-shared": "workspace:*" + "@module-federation/bridge-shared": "workspace:*", + "@module-federation/sdk": "workspace:*" }, "devDependencies": { "@vitejs/plugin-vue": "^5.0.4", diff --git a/packages/bridge/vue3-bridge/src/utils.ts b/packages/bridge/vue3-bridge/src/utils.ts index 08f5294ff0..e6d380db5d 100644 --- a/packages/bridge/vue3-bridge/src/utils.ts +++ b/packages/bridge/vue3-bridge/src/utils.ts @@ -1,3 +1,3 @@ -import { Logger } from '@module-federation/bridge-shared'; +import { createLogger } from '@module-federation/sdk'; -export const LoggerInstance = new Logger('vue3-bridge'); +export const LoggerInstance = createLogger('[ Module Federation Bridge Vue3 ]'); diff --git a/packages/data-prefetch/src/logger/index.ts b/packages/data-prefetch/src/logger/index.ts index 7e83975aa1..3687ee5320 100644 --- a/packages/data-prefetch/src/logger/index.ts +++ b/packages/data-prefetch/src/logger/index.ts @@ -1,3 +1,5 @@ -import { Logger } from '@module-federation/sdk'; +import { createLogger } from '@module-federation/sdk'; -export default new Logger('[Module Federation Data Prefetch]'); +const logger = createLogger('[ Module Federation Data Prefetch ]'); + +export default logger; diff --git a/packages/dts-plugin/src/core/lib/DTSManager.ts b/packages/dts-plugin/src/core/lib/DTSManager.ts index 431ae0f4ea..2d5597fc01 100644 --- a/packages/dts-plugin/src/core/lib/DTSManager.ts +++ b/packages/dts-plugin/src/core/lib/DTSManager.ts @@ -27,7 +27,7 @@ import { REMOTE_ALIAS_IDENTIFIER, HOST_API_TYPES_FILE_NAME, } from '../constant'; -import { fileLog } from '../../server'; +import { fileLog, logger } from '../../server'; import { axiosGet, cloneDeepOptions, isDebugMode } from './utils'; import { UpdateMode } from '../../server/constant'; @@ -163,12 +163,10 @@ class DTSManager { console.error(err); } } - console.log(ansiColors.green('Federated types created correctly')); + logger.success('Federated types created correctly'); } catch (error) { if (this.options.remote?.abortOnError === false) { - console.error( - ansiColors.red(`Unable to compile federated types, ${error}`), - ); + logger.error(`Unable to compile federated types, ${error}`); } else { throw error; } @@ -406,7 +404,7 @@ class DTSManager { this.consumeAPITypes(hostOptions); } - console.log(ansiColors.green('Federated types extraction completed')); + logger.success('Federated types extraction completed'); } catch (err) { if (this.options.host?.abortOnError === false) { fileLog( diff --git a/packages/dts-plugin/src/plugins/DevPlugin.ts b/packages/dts-plugin/src/plugins/DevPlugin.ts index 8d0edd81fd..00a2bed980 100644 --- a/packages/dts-plugin/src/plugins/DevPlugin.ts +++ b/packages/dts-plugin/src/plugins/DevPlugin.ts @@ -10,6 +10,7 @@ import { WEB_CLIENT_OPTIONS_IDENTIFIER, WebClientOptions, getIPV4, + logger, } from '../server'; import type { Compiler, WebpackPluginInstance } from 'webpack'; import path from 'path'; @@ -56,15 +57,15 @@ export class DevPlugin implements WebpackPluginInstance { private _stopWhenSIGTERMOrSIGINT(): void { process.on('SIGTERM', () => { - console.log( - chalk`{cyan ${this._options.name} Process(${process.pid}) SIGTERM, mf server will exit...}`, + logger.info( + `${this._options.name} Process(${process.pid}) SIGTERM, mf server will exit...`, ); this._exit(PROCESS_EXIT_CODE.SUCCESS); }); process.on('SIGINT', () => { - console.log( - chalk`{cyan ${this._options.name} Process(${process.pid}) SIGINT, mf server will exit...}`, + logger.info( + `${this._options.name} Process(${process.pid}) SIGINT, mf server will exit...`, ); this._exit(PROCESS_EXIT_CODE.SUCCESS); }); @@ -72,16 +73,16 @@ export class DevPlugin implements WebpackPluginInstance { private _handleUnexpectedExit(): void { process.on('unhandledRejection', (error) => { - console.error('Unhandled Rejection Error: ', error); - console.log( - chalk`{cyan ${this._options.name} Process(${process.pid}) unhandledRejection, mf server will exit...}`, + logger.error(error); + logger.error( + `Process(${process.pid}) unhandledRejection, mf server will exit...`, ); this._exit(PROCESS_EXIT_CODE.FAILURE); }); process.on('uncaughtException', (error) => { - console.error('Unhandled Rejection Error: ', error); - console.log( - chalk`{cyan ${this._options.name} Process(${process.pid}) uncaughtException, mf server will exit...}`, + logger.error(error); + logger.error( + `Process(${process.pid}) uncaughtException, mf server will exit...`, ); this._exit(PROCESS_EXIT_CODE.FAILURE); }); diff --git a/packages/dts-plugin/src/server/WebClient.ts b/packages/dts-plugin/src/server/WebClient.ts index 162e8b63c5..495cb4ac2c 100644 --- a/packages/dts-plugin/src/server/WebClient.ts +++ b/packages/dts-plugin/src/server/WebClient.ts @@ -1,8 +1,5 @@ import WebSocket from 'isomorphic-ws'; -import { - DEFAULT_WEB_SOCKET_PORT, - WEB_SOCKET_CONNECT_MAGIC_ID, -} from './constant'; +import { DEFAULT_WEB_SOCKET_PORT } from './constant'; import { Message } from './message/Message'; import { AddWebClientAction } from './message/Action'; import { APIKind, ReloadWebClientAPI } from './message/API'; diff --git a/packages/dts-plugin/src/server/utils/log.ts b/packages/dts-plugin/src/server/utils/log.ts index 9be6c676bd..cd40640f4b 100644 --- a/packages/dts-plugin/src/server/utils/log.ts +++ b/packages/dts-plugin/src/server/utils/log.ts @@ -1,11 +1,13 @@ -import { logger } from '@module-federation/sdk'; +import { createLogger } from '@module-federation/sdk'; import * as log4js from 'log4js'; import chalk from 'chalk'; import { MF_SERVER_IDENTIFIER } from '../constant'; import { ActionKind } from '../message/Action'; +const logger = createLogger(`[ ${MF_SERVER_IDENTIFIER} ]`); + function log(msg: string): void { - logger.info(chalk`{bold {greenBright [ ${MF_SERVER_IDENTIFIER} ]} ${msg}}`); + logger.info(msg); } function fileLog(msg: string, module: string, level: string) { @@ -35,4 +37,4 @@ function error(error: unknown, action: ActionKind, from: string): string { return err.toString(); } -export { log, fileLog, error }; +export { log, fileLog, error, logger }; diff --git a/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts b/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts index 71cd86283f..a10bd6a4d9 100644 --- a/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts +++ b/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts @@ -10,6 +10,7 @@ import { StatsPlugin } from '@module-federation/manifest'; import { composeKeyWithSeparator, type moduleFederationPlugin, + logger, } from '@module-federation/sdk'; import { PrefetchPlugin } from '@module-federation/data-prefetch/cli'; import { normalizeWebpackPath } from '@module-federation/sdk/normalize-webpack-path'; @@ -110,7 +111,7 @@ class ModuleFederationPlugin implements WebpackPluginInstance { if (err instanceof Error) { err.message = `[ ModuleFederationPlugin ]: Manifest will not generate, because: ${err.message}`; } - console.warn(err); + logger.warn(err); disableManifest = true; } } diff --git a/packages/enhanced/src/lib/container/runtime/ChildCompilationRuntimePlugin.ts b/packages/enhanced/src/lib/container/runtime/ChildCompilationRuntimePlugin.ts index 79f333292c..e816ddaa48 100644 --- a/packages/enhanced/src/lib/container/runtime/ChildCompilationRuntimePlugin.ts +++ b/packages/enhanced/src/lib/container/runtime/ChildCompilationRuntimePlugin.ts @@ -8,6 +8,7 @@ import fs from 'fs'; import path from 'path'; import { ConcatSource } from 'webpack-sources'; import { transformSync } from '@swc/core'; +import { logger } from '@module-federation/sdk'; const { RuntimeModule, Template, RuntimeGlobals } = require( normalizeWebpackPath('webpack'), @@ -142,7 +143,7 @@ class CustomRuntimePlugin { childCompiler.options.devtool = undefined; childCompiler.options.optimization.splitChunks = false; childCompiler.options.optimization.removeAvailableModules = true; - console.log('Creating child compiler for', this.bundlerRuntimePath); + logger.log('Creating child compiler for', this.bundlerRuntimePath); childCompiler.hooks.thisCompilation.tap( this.constructor.name, @@ -174,7 +175,7 @@ class CustomRuntimePlugin { onceForCompilationMap.set(compilation, source); onceForCompilationMap.set(compiler, source); fs.writeFileSync(outputPath, source); - console.log('got compilation asset'); + logger.log('got compilation asset'); childCompilation.chunks.forEach((chunk) => { chunk.files.forEach((file) => { childCompilation.deleteAsset(file); @@ -195,7 +196,7 @@ class CustomRuntimePlugin { } if (!childCompilation) { - console.warn( + logger.warn( 'Embed Federation Runtime: Child compilation is undefined', ); return callback(); @@ -205,7 +206,7 @@ class CustomRuntimePlugin { return callback(childCompilation.errors[0]); } - console.log('Code built successfully'); + logger.log('Code built successfully'); callback(); }, @@ -233,7 +234,7 @@ class CustomRuntimePlugin { ); compilation.addRuntimeModule(chunk, runtimeModule); - console.log(`Custom runtime module added to chunk: ${chunk.name}`); + logger.log(`Custom runtime module added to chunk: ${chunk.name}`); }; compilation.hooks.runtimeRequirementInTree .for(federationGlobal) diff --git a/packages/managers/src/PKGJsonManager.ts b/packages/managers/src/PKGJsonManager.ts index cb0fa728a1..416a0021c1 100644 --- a/packages/managers/src/PKGJsonManager.ts +++ b/packages/managers/src/PKGJsonManager.ts @@ -1,7 +1,7 @@ import path from 'path'; import finder from 'find-pkg'; import fs from 'fs'; -import { MFModuleType } from '@module-federation/sdk'; +import { MFModuleType, logger } from '@module-federation/sdk'; export class PKGJsonManager { private _pkg?: Record; @@ -27,7 +27,7 @@ export class PKGJsonManager { this._pkg = pkg; return pkg; } catch (err) { - console.error(err); + logger.error(err); return {}; } } diff --git a/packages/manifest/src/ManifestManager.ts b/packages/manifest/src/ManifestManager.ts index ac1af8e898..118f41d5d2 100644 --- a/packages/manifest/src/ManifestManager.ts +++ b/packages/manifest/src/ManifestManager.ts @@ -5,16 +5,14 @@ import { Stats, Manifest, ManifestExpose, - StatsExpose, - StatsShared, ManifestShared, ManifestRemote, - StatsRemote, moduleFederationPlugin, encodeName, MFPrefetchCommon, } from '@module-federation/sdk'; import { getFileName, isDev } from './utils'; +import logger from './logger'; import type { Compilation, Compiler } from 'webpack'; import { PLUGIN_IDENTIFIER } from './constants'; import { ManifestInfo } from './types'; @@ -145,10 +143,12 @@ class ManifestManager { } if (isDev()) { - console.log( - chalk`{bold {greenBright [ ${PLUGIN_IDENTIFIER} ]} {greenBright Manifest Link:} {cyan ${ - publicPath === 'auto' ? '{auto}/' : publicPath - }${manifestFileName}}}`, + logger.info( + `Manifest Link: ${chalk.cyan( + `${ + publicPath === 'auto' ? '{auto}/' : publicPath + }${manifestFileName}`, + )} `, ); } diff --git a/packages/manifest/src/StatsManager.ts b/packages/manifest/src/StatsManager.ts index 586dca2f8f..e74efe427a 100644 --- a/packages/manifest/src/StatsManager.ts +++ b/packages/manifest/src/StatsManager.ts @@ -2,7 +2,6 @@ /* eslint-disable @typescript-eslint/member-ordering */ /* eslint-disable max-depth */ -import chalk from 'chalk'; import { StatsRemote, StatsBuildInfo, @@ -31,6 +30,7 @@ import { getFileName, getTypesMetaInfo, } from './utils'; +import logger from './logger'; import { ContainerManager, RemoteManager, @@ -490,13 +490,13 @@ class StatsManager { } = compiler.options; if (typeof publicPath !== 'string') { - console.warn( - chalk`{bold {yellow [ ${PLUGIN_IDENTIFIER} ]: Manifest will not generate, because publicPath can only be string, but got '${publicPath}' }}`, + logger.warn( + `Manifest will not generate, because publicPath can only be string, but got '${publicPath}'`, ); return false; } else if (publicPath === 'auto') { - console.warn( - chalk`{bold {blue [ ${PLUGIN_IDENTIFIER} ]: Manifest will use absolute path resolution via its host at runtime, reason: publicPath='${publicPath}'}}`, + logger.warn( + `Manifest will use absolute path resolution via its host at runtime, reason: publicPath='${publicPath}'`, ); return true; } diff --git a/packages/manifest/src/StatsPlugin.ts b/packages/manifest/src/StatsPlugin.ts index 950e06fbb2..54539ed9c8 100644 --- a/packages/manifest/src/StatsPlugin.ts +++ b/packages/manifest/src/StatsPlugin.ts @@ -3,6 +3,7 @@ import { moduleFederationPlugin } from '@module-federation/sdk'; import { ManifestManager } from './ManifestManager'; import { StatsManager } from './StatsManager'; import { PLUGIN_IDENTIFIER } from './constants'; +import logger from './logger'; import { StatsInfo, ManifestInfo, ResourceInfo } from './types'; export class StatsPlugin implements WebpackPluginInstance { @@ -33,7 +34,7 @@ export class StatsPlugin implements WebpackPluginInstance { if (err instanceof Error) { err.message = `[ ${PLUGIN_IDENTIFIER} ]: Manifest will not generate, because: ${err.message}`; } - console.error(err); + logger.error(err); this._enable = false; } } diff --git a/packages/manifest/src/logger.ts b/packages/manifest/src/logger.ts new file mode 100644 index 0000000000..a8dfe2465c --- /dev/null +++ b/packages/manifest/src/logger.ts @@ -0,0 +1,6 @@ +import { createLogger } from '@module-federation/sdk'; +import { PLUGIN_IDENTIFIER } from './constants'; + +const logger = createLogger(`[ ${PLUGIN_IDENTIFIER} ]`); + +export default logger; diff --git a/packages/manifest/src/utils.ts b/packages/manifest/src/utils.ts index 88a6293572..bc90b5158d 100644 --- a/packages/manifest/src/utils.ts +++ b/packages/manifest/src/utils.ts @@ -1,5 +1,4 @@ import { Chunk, Compilation, StatsCompilation, StatsModule } from 'webpack'; -import chalk from 'chalk'; import path from 'path'; import { StatsAssets, @@ -15,6 +14,7 @@ import { retrieveTypesAssetsInfo, } from '@module-federation/dts-plugin/core'; import { HOT_UPDATE_SUFFIX, PLUGIN_IDENTIFIER } from './constants'; +import logger from './logger'; function isHotFile(file: string) { return file.includes(HOT_UPDATE_SUFFIX); @@ -310,8 +310,8 @@ export function getTypesMetaInfo( api: path.join(zipPrefix, apiFileName), }; } catch (err) { - console.warn( - chalk`{bold {yellow [ ${PLUGIN_IDENTIFIER} ]: getTypesMetaInfo failed, it will use the default types meta info, and the errors as belows: ${err} }}`, + logger.warn( + `getTypesMetaInfo failed, it will use the default types meta info, and the errors as belows: ${err}`, ); return defaultTypesMetaInfo; } diff --git a/packages/modernjs/src/cli/logger.ts b/packages/modernjs/src/cli/logger.ts new file mode 100644 index 0000000000..00d9f8b0e2 --- /dev/null +++ b/packages/modernjs/src/cli/logger.ts @@ -0,0 +1,6 @@ +import { createLogger } from '@module-federation/sdk'; +import { PLUGIN_IDENTIFIER } from '../constant'; + +const logger = createLogger(PLUGIN_IDENTIFIER); + +export default logger; diff --git a/packages/modernjs/src/cli/ssrPlugin.ts b/packages/modernjs/src/cli/ssrPlugin.ts index aaa1258379..69477d455c 100644 --- a/packages/modernjs/src/cli/ssrPlugin.ts +++ b/packages/modernjs/src/cli/ssrPlugin.ts @@ -7,6 +7,7 @@ import { ModuleFederationPlugin as RspackModuleFederationPlugin } from '@module- import UniverseEntryChunkTrackerPlugin from '@module-federation/node/universe-entry-chunk-tracker-plugin'; import { updateStatsAndManifest } from './manifest'; import { isDev } from './constant'; +import logger from './logger'; export function setEnv() { process.env['MF_DISABLE_EMIT_STATS'] = 'true'; @@ -110,9 +111,7 @@ export const moduleFederationSSRPlugin = ( next(); } } catch (err) { - if (process.env.FEDERATION_DEBUG) { - console.error(err); - } + logger.debug(err); next(); } }, diff --git a/packages/modernjs/src/cli/utils.ts b/packages/modernjs/src/cli/utils.ts index cd3ebaabdf..9a3bb94064 100644 --- a/packages/modernjs/src/cli/utils.ts +++ b/packages/modernjs/src/cli/utils.ts @@ -12,6 +12,7 @@ import { bundle } from '@modern-js/node-bundle-require'; import { PluginOptions } from '../types'; import { LOCALHOST, PLUGIN_IDENTIFIER } from '../constant'; import { BundlerConfig } from '../interfaces/bundler'; +import logger from './logger'; const defaultPath = path.resolve(process.cwd(), 'module-federation.config.ts'); const isDev = process.env.NODE_ENV === 'development'; @@ -283,8 +284,8 @@ export function patchBundlerConfig(options: { bundlerConfig.optimization.splitChunks.cacheGroups ) { bundlerConfig.optimization.splitChunks.chunks = 'async'; - console.warn( - `${PLUGIN_IDENTIFIER} splitChunks.chunks = async is not allowed with stream SSR mode, it will auto changed to "async"`, + logger.warn( + `splitChunks.chunks = async is not allowed with stream SSR mode, it will auto changed to "async"`, ); } diff --git a/packages/retry-plugin/package.json b/packages/retry-plugin/package.json index 965e6386d0..c050894f42 100644 --- a/packages/retry-plugin/package.json +++ b/packages/retry-plugin/package.json @@ -29,5 +29,8 @@ }, "devDependencies": { "@module-federation/runtime": "workspace:*" + }, + "dependencies": { + "@module-federation/sdk": "workspace:*" } } diff --git a/packages/retry-plugin/src/constant.ts b/packages/retry-plugin/src/constant.ts index c6f3d48d64..1d1662b74e 100644 --- a/packages/retry-plugin/src/constant.ts +++ b/packages/retry-plugin/src/constant.ts @@ -4,3 +4,5 @@ export const loadStatus = { success: 'success', error: 'error', }; + +export const PLUGIN_IDENTIFIER = '[ Module Federation RetryPlugin ]'; diff --git a/packages/retry-plugin/src/fetch-retry.ts b/packages/retry-plugin/src/fetch-retry.ts index 1965e63aba..13326c752a 100644 --- a/packages/retry-plugin/src/fetch-retry.ts +++ b/packages/retry-plugin/src/fetch-retry.ts @@ -1,5 +1,10 @@ import type { RequiredUrl, FetchWithRetryOptions } from './types'; -import { defaultRetries, defaultRetryDelay } from './constant'; +import { + defaultRetries, + defaultRetryDelay, + PLUGIN_IDENTIFIER, +} from './constant'; +import logger from './logger'; async function fetchWithRetry({ url, // fetch url @@ -27,8 +32,8 @@ async function fetchWithRetry({ return response; } catch (error) { if (retryTimes <= 0) { - console.log( - `>>>>>>>>> 【Module Federation RetryPlugin】: retry failed after ${retryTimes} times for url: ${url}, now will try fallbackUrl url <<<<<<<<<`, + logger.log( + `>>>>>>>>> retry failed after ${retryTimes} times for url: ${url}, now will try fallbackUrl url <<<<<<<<<`, ); if (fallback && typeof fallback === 'function') { return fetchWithRetry({ @@ -47,15 +52,15 @@ async function fetchWithRetry({ } throw new Error( - '【Module Federation RetryPlugin】: The request failed three times and has now been abandoned', + `${PLUGIN_IDENTIFIER}: The request failed three times and has now been abandoned`, ); } else { // If there are remaining times, delay 1 second and try again retryDelay > 0 && (await new Promise((resolve) => setTimeout(resolve, retryDelay))); - console.log( - `【Module Federation RetryPlugin】: Trying again. Number of retries available:${retryTimes - 1}`, + logger.log( + `Trying again. Number of retries available:${retryTimes - 1}`, ); return await fetchWithRetry({ url, diff --git a/packages/retry-plugin/src/logger.ts b/packages/retry-plugin/src/logger.ts new file mode 100644 index 0000000000..c1be325216 --- /dev/null +++ b/packages/retry-plugin/src/logger.ts @@ -0,0 +1,6 @@ +import { createLogger } from '@module-federation/sdk'; +import { PLUGIN_IDENTIFIER } from './constant'; + +const logger = createLogger(PLUGIN_IDENTIFIER); + +export default logger; diff --git a/packages/retry-plugin/src/script-retry.ts b/packages/retry-plugin/src/script-retry.ts index 9b9524aef0..d5667cbdca 100644 --- a/packages/retry-plugin/src/script-retry.ts +++ b/packages/retry-plugin/src/script-retry.ts @@ -1,5 +1,6 @@ import { ScriptWithRetryOptions, CreateScriptFunc, RequiredUrl } from './types'; import { defaultRetries, defaultRetryDelay, loadStatus } from './constant'; +import logger from './logger'; export const defaultCreateScript = ( url: string, @@ -60,8 +61,8 @@ async function loadScript( script.onerror = (event) => { if (retries < maxRetries) { retries++; - console.warn( - `【Module Federation RetryPlugin】: Failed to load script. Retrying... (${retries}/${maxRetries})`, + logger.warn( + `Failed to load script. Retrying... (${retries}/${maxRetries})`, ); // reload after a delay @@ -70,9 +71,8 @@ async function loadScript( resolve(attemptLoad()); }, retryDelay); } else { - console.error( - '【Module Federation RetryPlugin】: Failed to load script after maximum retries. the url is:', - url, + logger.error( + `Failed to load script after maximum retries. the url is: ${url}`, ); resolve({ status: loadStatus.error, @@ -101,8 +101,8 @@ function scriptWithRetry({ const originOnerror = script.onerror; const originOnLoad = script.onload; script.onerror = async (event) => { - console.warn( - `【Module Federation RetryPlugin】: Script load failed, retrying (${retryTimes + 1}/${defaultRetries}): ${url}`, + logger.warn( + `Script load failed, retrying (${retryTimes + 1}/${defaultRetries}): ${url}`, ); const scriptLoader = await loadScript( diff --git a/packages/rsbuild-plugin/src/cli/index.ts b/packages/rsbuild-plugin/src/cli/index.ts index bcd0fc835d..81e712a7c5 100644 --- a/packages/rsbuild-plugin/src/cli/index.ts +++ b/packages/rsbuild-plugin/src/cli/index.ts @@ -2,7 +2,7 @@ import { parseOptions } from '@module-federation/enhanced'; import { ModuleFederationPlugin } from '@module-federation/enhanced/rspack'; import { isRequiredVersion } from '@module-federation/sdk'; -import { isRegExp, DEFAULT_ASSET_PREFIX } from '../utils/index'; +import { isRegExp } from '../utils/index'; import pkgJson from '../../package.json'; import type { @@ -10,6 +10,7 @@ import type { sharePlugin, } from '@module-federation/sdk'; import type { RsbuildPlugin, EnvironmentConfig } from '@rsbuild/core'; +import logger from '../logger'; type ModuleFederationOptions = moduleFederationPlugin.ModuleFederationPluginOptions; @@ -106,8 +107,8 @@ export const pluginModuleFederation = ( }); if (match) { - console.log( - `[Module Federation Rsbuild Plugin]: ${sharedModule} is removed from externals because it is a shared module.`, + logger.log( + `${sharedModule} is removed from externals because it is a shared module.`, ); } return !match; @@ -125,8 +126,8 @@ export const pluginModuleFederation = ( return dep === ext; }); if (match) { - console.log( - `[Module Federation Rsbuild Plugin]: ${sharedModule} is removed from externals because it is a shared module.`, + logger.log( + `${sharedModule} is removed from externals because it is a shared module.`, ); return false; } diff --git a/packages/rsbuild-plugin/src/logger.ts b/packages/rsbuild-plugin/src/logger.ts new file mode 100644 index 0000000000..025e9f4a83 --- /dev/null +++ b/packages/rsbuild-plugin/src/logger.ts @@ -0,0 +1,5 @@ +import { createLogger } from '@module-federation/sdk'; + +const logger = createLogger('[ Module Federation Rsbuild Plugin ]'); + +export default logger; diff --git a/packages/runtime/src/module/index.ts b/packages/runtime/src/module/index.ts index 51788b04d3..1658236c09 100644 --- a/packages/runtime/src/module/index.ts +++ b/packages/runtime/src/module/index.ts @@ -1,4 +1,4 @@ -import { getFMId, assert } from '../utils'; +import { getFMId, assert, logger } from '../utils'; import { safeToString, ModuleInfo } from '@module-federation/sdk'; import { getRemoteEntry } from '../utils/load'; import { FederationHost } from '../core'; @@ -88,7 +88,7 @@ class Module { }); if (typeof remoteEntryExports?.init === 'undefined') { - console.error( + logger.error( 'The remote entry interface does not contain "init"', '\n', 'Ensure the name of this remote is not reserved or in use. Check if anything already exists on window[nameOfRemote]', diff --git a/packages/runtime/src/remote/index.ts b/packages/runtime/src/remote/index.ts index 0b0bf556e2..3c96759388 100644 --- a/packages/runtime/src/remote/index.ts +++ b/packages/runtime/src/remote/index.ts @@ -30,6 +30,7 @@ import { getRemoteInfo, getRemoteEntryUniqueKey, matchRemoteWithNameAndExpose, + logger, } from '../utils'; import { DEFAULT_REMOTE_TYPE, DEFAULT_SCOPE } from '../constant'; import { Module, ModuleOptions } from '../module'; @@ -586,7 +587,7 @@ export class RemoteHandler { host.moduleCache.delete(remote.name); } } catch (err) { - console.log('removeRemote fail: ', err); + logger.log('removeRemote fail: ', err); } } } diff --git a/packages/runtime/src/utils/logger.ts b/packages/runtime/src/utils/logger.ts index bf027f3e9a..b782e00352 100644 --- a/packages/runtime/src/utils/logger.ts +++ b/packages/runtime/src/utils/logger.ts @@ -1,4 +1,8 @@ +import { createLogger } from '@module-federation/sdk'; + const LOG_CATEGORY = '[ Federation Runtime ]'; +// FIXME: pre-bundle ? +const logger = createLogger(LOG_CATEGORY); // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function assert(condition: any, msg: string): asserts condition { @@ -18,8 +22,14 @@ export function error(msg: string | Error | unknown): never { export function warn(msg: Parameters[0]): void { if (msg instanceof Error) { msg.message = `${LOG_CATEGORY}: ${msg.message}`; - console.warn(msg); + logger.warn(msg); } else { - console.warn(`${LOG_CATEGORY}: ${msg}`); + logger.warn(msg); } } + +export function log(...args: unknown[]) { + logger.log(...args); +} + +export { logger }; diff --git a/packages/sdk/package.json b/packages/sdk/package.json index deb46fd84e..82322ecc3d 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -40,5 +40,8 @@ "./dist/normalize-webpack-path.cjs.d.ts" ] } + }, + "dependencies": { + "isomorphic-rslog": "0.0.4" } } diff --git a/packages/sdk/rollup.config.js b/packages/sdk/rollup.config.js index a1277443f1..102f33ba78 100644 --- a/packages/sdk/rollup.config.js +++ b/packages/sdk/rollup.config.js @@ -7,7 +7,7 @@ module.exports = (rollupConfig, _projectOptions) => { }), ); - rollupConfig.external = [/@module-federation/]; + rollupConfig.external = [/@module-federation/, 'isomorphic-rslog']; if (Array.isArray(rollupConfig.output)) { rollupConfig.output = rollupConfig.output.map((c) => ({ diff --git a/packages/sdk/src/env.ts b/packages/sdk/src/env.ts index 63343e58b4..43175c0df1 100644 --- a/packages/sdk/src/env.ts +++ b/packages/sdk/src/env.ts @@ -1,3 +1,5 @@ +import { BROWSER_LOG_KEY, BROWSER_LOG_VALUE } from './constant'; + declare global { // eslint-disable-next-line no-var var FEDERATION_DEBUG: string | undefined; @@ -6,6 +8,16 @@ declare global { function isBrowserEnv(): boolean { return typeof window !== 'undefined'; } +function isBrowserDebug() { + try { + if (isBrowserEnv() && window.localStorage) { + return localStorage.getItem(BROWSER_LOG_KEY) === BROWSER_LOG_VALUE; + } + } catch (error) { + return false; + } + return false; +} function isDebugMode(): boolean { if ( @@ -15,7 +27,12 @@ function isDebugMode(): boolean { ) { return Boolean(process.env['FEDERATION_DEBUG']); } - return typeof FEDERATION_DEBUG !== 'undefined' && Boolean(FEDERATION_DEBUG); + + if (typeof FEDERATION_DEBUG !== 'undefined' && Boolean(FEDERATION_DEBUG)) { + return true; + } + + return isBrowserDebug(); } const getProcessEnv = function (): Record { diff --git a/packages/sdk/src/logger.ts b/packages/sdk/src/logger.ts index b6151750ef..7f681b14e6 100644 --- a/packages/sdk/src/logger.ts +++ b/packages/sdk/src/logger.ts @@ -1,66 +1,43 @@ -import { BROWSER_LOG_KEY, BROWSER_LOG_VALUE } from './constant'; -import { isBrowserEnv, isDebugMode } from './env'; +import { type Logger, createLogger as _createLogger } from 'isomorphic-rslog'; +import { isDebugMode } from './env'; -const DEBUG_LOG = '[ FEDERATION DEBUG ]'; +const PREFIX = '[ Module Federation ]'; -function safeToString(info: any): string { - try { - return JSON.stringify(info, null, 2); - } catch (e) { - return ''; +function setDebug(loggerInstance: Logger) { + if (isDebugMode()) { + loggerInstance.level = 'verbose'; } } -function safeGetLocalStorageItem() { - try { - if (typeof window !== 'undefined' && window.localStorage) { - return localStorage.getItem(BROWSER_LOG_KEY) === BROWSER_LOG_VALUE; - } - } catch (error) { - return typeof document !== 'undefined'; - } - return false; +function setPrefix(loggerInstance: Logger, prefix: string) { + loggerInstance.labels = { + warn: `${prefix} Warn`, + error: `${prefix} Error`, + success: `${prefix} Success`, + info: `${prefix} Info`, + ready: `${prefix} Ready`, + debug: `${prefix} Debug`, + }; } -class Logger { - enable = false; - identifier: string; - constructor(identifier?: string) { - this.identifier = identifier || DEBUG_LOG; - if (isBrowserEnv() && safeGetLocalStorageItem()) { - this.enable = true; - } else if (isDebugMode()) { - this.enable = true; - } - } - info(msg: string, info?: any): void { - if (this.enable) { - const argsToString = safeToString(info) || ''; - if (isBrowserEnv()) { - console.info( - `%c ${this.identifier}: ${msg} ${argsToString}`, - 'color:#3300CC', - ); - } else { - console.info( - '\x1b[34m%s', - `${this.identifier}: ${msg} ${ - argsToString ? `\n${argsToString}` : '' - }`, - ); - } - } - } - logOriginalInfo(...args: unknown[]) { - if (this.enable) { - if (isBrowserEnv()) { - console.info(`%c ${this.identifier}: OriginalInfo`, 'color:#3300CC'); - console.log(...args); - } else { - console.info(`%c ${this.identifier}: OriginalInfo`, 'color:#3300CC'); - console.log(...args); - } - } - } + +function createLogger(prefix: string) { + const loggerInstance = _createLogger({ + labels: { + warn: `${PREFIX} Warn`, + error: `${PREFIX} Error`, + success: `${PREFIX} Success`, + info: `${PREFIX} Info`, + ready: `${PREFIX} Ready`, + debug: `${PREFIX} Debug`, + }, + }); + + setDebug(loggerInstance); + setPrefix(loggerInstance, prefix); + return loggerInstance; } -export { Logger }; +const logger = createLogger(PREFIX); + +export { logger, createLogger }; +export type { Logger }; diff --git a/packages/sdk/src/utils.ts b/packages/sdk/src/utils.ts index 435cfabb04..1f34c5334e 100644 --- a/packages/sdk/src/utils.ts +++ b/packages/sdk/src/utils.ts @@ -6,7 +6,7 @@ import { SEPARATOR, MANIFEST_EXT, } from './constant'; -import { Logger } from './logger'; +import { logger } from './logger'; import { getProcessEnv } from './env'; const LOG_CATEGORY = '[ Federation Runtime ]'; @@ -70,8 +70,6 @@ declare global { var FEDERATION_DEBUG: string | undefined; } -const logger = new Logger(); - const composeKeyWithSeparator = function ( ...args: (string | undefined)[] ): string { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f07dc4f8a7..1c2d3bf4fa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1738,6 +1738,9 @@ importers: '@module-federation/bridge-shared': specifier: workspace:* version: link:../bridge-shared + '@module-federation/sdk': + specifier: workspace:* + version: link:../../sdk react-error-boundary: specifier: ^4.0.13 version: 4.0.13(react@18.3.1) @@ -1833,6 +1836,9 @@ importers: '@module-federation/bridge-shared': specifier: workspace:* version: link:../bridge-shared + '@module-federation/sdk': + specifier: workspace:* + version: link:../../sdk devDependencies: '@vitejs/plugin-vue': specifier: ^5.0.4 @@ -2398,6 +2404,10 @@ importers: version: 5.93.0(@swc/core@1.7.26)(esbuild@0.24.0) packages/retry-plugin: + dependencies: + '@module-federation/sdk': + specifier: workspace:* + version: link:../sdk devDependencies: '@module-federation/runtime': specifier: workspace:* @@ -2462,7 +2472,11 @@ importers: specifier: workspace:* version: link:../webpack-bundler-runtime - packages/sdk: {} + packages/sdk: + dependencies: + isomorphic-rslog: + specifier: 0.0.4 + version: 0.0.4 packages/storybook-addon: dependencies: @@ -30605,6 +30619,11 @@ packages: simple-get: 4.0.1 dev: true + /isomorphic-rslog@0.0.4: + resolution: {integrity: sha512-KwROYmorP1F97yiPCRENbvJRshPiWFLzU73CSzqO8jUVGiGK8d3RqrKBSTmSLc7MKse69LyYydTq6Xy0xBFE0g==} + engines: {node: '>=14.17.6'} + dev: false + /isomorphic-ws@5.0.0(ws@8.17.1): resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} peerDependencies: