Skip to content

Commit 92eb2c2

Browse files
committed
Fix multiple react imports during runtime
1 parent cfaa562 commit 92eb2c2

File tree

2 files changed

+112
-11
lines changed

2 files changed

+112
-11
lines changed

packages/lib/src/prod/remote-production.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import { walk } from 'estree-walker'
1717
import MagicString from 'magic-string'
1818
import type { AcornNode, TransformPluginContext } from 'rollup'
19-
import type { ConfigTypeSet, VitePluginFederationOptions } from 'types'
19+
import type { VitePluginFederationOptions } from 'types'
2020
import type { PluginHooks } from '../../types/pluginHooks'
2121
import {
2222
builderInfo,
@@ -31,11 +31,6 @@ import {
3131
REMOTE_FROM_PARAMETER
3232
} from '../utils'
3333

34-
const sharedFileName2Prop: Map<string, ConfigTypeSet> = new Map<
35-
string,
36-
ConfigTypeSet
37-
>()
38-
3934
export function prodRemotePlugin(
4035
options: VitePluginFederationOptions
4136
): PluginHooks {
@@ -476,5 +471,3 @@ export function prodRemotePlugin(
476471
}
477472
}
478473
}
479-
480-
export { sharedFileName2Prop }

packages/lib/src/prod/shared-production.ts

Lines changed: 111 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,24 @@ import type { PluginHooks } from '../../types/pluginHooks'
1717
import { NAME_CHAR_REG, parseSharedOptions, removeNonRegLetter } from '../utils'
1818
import { parsedOptions } from '../public'
1919
import type { ConfigTypeSet, VitePluginFederationOptions } from 'types'
20+
import { walk } from 'estree-walker'
21+
import MagicString from 'magic-string'
2022
import { basename, join, resolve } from 'path'
2123
import { readdirSync, readFileSync, statSync } from 'fs'
22-
const sharedFilePathReg = /__federation_shared_(.+)-.{8}\.js$/
24+
import type {
25+
NormalizedOutputOptions,
26+
OutputChunk,
27+
PluginContext
28+
} from 'rollup'
29+
2330
import federation_fn_import from './federation_fn_import.js?raw'
2431

32+
const sharedFilePathReg = /__federation_shared_(.+)-.{8}\.js$/
33+
const getSharedName = (importName: string) => {
34+
const regRst = sharedFilePathReg.exec(importName)
35+
return regRst?.[1]
36+
}
37+
2538
export function prodSharedPlugin(
2639
options: VitePluginFederationOptions
2740
): PluginHooks {
@@ -34,6 +47,85 @@ export function prodSharedPlugin(
3447
let isRemote
3548
const id2Prop = new Map<string, any>()
3649

50+
const transformImportFn = function (
51+
this: PluginContext,
52+
code,
53+
chunk: OutputChunk
54+
) {
55+
const ast = this.parse(code)
56+
const magicString = new MagicString(code)
57+
let importSharedRequired = false
58+
let importSharedFound = false
59+
let modified = false
60+
61+
walk(ast, {
62+
enter(node: any) {
63+
if (node.type === 'ImportDeclaration') {
64+
if (
65+
node.source.value.includes('__federation_fn_import-') &&
66+
node.specifiers.some(
67+
(specify) => specify.imported?.name === 'importShared'
68+
)
69+
) {
70+
importSharedFound = true
71+
}
72+
73+
const sharedName = getSharedName(node.source.value)
74+
if (sharedName) {
75+
const declaration: (string | never)[] = []
76+
if (!node.specifiers?.length) {
77+
// invalid import , like import './__federation_shared_lib.js' , and remove it
78+
magicString.remove(node.start, node.end)
79+
modified = true
80+
} else {
81+
node.specifiers.forEach((specify) => {
82+
declaration.push(
83+
`${
84+
specify.imported?.name
85+
? `${
86+
specify.imported.name === specify.local.name
87+
? specify.local.name
88+
: `${specify.imported.name}:${specify.local.name}`
89+
}`
90+
: `default:${specify.local.name}`
91+
}`
92+
)
93+
})
94+
}
95+
if (declaration.length) {
96+
magicString.overwrite(
97+
node.start,
98+
node.end,
99+
`const {${declaration.join(
100+
','
101+
)}} = await importShared('${sharedName}');\n`
102+
)
103+
importSharedRequired = true
104+
modified = true
105+
}
106+
}
107+
}
108+
}
109+
})
110+
if (importSharedRequired && !importSharedFound) {
111+
const prop = id2Prop.get(chunk.facadeModuleId as string)
112+
magicString.prepend(
113+
`import {importShared} from '${
114+
prop?.root ? '.' : ''
115+
}./__federation_fn_import.js';\n`
116+
)
117+
}
118+
if (modified) {
119+
return {
120+
code: magicString.toString(),
121+
map: magicString.generateMap({
122+
source: chunk.map?.file,
123+
hires: true
124+
})
125+
}
126+
}
127+
}
128+
37129
return {
38130
name: 'originjs:shared-production',
39131
virtualFile: {
@@ -190,9 +282,25 @@ export function prodSharedPlugin(
190282
const chunk = bundle[key]
191283
if (chunk.type === 'chunk') {
192284
if (!isHost) {
193-
const regRst = sharedFilePathReg.exec(chunk.fileName)
194-
if (regRst && shareName2Prop.get(regRst[1])?.generate === false) {
285+
const sharedName = getSharedName(chunk.fileName)
286+
if (
287+
sharedName &&
288+
shareName2Prop.get(sharedName)?.generate === false
289+
) {
195290
needRemoveShared.add(key)
291+
continue
292+
}
293+
const hasSharedImport = chunk.imports?.some((name) =>
294+
sharedFilePathReg.test(name)
295+
)
296+
297+
if (hasSharedImport && options.format === 'es') {
298+
const transformedCode = transformImportFn.apply(this, [
299+
chunk.code,
300+
chunk
301+
])
302+
chunk.code = transformedCode?.code ?? chunk.code
303+
chunk.map = transformedCode?.map ?? chunk.map
196304
}
197305
}
198306
}

0 commit comments

Comments
 (0)