Skip to content

Commit 3fa77a3

Browse files
authored
fix: vite 2.9.0 causes manualChunks failed (#183)
1 parent 717495b commit 3fa77a3

File tree

4 files changed

+78
-41
lines changed

4 files changed

+78
-41
lines changed

.husky/pre-commit

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/bin/sh
22
. "$(dirname "$0")/_/husky.sh"
33

4-
pnpm run lint-staged --workspace-concurrency false
4+
pnpm run lint-staged

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@
4646
},
4747
"lint-staged": {
4848
"*.{ts,js,json,tsx,jsx,vue}": [
49-
"eslint",
49+
"prettier --write",
5050
"eslint --cache --fix",
51-
"prettier --write"
51+
"eslint"
5252
]
5353
}
5454
}

packages/lib/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ export default function federation(
148148
},
149149

150150
outputOptions(outputOptions) {
151-
outputOptions.manualChunks = outputOptions.manualChunks || {}
152151
for (const pluginHook of pluginList) {
153152
pluginHook.outputOptions?.call(this, outputOptions)
154153
}

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

Lines changed: 75 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,22 @@ import type { PluginHooks } from '../../types/pluginHooks'
22
import {
33
findDependencies,
44
getModuleMarker,
5-
parseOptions, removeNonRegLetter
5+
parseOptions,
6+
removeNonRegLetter
67
} from '../utils'
78
import { builderInfo, EXPOSES_MAP, parsedOptions } from '../public'
89
import type { ConfigTypeSet, VitePluginFederationOptions } from 'types'
910
import { walk } from 'estree-walker'
1011
import MagicString from 'magic-string'
1112
import { join, sep, resolve, basename } from 'path'
1213
import { readdirSync, statSync } from 'fs'
13-
import type { OutputOptions, PluginContext, OutputChunk, RenderedChunk } from 'rollup'
14-
import {sharedFileName2Prop} from "./remote-production";
14+
import type {
15+
OutputOptions,
16+
PluginContext,
17+
OutputChunk,
18+
RenderedChunk
19+
} from 'rollup'
20+
import { sharedFileName2Prop } from './remote-production'
1521
const sharedFileReg = /^__federation_shared_.+\.js$/
1622

1723
export function prodSharedPlugin(
@@ -42,7 +48,12 @@ export function prodSharedPlugin(
4248
const moduleCheckedSet = new Set<string>()
4349
const moduleNeedToTransformSet = new Set<string>() // record modules that import shard libs, and refered in chunk tranform logic
4450

45-
const transformImportFn = function (this: PluginContext, code, chunk: OutputChunk | RenderedChunk, options: OutputOptions) {
51+
const transformImportFn = function (
52+
this: PluginContext,
53+
code,
54+
chunk: OutputChunk | RenderedChunk,
55+
options: OutputOptions
56+
) {
4657
const ast = this.parse(code)
4758
const magicString = new MagicString(code)
4859
let modify = false
@@ -55,7 +66,9 @@ export function prodSharedPlugin(
5566
node.type === 'ImportDeclaration' &&
5667
sharedFileReg.test(basename(node.source.value))
5768
) {
58-
const sharedName = sharedFileName2Prop.get(basename(node.source.value))?.[0];
69+
const sharedName = sharedFileName2Prop.get(
70+
basename(node.source.value)
71+
)?.[0]
5972
if (sharedName) {
6073
const declaration: (string | never)[] = []
6174
node.specifiers?.forEach((specify) => {
@@ -106,8 +119,7 @@ export function prodSharedPlugin(
106119
: node.body.find(
107120
(item) =>
108121
item.type === 'ExpressionStatement' &&
109-
item.expression?.callee?.object?.name ===
110-
'System' &&
122+
item.expression?.callee?.object?.name === 'System' &&
111123
item.expression.callee.property?.name === 'register'
112124
)?.expression
113125
if (expression) {
@@ -135,21 +147,19 @@ export function prodSharedPlugin(
135147
args[1]?.type === 'FunctionExpression'
136148
) {
137149
const functionExpression = args[1]
138-
const returnStatement =
139-
functionExpression?.body?.body.find(
140-
(item) => item.type === 'ReturnStatement'
141-
)
150+
const returnStatement = functionExpression?.body?.body.find(
151+
(item) => item.type === 'ReturnStatement'
152+
)
142153

143154
if (returnStatement) {
144155
// insert __federation_import variable
145156
magicString.prependLeft(
146157
returnStatement.start,
147158
'var __federation_import;\n'
148159
)
149-
const setters =
150-
returnStatement.argument.properties.find(
151-
(property) => property.key.name === 'setters'
152-
)
160+
const setters = returnStatement.argument.properties.find(
161+
(property) => property.key.name === 'setters'
162+
)
153163
const settersElements = setters.value.elements
154164
// insert __federation_import setter
155165
magicString.appendRight(
@@ -158,10 +168,9 @@ export function prodSharedPlugin(
158168
removeLast ? '' : ','
159169
}function (module){__federation_import=module.importShared}`
160170
)
161-
const execute =
162-
returnStatement.argument.properties.find(
163-
(property) => property.key.name === 'execute'
164-
)
171+
const execute = returnStatement.argument.properties.find(
172+
(property) => property.key.name === 'execute'
173+
)
165174
const insertPos = execute.value.body.body[0].start
166175
importIndex.forEach((item) => {
167176
// remove unnecessary setters and import
@@ -179,7 +188,9 @@ export function prodSharedPlugin(
179188
: args[0].elements[item.index + 1].start - 1
180189
)
181190
// insert federation shared import lib
182-
const varName = `__federation_${removeNonRegLetter(item.name)}`
191+
const varName = `__federation_${removeNonRegLetter(
192+
item.name
193+
)}`
183194
magicString.prependLeft(
184195
insertPos,
185196
`var ${varName} = await __federation_import('${item.name}');\n`
@@ -202,9 +213,7 @@ export function prodSharedPlugin(
202213
// add sharedImport import declaration
203214
magicString.appendRight(
204215
args[0].end - 1,
205-
`${
206-
removeLast ? '' : ','
207-
}'./__federation_fn_import.js'`
216+
`${removeLast ? '' : ','}'./__federation_fn_import.js'`
208217
)
209218
modify = true
210219
}
@@ -454,33 +463,58 @@ export function prodSharedPlugin(
454463
const bIndex = priority.findIndex((value) => value === b[0])
455464
return aIndex - bIndex
456465
})
466+
467+
const manualChunkFunc = (id: string, obj: unknown) => {
468+
// if id is in shared dependencies, return id ,else return vite function value
469+
const find = parsedOptions.prodShared.find((arr) =>
470+
arr[1].dependencies.has(id)
471+
)
472+
return find ? find[0] : undefined
473+
}
474+
457475
// only active when manualChunks is function,array not to solve
458476
if (typeof outputOption.manualChunks === 'function') {
459477
outputOption.manualChunks = new Proxy(outputOption.manualChunks, {
460478
apply(target, thisArg, argArray) {
461-
const id = argArray[0]
462-
// if id is in shared dependencies, return id ,else return vite function value
463-
const find = parsedOptions.prodShared.find((arr) =>
464-
arr[1].dependencies.has(id)
465-
)
466-
return find ? find[0] : target(argArray[0], argArray[1])
479+
const result = manualChunkFunc(argArray[0], argArray[1])
480+
return result ? result : target(argArray[0], argArray[1])
467481
}
468482
})
469483
}
470484

485+
// The default manualChunk function is no longer available from vite 2.9.0
486+
if (outputOption.manualChunks === undefined) {
487+
outputOption.manualChunks = manualChunkFunc
488+
}
489+
471490
// handle expose component import other components which may import shared
472-
if (isRemote && parsedOptions.prodShared.length && parsedOptions.prodExpose.length) {
491+
if (
492+
isRemote &&
493+
parsedOptions.prodShared.length &&
494+
parsedOptions.prodExpose.length
495+
) {
473496
// start collect exposed modules and their dependency modules which imported shared libs
474-
const exposedModuleIds = parsedOptions.prodExpose.filter(item => !!item?.[1]?.id).map(item => item[1]['id'])
475-
const sharedLibIds = new Set( parsedOptions.prodShared.map(item => item?.[1]?.id).filter(item => !!item));
497+
const exposedModuleIds = parsedOptions.prodExpose
498+
.filter((item) => !!item?.[1]?.id)
499+
.map((item) => item[1]['id'])
500+
const sharedLibIds = new Set(
501+
parsedOptions.prodShared
502+
.map((item) => item?.[1]?.id)
503+
.filter((item) => !!item)
504+
)
476505

477-
const addDeps = id => {
506+
const addDeps = (id) => {
478507
if (moduleCheckedSet.has(id)) return
479508
moduleCheckedSet.add(id)
480509
const info = this.getModuleInfo(id)
481510
if (!info) return
482-
const dependencyModuleIds = [...info.importedIds, ...info.dynamicallyImportedIds]
483-
const isImportSharedLib = dependencyModuleIds.some(id => sharedLibIds.has(id))
511+
const dependencyModuleIds = [
512+
...info.importedIds,
513+
...info.dynamicallyImportedIds
514+
]
515+
const isImportSharedLib = dependencyModuleIds.some((id) =>
516+
sharedLibIds.has(id)
517+
)
484518
if (isImportSharedLib) {
485519
moduleNeedToTransformSet.add(id)
486520
}
@@ -497,8 +531,12 @@ export function prodSharedPlugin(
497531
if (moduleNeedToTransformSet.size === 0) return null
498532
const relatedModules = Object.keys(chunk.modules)
499533

500-
if (relatedModules.some(id => moduleNeedToTransformSet.has(id))) {
501-
const transformedCode = transformImportFn.apply(this, [code, chunk, options])
534+
if (relatedModules.some((id) => moduleNeedToTransformSet.has(id))) {
535+
const transformedCode = transformImportFn.apply(this, [
536+
code,
537+
chunk,
538+
options
539+
])
502540
if (transformedCode) return transformedCode
503541
}
504542
return null

0 commit comments

Comments
 (0)