-
-
Notifications
You must be signed in to change notification settings - Fork 419
Expand file tree
/
Copy pathindex.js
More file actions
126 lines (106 loc) · 3.82 KB
/
Copy pathindex.js
File metadata and controls
126 lines (106 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// reuse `@babel/types` from `metro`
const metroPath = require.resolve('metro');
const babelTypesPath = require.resolve('@babel/types', { paths: [metroPath] });
const t = require(babelTypesPath);
const UNSUPPORTED_IMPORT_MESSAGE =
'The module path for import() must be a static string literal. Expressions or variables are not supported.';
const WEBPACK_IGNORE_COMMENT = 'webpackIgnore: true';
function isIgnoredWebpackImport(path) {
const [firstArg] = path.node.arguments;
const comments = [
...(firstArg?.leadingComments || []),
...(path.node?.leadingComments || []),
...(path.node?.innerComments || []),
];
return (
t.isImport(path.node.callee) &&
comments.some((comment) => comment.value.includes(WEBPACK_IGNORE_COMMENT))
);
}
function getRemotesRegExp(remotes) {
return new RegExp(`^(${Object.keys(remotes).join('|')})/`);
}
function getSharedRegExp(shared) {
return new RegExp(`^(${Object.keys(shared).join('|')})$`);
}
function isRemoteImport(path, options) {
return (
t.isImport(path.node.callee) &&
t.isStringLiteral(path.node.arguments[0]) &&
Object.keys(options.remotes).length > 0 &&
path.node.arguments[0].value.match(getRemotesRegExp(options.remotes))
);
}
function isSharedImport(path, options) {
return (
t.isImport(path.node.callee) &&
t.isStringLiteral(path.node.arguments[0]) &&
Object.keys(options.shared).length > 0 &&
path.node.arguments[0].value.match(getSharedRegExp(options.shared))
);
}
function createWrappedImport(importName, methodName) {
const importArg = t.stringLiteral(importName);
// require('mf:remote-module-registry')
const requireCall = t.callExpression(t.identifier('require'), [
t.stringLiteral('mf:remote-module-registry'),
]);
// .loadAndGetRemote(importName) or .loadAndGetShared(importName)
const loadAndGetCall = t.callExpression(
t.memberExpression(requireCall, t.identifier(methodName)),
[importArg],
);
return loadAndGetCall;
}
function getWrappedRemoteImport(importName) {
return createWrappedImport(importName, 'loadAndGetRemote');
}
function getWrappedSharedImport(importName) {
return createWrappedImport(importName, 'loadAndGetShared');
}
function getRejectedPromise(errorMessage) {
return t.callExpression(
t.memberExpression(t.identifier('Promise'), t.identifier('reject')),
[t.newExpression(t.identifier('Error'), [t.stringLiteral(errorMessage)])],
);
}
// normalize paths to POSIX separators so comparisons against generated
// paths work on Windows, where Metro and `path.resolve` can disagree
// on path separators
function toPosixPath(value) {
return typeof value === 'string' ? value.replace(/\\/g, '/') : value;
}
function moduleFederationMetroBabelPlugin() {
return {
name: 'module-federation-metro-babel-plugin',
visitor: {
CallExpression(path, state) {
const filename = toPosixPath(state.filename);
const blacklistedPaths = (state.opts.blacklistedPaths || []).map(
toPosixPath,
);
if (blacklistedPaths.includes(filename)) {
return;
}
// Workaround to remove problematic import from `loadEsmEntry` in `@module-federation/runtime-core`
// That causes crashes in Metro bundler
if (isIgnoredWebpackImport(path)) {
path.replaceWith(getRejectedPromise(UNSUPPORTED_IMPORT_MESSAGE));
return;
}
if (isRemoteImport(path, state.opts)) {
const wrappedImport = getWrappedRemoteImport(
path.node.arguments[0].value,
);
path.replaceWith(wrappedImport);
} else if (isSharedImport(path, state.opts)) {
const wrappedImport = getWrappedSharedImport(
path.node.arguments[0].value,
);
path.replaceWith(wrappedImport);
}
},
},
};
}
module.exports = moduleFederationMetroBabelPlugin;