Skip to content

Commit

Permalink
refactor(esbuild): split up plugin source
Browse files Browse the repository at this point in the history
  • Loading branch information
ScriptedAlchemy committed May 17, 2024
1 parent 34d20c4 commit 42ba8c6
Show file tree
Hide file tree
Showing 7 changed files with 352 additions and 329 deletions.
7 changes: 3 additions & 4 deletions packages/esbuild/src/adapters/lib/containerPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { OnResolveArgs, OnLoadArgs, PluginBuild } from 'esbuild';
import { createContainerCode } from '../../lib/core/createContainerTemplate.js';

const buildContainerHost = (config: any) => {
//@ts-ignore
const buildContainerHost = ({ config }) => {
const { name, remotes = {}, shared = {}, exposes = {} } = config;

const remoteConfigs = Object.entries(remotes).map(
Expand Down Expand Up @@ -75,7 +75,6 @@ const buildContainerHost = (config: any) => {
name: 'import-maps-plugin',
async init(args) {
const remotePrefetch = args.options.remotes.map(async (remote) => {
console.log('remote', remote);
if (remote.type === 'esm') {
await import(remote.entry);
}
Expand All @@ -84,6 +83,7 @@ const buildContainerHost = (config: any) => {
await Promise.all(remotePrefetch);
console.log('module map',moduleMap);
const map = Object.keys(moduleMap).reduce((acc, expose) => {
const importMap = importShim.getImportMap().imports;
const key = args.origin.name + expose.replace('.', '');
Expand All @@ -95,7 +95,6 @@ const buildContainerHost = (config: any) => {
}
return acc;
}, {});
await importShim.addImportMap({ imports: map });
console.log('final map', importShim.getImportMap());
Expand Down
130 changes: 130 additions & 0 deletions packages/esbuild/src/adapters/lib/containerReference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { federationBuilder } from '../../lib/core/federation-builder';
import fs from 'fs';

// Builds the federation host code
export const buildFederationHost = () => {
const { name, remotes, shared } = federationBuilder.config;

const remoteConfigs = remotes
? JSON.stringify(
Object.entries(remotes).map(([remoteAlias, remote]) => ({
name: remoteAlias,
entry: remote,
alias: remoteAlias,
type: 'esm',
})),
)
: '[]';

const sharedConfig =
Object.entries(shared).reduce((acc, [pkg, config]) => {
const version = config.requiredVersion?.replace(/^[^0-9]/, '') || '';
acc += `${JSON.stringify(pkg)}: {
"package": "${pkg}",
"version": "${version}",
"scope": "default",
"get": async () => await import('federationShare/${pkg}'),
"shareConfig": {
"singleton": ${config.singleton},
"requiredVersion": "${config.requiredVersion}",
"eager": ${config.eager},
"strictVersion": ${config.strictVersion}
}
},\n`;
return acc;
}, '{') + '}';
return `
import { init as initFederationHost } from "@module-federation/runtime";
export const createVirtualRemoteModule = (name, ref, exports) => {
const genExports = exports.map(e =>
e === 'default'
? 'export default mfLsZJ92.default;'
: \`export const \${e} = mfLsZJ92[\${JSON.stringify(e)}];\`
).join('');
const loadRef = \`const mfLsZJ92 = await container.loadRemote(\${JSON.stringify(ref)});\`;
return \`
const container = __FEDERATION__.__INSTANCES__.find(container => container.name === name) || __FEDERATION__.__INSTANCES__[0];
\${loadRef}
\${genExports}
\`;
};
function encodeInlineESM(code) {
return 'data:text/javascript;charset=utf-8,' + encodeURIComponent(code);
}
const runtimePlugin = () => ({
name: 'import-maps-plugin',
async init(args) {
const remotePrefetch = args.options.remotes.map(async (remote) => {
console.log('remote', remote);
if (remote.type === 'esm') {
await import(remote.entry);
}
});
await Promise.all(remotePrefetch);
if (typeof moduleMap !== 'undefined') {
const map = Object.keys(moduleMap).reduce((acc, expose) => {
const importMap = importShim.getImportMap().imports;
const key = args.origin.name + expose.replace('.', '');
if (!importMap[key]) {
const encodedModule = encodeInlineESM(
createVirtualRemoteModule(args.origin.name, key, moduleMap[expose].exports)
);
acc[key] = encodedModule;
}
return acc;
}, {});
await importShim.addImportMap({ imports: map });
}
return args;
}
});
initFederationHost({
name: ${JSON.stringify(name)},
remotes: ${remoteConfigs},
shared: ${sharedConfig},
plugins: [runtimePlugin()],
});
`;
};

export const initializeHostPlugin = {
name: 'host-initialization',
setup(build: any) {
build.onResolve({ filter: /federation-host/ }, (args: any) => ({
path: args.path,
namespace: 'federation-host',
pluginData: { kind: args.kind, resolveDir: args.resolveDir },
}));

build.onLoad(
{ filter: /.*/, namespace: 'federation-host' },
async (args: any) => ({
contents: buildFederationHost(),
resolveDir: args.pluginData.resolveDir,
}),
);

build.onLoad(
{ filter: /.*\.(ts|js|mjs)$/, namespace: 'file' },
async (args: any) => {
if (
!build.initialOptions.entryPoints.some((e: string) =>
args.path.includes(e),
)
)
return;
const contents = await fs.promises.readFile(args.path, 'utf8');
return { contents: buildFederationHost() + contents };
},
);
},
};
47 changes: 47 additions & 0 deletions packages/esbuild/src/adapters/lib/linkRemotesPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { federationBuilder } from '../../lib/core/federation-builder';
import path from 'path';

// relys on import map since i dont know the named exports of a remote to return.
export const createVirtualRemoteModule = (name: string, ref: string) => `
export * from ${JSON.stringify('federationRemote/' + ref)}
`;

export const linkRemotesPlugin = {
name: 'linkRemotes',
setup(build: any) {
//@ts-ignore
const remotes = federationBuilder.config.remotes || {};
const filter = new RegExp(
Object.keys(remotes)
.reduce((acc, key) => {
if (!key) return acc;
acc.push(`^${key}`);
return acc;
}, [] as string[])
.join('|'),
);

build.onResolve({ filter: filter }, async (args: any) => {
return { path: args.path, namespace: 'remote-module' };
});

build.onResolve({ filter: /^federationRemote/ }, async (args: any) => {
return {
path: args.path.replace('federationRemote/', ''),
external: true,
namespace: 'externals',
};
});

build.onLoad({ filter, namespace: 'remote-module' }, async (args: any) => {
return {
contents: createVirtualRemoteModule(
federationBuilder.config.name,
args.path,
),
loader: 'js',
resolveDir: path.dirname(args.path),
};
});
},
};
2 changes: 1 addition & 1 deletion packages/esbuild/src/adapters/lib/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export const writeRemoteManifest = async (config, result) => {
});

const exposes = await Promise.all(
Object.entries(mfConfig.exposes).map(async ([expose, value]) => {
Object.entries(mfConfig.exposes).map(([expose, value]) => {
const exposedFound = outputMapWithoutExt[value.replace('./', '')];
const chunks = getChunks(exposedFound, outputMap);

Expand Down
Loading

0 comments on commit 42ba8c6

Please sign in to comment.