Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions packages/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"extends": ["../.eslintrc.json"],
"ignorePatterns": ["!**/*", "dist/**/*", "**/*.d.ts"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.json"],
"parser": "jsonc-eslint-parser",
"rules": {}
}
]
}
3 changes: 3 additions & 0 deletions packages/assemble-release-plan/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["../.eslintrc.json"]
}
3 changes: 3 additions & 0 deletions packages/cli/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["../.eslintrc.json"]
}
4 changes: 1 addition & 3 deletions packages/cli/src/utils/readConfig.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import path from 'path';
import type { moduleFederationPlugin } from '@module-federation/sdk';

const { createJiti } = require('jiti');
import { createJiti } from 'jiti';
const DEFAULT_CONFIG_PATH = 'module-federation.config.ts';

export const getConfigPath = (userConfigPath?: string) => {
Expand All @@ -16,7 +15,6 @@ export async function readConfig(userConfigPath?: string) {
const configPath = getConfigPath(userConfigPath);
const jit = createJiti(__filename, {
interopDefault: true,
esmResolve: true,
});
const configModule = await jit(configPath);
const resolvedConfig = (
Expand Down
3 changes: 3 additions & 0 deletions packages/create-module-federation/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["../.eslintrc.json"]
}
3 changes: 3 additions & 0 deletions packages/data-prefetch/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["../.eslintrc.json"]
}
1 change: 1 addition & 0 deletions packages/data-prefetch/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { fileExistsWithCaseSync, fixPrefetchPath } from '../common/node-utils';
import { getPrefetchId } from '../common/runtime-utils';
import { SHARED_STRATEGY } from '../constant';

// eslint-disable-next-line @typescript-eslint/no-require-imports
const { RuntimeGlobals, Template } = require(
normalizeWebpackPath('webpack'),
) as typeof import('webpack');
Expand Down
3 changes: 3 additions & 0 deletions packages/dts-plugin/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["../.eslintrc.json"]
}
2 changes: 2 additions & 0 deletions packages/dts-plugin/src/core/lib/DtsWorker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ describe('generateTypesInChildProcess', () => {
it('generateTypesInChildProcess', async () => {
// createRpcWorker will use dist assets , so it need to test dist
const { DtsWorker } =
// eslint-disable-next-line @typescript-eslint/no-require-imports
require('../../../dist/core') as typeof import('../index');
const dtsWorker = new DtsWorker({
host: hostOptions,
Expand Down Expand Up @@ -273,6 +274,7 @@ describe('DtsWorker Unit Tests', () => {
vi.spyOn(console, 'error').mockImplementation(() => {});
originalKill = process.kill;
originalDebugMode = isDebugMode;
// eslint-disable-next-line @typescript-eslint/no-require-imports
DtsWorkerClass = require('../../../dist/core').DtsWorker;
// Reset isDebugMode for each test
vi.mock('./utils', () => ({
Expand Down
1 change: 1 addition & 0 deletions packages/dts-plugin/src/core/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function getDTSManagerConstructor(
implementation?: string,
): typeof DTSManager {
if (implementation) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const NewConstructor = require(implementation);
return NewConstructor.default ? NewConstructor.default : NewConstructor;
}
Expand Down
2 changes: 0 additions & 2 deletions packages/dts-plugin/src/server/broker/Broker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,6 @@ export class Broker {
client,
);
fileLog(
// eslint-disable-next-line @ies/eden/max-calls-in-template
`[${
ActionKind.ADD_SUBSCRIBER
}]: ${identifier} has been started, Adding Subscriber ${subscriberName} Succeed, this.__publisherMap are: ${JSON.stringify(
Expand All @@ -414,7 +413,6 @@ export class Broker {
},
);
fileLog(
// eslint-disable-next-line @ies/eden/max-calls-in-template
`[${ActionKind.ADD_SUBSCRIBER}]: notifySubscriber Subscriber ${subscriberName}, updateMode: "PASSIVE", updateSourcePaths: ${registeredPublisher.name}`,
'Broker',
'info',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,90 @@ const { mkdirpSync } = require(
normalizeWebpackPath('webpack/lib/util/fs'),
) as typeof import('webpack/lib/util/fs');

function resolveRuntimePaths(implementation?: string) {
const ext = process.env.IS_ESM_BUILD === 'true' ? '.js' : '.cjs';
const runtimeToolsSpec = `@module-federation/runtime-tools/dist/index${ext}`;
const bundlerRuntimeSpec = `@module-federation/webpack-bundler-runtime/dist/index${ext}`;
const runtimeSpec = `@module-federation/runtime/dist/index${ext}`;
type ResolveFn = typeof require.resolve;
type RuntimeEntrySpec = {
bundler: string;
esm: string;
cjs: string;
};

function resolveRuntimeEntry(
spec: RuntimeEntrySpec,
implementation: string | undefined,
resolve: ResolveFn = require.resolve,
) {
const candidates = [spec.bundler, spec.esm, spec.cjs];
const modulePaths = implementation ? [implementation] : undefined;
let lastError: unknown;

for (const candidate of candidates) {
try {
return modulePaths
? resolve(candidate, { paths: modulePaths })
: resolve(candidate);
} catch (error) {
lastError = error;
}
}

const runtimeToolsPath = require.resolve(runtimeToolsSpec);
const modulePaths = implementation ? [implementation] : [runtimeToolsPath];
throw lastError;
}

function resolveRuntimeEntryWithFallback(
spec: RuntimeEntrySpec,
implementation: string | undefined,
resolve: ResolveFn = require.resolve,
) {
if (implementation) {
try {
return resolveRuntimeEntry(spec, implementation, resolve);
} catch {
// Fall back to the workspace runtime packages when a custom
// implementation hasn't published the newer subpath yet.
}
}

return resolveRuntimeEntry(spec, undefined, resolve);
}

export function resolveRuntimePaths(
implementation?: string,
resolve: ResolveFn = require.resolve,
) {
// Prefer the dedicated bundler subpath so webpack can tree-shake across the
// runtime package boundary. Fall back to the legacy dist contract for older
// custom implementations that have not published /bundler yet.
const runtimeToolsPath = resolveRuntimeEntryWithFallback(
{
bundler: '@module-federation/runtime-tools/bundler',
esm: '@module-federation/runtime-tools/dist/index.js',
cjs: '@module-federation/runtime-tools/dist/index.cjs',
},
implementation,
resolve,
);
const moduleBase = implementation || runtimeToolsPath;

return {
runtimeToolsPath,
bundlerRuntimePath: require.resolve(bundlerRuntimeSpec, {
paths: modulePaths,
}),
runtimePath: require.resolve(runtimeSpec, {
paths: modulePaths,
}),
bundlerRuntimePath: resolveRuntimeEntry(
{
bundler: '@module-federation/webpack-bundler-runtime/bundler',
esm: '@module-federation/webpack-bundler-runtime/dist/index.js',
cjs: '@module-federation/webpack-bundler-runtime/dist/index.cjs',
},
moduleBase,
resolve,
),
runtimePath: resolveRuntimeEntry(
{
bundler: '@module-federation/runtime/bundler',
esm: '@module-federation/runtime/dist/index.js',
cjs: '@module-federation/runtime/dist/index.cjs',
},
moduleBase,
resolve,
),
};
}

Expand Down
136 changes: 129 additions & 7 deletions packages/enhanced/test/unit/container/FederationRuntimePlugin.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import FederationRuntimePlugin from '../../../src/lib/container/runtime/FederationRuntimePlugin';
import FederationRuntimePlugin, {
resolveRuntimePaths,
} from '../../../src/lib/container/runtime/FederationRuntimePlugin';
import type { Compiler } from 'webpack';
import { rs, Mock } from '@rstest/core';

Expand Down Expand Up @@ -216,7 +218,7 @@ describe('FederationRuntimePlugin runtimePluginCalls', () => {
}
});

it('prefers cjs runtime entry when IS_ESM_BUILD is false', () => {
it('prefers the bundler runtime entry when IS_ESM_BUILD is false', () => {
process.env.IS_ESM_BUILD = 'false';
const plugin = new FederationRuntimePlugin({
implementation: '/legacy/runtime-tools',
Expand All @@ -226,11 +228,131 @@ describe('FederationRuntimePlugin runtimePluginCalls', () => {
} as unknown as Compiler);

expect(normalizePath(runtimePath)).toMatch(
/\/runtime\/dist\/index\.cjs(?:\.cjs)?$/,
/\/runtime\/dist\/bundler\.js$/,
);
});

it('prefers esm runtime entry when IS_ESM_BUILD is true', () => {
it('falls back to legacy esm runtime entries for older implementations', () => {
const resolve = rs.fn(
(request: string, options?: { paths?: string[] }) => {
const basedFromLegacy =
options?.paths?.[0] === '/legacy/runtime-tools';

if (request === '@module-federation/runtime-tools/bundler') {
return '/workspace/runtime-tools/dist/bundler.js';
}
if (basedFromLegacy && request.endsWith('/bundler')) {
throw new Error(`Cannot find module '${request}'`);
}
if (request === '@module-federation/runtime/dist/index.js') {
return '/legacy/runtime/dist/index.js';
}
if (
request ===
'@module-federation/webpack-bundler-runtime/dist/index.js'
) {
return '/legacy/webpack-bundler-runtime/dist/index.js';
}

throw new Error(`Unexpected request: ${request}`);
},
);

const resolved = resolveRuntimePaths('/legacy/runtime-tools', resolve);

expect(normalizePath(resolved.runtimeToolsPath)).toBe(
'/workspace/runtime-tools/dist/bundler.js',
);
expect(normalizePath(resolved.runtimePath)).toBe(
'/legacy/runtime/dist/index.js',
);
expect(normalizePath(resolved.bundlerRuntimePath)).toBe(
'/legacy/webpack-bundler-runtime/dist/index.js',
);
});

it('prefers the provided runtime-tools implementation when available', () => {
const resolve = rs.fn(
(request: string, options?: { paths?: string[] }) => {
const basedFromLegacy =
options?.paths?.[0] === '/legacy/runtime-tools';

if (
basedFromLegacy &&
request === '@module-federation/runtime-tools/bundler'
) {
return '/legacy/runtime-tools/dist/bundler.js';
}
if (
basedFromLegacy &&
request === '@module-federation/runtime/bundler'
) {
return '/legacy/runtime/dist/bundler.js';
}
if (
basedFromLegacy &&
request === '@module-federation/webpack-bundler-runtime/bundler'
) {
return '/legacy/webpack-bundler-runtime/dist/bundler.js';
}

throw new Error(`Unexpected request: ${request}`);
},
);

const resolved = resolveRuntimePaths('/legacy/runtime-tools', resolve);

expect(normalizePath(resolved.runtimeToolsPath)).toBe(
'/legacy/runtime-tools/dist/bundler.js',
);
expect(normalizePath(resolved.runtimePath)).toBe(
'/legacy/runtime/dist/bundler.js',
);
expect(normalizePath(resolved.bundlerRuntimePath)).toBe(
'/legacy/webpack-bundler-runtime/dist/bundler.js',
);
});

it('falls back to legacy cjs runtime entries when esm legacy builds are unavailable', () => {
const resolve = rs.fn(
(request: string, options?: { paths?: string[] }) => {
const basedFromLegacy =
options?.paths?.[0] === '/legacy/runtime-tools';

if (request === '@module-federation/runtime-tools/bundler') {
return '/workspace/runtime-tools/dist/bundler.js';
}
if (
basedFromLegacy &&
(request.endsWith('/bundler') || request.endsWith('/dist/index.js'))
) {
throw new Error(`Cannot find module '${request}'`);
}
if (request === '@module-federation/runtime/dist/index.cjs') {
return '/legacy/runtime/dist/index.cjs';
}
if (
request ===
'@module-federation/webpack-bundler-runtime/dist/index.cjs'
) {
return '/legacy/webpack-bundler-runtime/dist/index.cjs';
}

throw new Error(`Unexpected request: ${request}`);
},
);

const resolved = resolveRuntimePaths('/legacy/runtime-tools', resolve);

expect(normalizePath(resolved.runtimePath)).toBe(
'/legacy/runtime/dist/index.cjs',
);
expect(normalizePath(resolved.bundlerRuntimePath)).toBe(
'/legacy/webpack-bundler-runtime/dist/index.cjs',
);
});

it('prefers the bundler runtime entry when IS_ESM_BUILD is true', () => {
process.env.IS_ESM_BUILD = 'true';
const plugin = new FederationRuntimePlugin({
implementation: '/legacy/runtime-tools',
Expand All @@ -243,7 +365,7 @@ describe('FederationRuntimePlugin runtimePluginCalls', () => {
} as unknown as Compiler);

expect(normalizePath(runtimePath)).toMatch(
/\/runtime\/dist\/index\.(?:js|esm\.js)$/,
/\/runtime\/dist\/bundler\.js$/,
);
});

Expand All @@ -267,7 +389,7 @@ describe('FederationRuntimePlugin runtimePluginCalls', () => {
'@module-federation/runtime-tools$'
],
),
).toMatch(/\/runtime-tools\/dist\/index\.cjs(?:\.cjs)?$/);
).toMatch(/\/runtime-tools\/dist\/bundler\.js$/);
});

it('resolves runtime-tools alias for ESM mode when runtime alias is preset', () => {
Expand All @@ -290,7 +412,7 @@ describe('FederationRuntimePlugin runtimePluginCalls', () => {
'@module-federation/runtime-tools$'
],
),
).toMatch(/\/runtime-tools\/dist\/index\.(?:js|esm\.js)$/);
).toMatch(/\/runtime-tools\/dist\/bundler\.js$/);
});
});
});
3 changes: 3 additions & 0 deletions packages/error-codes/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["../.eslintrc.json"]
}
3 changes: 3 additions & 0 deletions packages/managers/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["../.eslintrc.json"]
}
Loading
Loading