Skip to content

Commit

Permalink
feat(sdk): auto public path support for json remote (#2463)
Browse files Browse the repository at this point in the history
Co-authored-by: ScriptedAlchemy <[email protected]>
Co-authored-by: 2heal1 <[email protected]>
  • Loading branch information
3 people authored May 10, 2024
1 parent 3344fc1 commit 2e52e51
Show file tree
Hide file tree
Showing 25 changed files with 111 additions and 26 deletions.
5 changes: 5 additions & 0 deletions .changeset/chatty-lies-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@module-federation/dts-plugin': patch
---

Build zip url for json ext as well
5 changes: 5 additions & 0 deletions .changeset/dull-pumas-bow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@module-federation/managers': patch
---

If library.name is not set, fallback to plugin name
6 changes: 6 additions & 0 deletions .changeset/young-apricots-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@module-federation/manifest': patch
'@module-federation/sdk': patch
---

publicPath: auto support for json manifest remote
10 changes: 10 additions & 0 deletions .cursorignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
./tmp
./scripts
./.git
./packages/storybook-addon
./packages/core
./packages/utilities
./packages/typescript
./packages/native-*
./apps
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/tmp
/out-tsc
/build
/@mf-types
**/@mf-types
**/@mf-types/**
/docs
/.nx
Expand Down
6 changes: 6 additions & 0 deletions apps/manifest-demo/3009-webpack-provider/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@
"hmr": true,
"port": 3009
},
"dependsOn": [
{
"target": "build",
"dependencies": true
}
],
"configurations": {
"development": {
"buildTarget": "3009-webpack-provider:build:development"
Expand Down
2 changes: 1 addition & 1 deletion apps/manifest-demo/3009-webpack-provider/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = composePlugins(
ignored: ['**/node_modules/**', '**/@mf-types/**'],
};
// publicPath must be specific url
config.output.publicPath = 'http://localhost:3009/';
config.output.publicPath = 'auto';
config.plugins.push(
new ModuleFederationPlugin({
name: 'webpack_provider',
Expand Down
6 changes: 6 additions & 0 deletions apps/manifest-demo/3010-rspack-provider/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
"buildTarget": "3010-rspack-provider:build",
"port": 3010
},
"dependsOn": [
{
"target": "build",
"dependencies": true
}
],
"configurations": {
"development": {
"buildTarget": "3010-rspack-provider:build:development",
Expand Down
6 changes: 6 additions & 0 deletions apps/manifest-demo/3011-rspack-manifest-provider/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
"buildTarget": "3011-rspack-manifest-provider:build",
"port": 3011
},
"dependsOn": [
{
"target": "build",
"dependencies": true
}
],
"configurations": {
"development": {
"buildTarget": "3011-rspack-manifest-provider:build:development",
Expand Down
6 changes: 6 additions & 0 deletions apps/manifest-demo/3012-rspack-js-entry-provider/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
"buildTarget": "3012-rspack-js-entry-provider:build",
"port": 3012
},
"dependsOn": [
{
"target": "build",
"dependencies": true
}
],
"configurations": {
"development": {
"buildTarget": "3012-rspack-js-entry-provider:build:development",
Expand Down
2 changes: 1 addition & 1 deletion apps/node-remote/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module.exports = composePlugins(withNx(), (config) => {
require.resolve('@module-federation/node/runtimePlugin'),
],
name: 'node_remote',
library: { type: 'commonjs-module' },
library: { type: 'commonjs-module', name: 'node_remote' },
filename: 'remoteEntry.js',
exposes: {
'./test': './src/expose.js',
Expand Down
7 changes: 5 additions & 2 deletions apps/website-new/docs/en/guide/basic/webpack.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,18 @@ import { PackageManagerTabs } from '@theme';

In `Webpack`, you can add the plugin through the `plugins` configuration item in the `webpack.config.js` file:

:::warning Public Path Auto & Manifest
When using mf-manifest.json remotes `publicPath: 'auto'` support is experimental
:::

```ts title='webpack.config.js'
import { ModuleFederationPlugin } from '@module-federation/enhanced/webpack';
module.exports = {
devServer: {
port: 2000,
},
output: {
// publicPath must be configured if using manifest
publicPath: 'http://localhost:2000/',
publicPath: 'http://localhost:2000/', // or auto
},
plugins: [
new ModuleFederationPlugin({
Expand Down
6 changes: 5 additions & 1 deletion apps/website-new/docs/zh/guide/basic/webpack.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ import { PackageManagerTabs } from '@theme';

`Webpack` 中,你可以通过 `webpack.config.js` 配置文件中的 `plugins` 配置项来添加插件:

:::warning 公共路径自动配置与 Manifest
当使用 mf-manifest.json 远程模块时,`publicPath: 'auto'` 的支持还处于实验阶段
:::

```ts title='webpack.config.js'
import { ModuleFederationPlugin } from '@module-federation/enhanced/webpack';
module.exports = {
Expand All @@ -35,7 +39,7 @@ module.exports = {
},
output: {
// 使用 manifest 必须要配置 publicPath
publicPath: 'http://localhost:2000/',
publicPath: 'http://localhost:2000/', //or 'auto'
},
plugins: [
new ModuleFederationPlugin({
Expand Down
4 changes: 1 addition & 3 deletions packages/dts-plugin/src/core/configurations/hostPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ const defaultOptions = {
const buildZipUrl = (hostOptions: Required<HostOptions>, url: string) => {
const remoteUrl = new URL(url);

if (remoteUrl.href.includes(MANIFEST_EXT)) {
return undefined;
}
const pathnameWithoutEntry = remoteUrl.pathname
.split('/')
.slice(0, -1)
Expand Down Expand Up @@ -51,6 +48,7 @@ const retrieveRemoteInfo = (options: {
: parsedInfo.name === remote
? remote
: '';

const zipUrl = url ? buildZipUrl(hostOptions, url) : '';

return {
Expand Down
17 changes: 12 additions & 5 deletions packages/dts-plugin/src/core/lib/DTSManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import ansiColors from 'ansi-colors';
import path from 'path';
import { rm } from 'fs/promises';
import fs from 'fs';
import { MANIFEST_EXT, Manifest } from '@module-federation/sdk';
import {
MANIFEST_EXT,
Manifest,
inferAutoPublicPath,
} from '@module-federation/sdk';
import cloneDeepWith from 'lodash.clonedeepwith';

import { retrieveRemoteConfig } from '../configurations/remotePlugin';
Expand All @@ -22,7 +26,6 @@ import {
HOST_API_TYPES_FILE_NAME,
} from '../constant';
import axios from 'axios';
import { replaceLocalhost } from './utils';
import { fileLog } from '../../server';

export const MODULE_DTS_MANAGER_IDENTIFIER = 'MF DTS Manager';
Expand Down Expand Up @@ -171,7 +174,7 @@ class DTSManager {
if (!remoteInfo.url.includes(MANIFEST_EXT)) {
return remoteInfo as Required<RemoteInfo>;
}
const url = replaceLocalhost(remoteInfo.url);
const url = remoteInfo.url;
const res = await axios({
method: 'get',
url,
Expand All @@ -186,10 +189,14 @@ class DTSManager {
}
return u;
};
const publicPath =

let publicPath =
'publicPath' in manifestJson.metaData
? manifestJson.metaData.publicPath
: new Function(manifestJson.metaData.getPublicPath)();
if (publicPath === 'auto') {
publicPath = inferAutoPublicPath(remoteInfo.url);
}

remoteInfo.zipUrl = new URL(
path.join(addProtocol(publicPath), manifestJson.metaData.types.zip),
Expand Down Expand Up @@ -233,7 +240,7 @@ class DTSManager {
return;
}
try {
const url = replaceLocalhost(apiTypeUrl);
const url = apiTypeUrl;
const res = await axios.get(url);
let apiTypeFile = res.data as string;
apiTypeFile = apiTypeFile.replaceAll(
Expand Down
3 changes: 1 addition & 2 deletions packages/dts-plugin/src/core/lib/archiveHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import typescript from 'typescript';
import { HostOptions } from '../interfaces/HostOptions';
import { RemoteOptions } from '../interfaces/RemoteOptions';
import { retrieveMfTypesPath } from './typeScriptCompiler';
import { replaceLocalhost } from './utils';
import { fileLog } from '../../server';

export const retrieveTypesZipPath = (
Expand Down Expand Up @@ -59,7 +58,7 @@ export const downloadTypesArchive = (hostOptions: Required<HostOptions>) => {

while (retries++ < hostOptions.maxRetries) {
try {
const url = replaceLocalhost(fileToDownload);
const url = fileToDownload;
const response = await axios
.get(url, { responseType: 'arraybuffer' })
.catch(downloadErrorLogger(destinationFolder, url));
Expand Down
4 changes: 0 additions & 4 deletions packages/dts-plugin/src/core/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ export function retrieveTypesAssetsInfo(options: RemoteOptions) {
}
}

export function replaceLocalhost(url: string): string {
return url.replace('localhost', '127.0.0.1');
}

export function isDebugMode() {
return Boolean(process.env['FEDERATION_DEBUG']);
}
Expand Down
4 changes: 3 additions & 1 deletion packages/managers/__tests__/ContainerManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ describe('ContainerManager', () => {
const containerManager = new ContainerManager();
containerManager.init(options);

expect(containerManager.globalEntryName).toEqual(undefined);
expect(containerManager.globalEntryName).toEqual(
'@module-federation/container-managers-test',
);
});

it('set expose name by default', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/managers/src/ContainerManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class ContainerManager extends BasicPluginOptionsManager<moduleFederationPlugin.
if (typeof library.name === 'string') {
return library.name;
}
return undefined;
return name;
}

return name;
Expand Down
4 changes: 3 additions & 1 deletion packages/manifest/src/ManifestManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ class ManifestManager {

if (isDev()) {
console.log(
chalk`{bold {greenBright [ ${PLUGIN_IDENTIFIER} ]} {greenBright Manifest Link:} {cyan ${publicPath}${manifestFileName}}}`,
chalk`{bold {greenBright [ ${PLUGIN_IDENTIFIER} ]} {greenBright Manifest Link:} {cyan ${
publicPath === 'auto' ? '{auto}/' : publicPath
}${manifestFileName}}}`,
);
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/manifest/src/StatsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,9 +440,9 @@ class StatsManager {
return false;
} else if (publicPath === 'auto') {
console.warn(
chalk`{bold {yellow [ ${PLUGIN_IDENTIFIER} ]: Manifest will not generate, because publicPath can only be absolute path, but got '${publicPath}'}}`,
chalk`{bold {blue [ ${PLUGIN_IDENTIFIER} ]: Manifest will use absolute path resolution via its host at runtime, reason: publicPath='${publicPath}'}}`,
);
return false;
return true;
}

return true;
Expand Down
2 changes: 1 addition & 1 deletion packages/node/src/runtimePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ export default function () {
}

__webpack_require__.federation.runtime
.loadScriptNode(url, { attrs: {} })
.loadScriptNode(url, { attrs: { globalName: remoteName } })
.then(function (res) {
var federation = __webpack_require__.federation;
var enhancedRemote = federation.instance.initRawContainer(
Expand Down
12 changes: 12 additions & 0 deletions packages/sdk/__tests__/inferAutoPublicPath.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { inferAutoPublicPath } from '../src';

describe('inferAutoPublicPath', () => {
it('should infer correct public path', () => {
expect(inferAutoPublicPath('http://localhost:3009/mf-stats.json')).toEqual(
'http://localhost:3009/',
);
expect(inferAutoPublicPath('http://localhost:3009/remoteEntry.js')).toEqual(
'http://localhost:3009/',
);
});
});
11 changes: 11 additions & 0 deletions packages/sdk/src/generateSnapshotFromManifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ export const simpleJoinRemoteEntry = (rPath: string, rName: string): string => {
return `${transformedPath}/${rName}`;
};

export function inferAutoPublicPath(url: string): string {
return url
.replace(/#.*$/, '')
.replace(/\?.*$/, '')
.replace(/\/[^\/]+$/, '/');
}

// Priority: overrides > remotes
// eslint-disable-next-line max-lines-per-function
export function generateSnapshotFromManifest(
Expand All @@ -59,6 +66,10 @@ export function generateSnapshotFromManifest(

const getPublicPath = (): string => {
if ('publicPath' in manifest.metaData) {
if (manifest.metaData.publicPath === 'auto' && version) {
// use same implementation as publicPath auto runtime module implements
return inferAutoPublicPath(version);
}
return manifest.metaData.publicPath;
} else {
return manifest.metaData.getPublicPath;
Expand Down
1 change: 1 addition & 0 deletions packages/sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export {
generateSnapshotFromManifest,
isManifestProvider,
simpleJoinRemoteEntry,
inferAutoPublicPath,
} from './generateSnapshotFromManifest';
export * from './logger';
export * from './env';
Expand Down

0 comments on commit 2e52e51

Please sign in to comment.