@umijs/mfsu 4.0.0-canary.20220429.2 → 4.0.0-canary.20220506.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/babelPlugins/awaitImport/awaitImport.d.ts +27 -0
- package/dist/babelPlugins/awaitImport/awaitImport.js +120 -0
- package/dist/babelPlugins/awaitImport/checkMatch.d.ts +18 -0
- package/dist/babelPlugins/awaitImport/checkMatch.js +127 -0
- package/dist/babelPlugins/awaitImport/getAliasedPath.d.ts +4 -0
- package/dist/babelPlugins/awaitImport/getAliasedPath.js +30 -0
- package/dist/babelPlugins/awaitImport/getRealPath.d.ts +4 -0
- package/dist/babelPlugins/awaitImport/getRealPath.js +24 -0
- package/dist/babelPlugins/awaitImport/isExternals.d.ts +11 -0
- package/dist/babelPlugins/awaitImport/isExternals.js +29 -0
- package/dist/babelPlugins/awaitImport/parseSpecifiers.d.ts +1 -0
- package/dist/babelPlugins/awaitImport/parseSpecifiers.js +55 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.js +10 -0
- package/dist/dep/dep.d.ts +30 -0
- package/dist/dep/dep.js +96 -0
- package/dist/dep/getCJSExports.d.ts +3 -0
- package/dist/dep/getCJSExports.js +58 -0
- package/dist/dep/getExposeFromContent.d.ts +6 -0
- package/dist/dep/getExposeFromContent.js +69 -0
- package/dist/dep/getModuleExports.d.ts +7 -0
- package/dist/dep/getModuleExports.js +34 -0
- package/dist/depBuilder/depBuilder.d.ts +30 -0
- package/dist/depBuilder/depBuilder.js +164 -0
- package/dist/depBuilder/getESBuildEntry.d.ts +4 -0
- package/dist/depBuilder/getESBuildEntry.js +328 -0
- package/dist/depInfo.d.ts +17 -0
- package/dist/depInfo.js +50 -0
- package/dist/esbuildHandlers/autoCssModules.d.ts +2 -0
- package/dist/esbuildHandlers/autoCssModules.js +24 -0
- package/dist/esbuildHandlers/awaitImport/index.d.ts +12 -0
- package/dist/esbuildHandlers/awaitImport/index.js +44 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +23 -0
- package/dist/loader/esbuild.d.ts +5 -0
- package/dist/loader/esbuild.js +38 -0
- package/dist/mfsu.d.ts +63 -0
- package/dist/mfsu.js +294 -0
- package/dist/moduleGraph.d.ts +73 -0
- package/dist/moduleGraph.js +197 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.js +8 -0
- package/dist/utils/makeArray.d.ts +1 -0
- package/dist/utils/makeArray.js +7 -0
- package/dist/utils/trimFileContent.d.ts +1 -0
- package/dist/utils/trimFileContent.js +7 -0
- package/dist/webpackPlugins/buildDepPlugin.d.ts +10 -0
- package/dist/webpackPlugins/buildDepPlugin.js +17 -0
- package/dist/webpackPlugins/depChunkIdPrefixPlugin.d.ts +5 -0
- package/dist/webpackPlugins/depChunkIdPrefixPlugin.js +19 -0
- package/dist/webpackPlugins/stripSourceMapUrlPlugin.d.ts +10 -0
- package/dist/webpackPlugins/stripSourceMapUrlPlugin.js +28 -0
- package/dist/webpackPlugins/writeCachePlugin.d.ts +10 -0
- package/dist/webpackPlugins/writeCachePlugin.js +15 -0
- package/package.json +4 -4
package/dist/depInfo.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DepInfo = void 0;
|
|
4
|
+
const utils_1 = require("@umijs/utils");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const moduleGraph_1 = require("./moduleGraph");
|
|
8
|
+
class DepInfo {
|
|
9
|
+
constructor(opts) {
|
|
10
|
+
this.moduleGraph = new moduleGraph_1.ModuleGraph();
|
|
11
|
+
this.cacheDependency = {};
|
|
12
|
+
this.opts = opts;
|
|
13
|
+
this.cacheFilePath = (0, path_1.join)(this.opts.mfsu.opts.tmpBase, 'MFSU_CACHE.json');
|
|
14
|
+
}
|
|
15
|
+
shouldBuild() {
|
|
16
|
+
if (!utils_1.lodash.isEqual(this.cacheDependency, this.opts.mfsu.opts.getCacheDependency())) {
|
|
17
|
+
return 'cacheDependency has changed';
|
|
18
|
+
}
|
|
19
|
+
if (this.moduleGraph.hasDepChanged()) {
|
|
20
|
+
return 'moduleGraph has changed';
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
snapshot() {
|
|
25
|
+
this.cacheDependency = this.opts.mfsu.opts.getCacheDependency();
|
|
26
|
+
this.moduleGraph.snapshotDeps();
|
|
27
|
+
}
|
|
28
|
+
loadCache() {
|
|
29
|
+
if ((0, fs_1.existsSync)(this.cacheFilePath)) {
|
|
30
|
+
utils_1.logger.info('MFSU restore cache');
|
|
31
|
+
const { cacheDependency, moduleGraph } = JSON.parse((0, fs_1.readFileSync)(this.cacheFilePath, 'utf-8'));
|
|
32
|
+
this.cacheDependency = cacheDependency;
|
|
33
|
+
this.moduleGraph.restore(moduleGraph);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
writeCache() {
|
|
37
|
+
utils_1.fsExtra.mkdirpSync((0, path_1.dirname)(this.cacheFilePath));
|
|
38
|
+
const newContent = JSON.stringify({
|
|
39
|
+
cacheDependency: this.cacheDependency,
|
|
40
|
+
moduleGraph: this.moduleGraph.toJSON(),
|
|
41
|
+
}, null, 2);
|
|
42
|
+
if ((0, fs_1.existsSync)(this.cacheFilePath) &&
|
|
43
|
+
(0, fs_1.readFileSync)(this.cacheFilePath, 'utf-8') === newContent) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
utils_1.logger.info('MFSU write cache');
|
|
47
|
+
(0, fs_1.writeFileSync)(this.cacheFilePath, newContent, 'utf-8');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.DepInfo = DepInfo;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.autoCssModulesHandler = void 0;
|
|
4
|
+
const utils_1 = require("@umijs/utils");
|
|
5
|
+
const CSS_MODULES_QUERY = '?modules';
|
|
6
|
+
const QUERY_LENGTH = CSS_MODULES_QUERY.length;
|
|
7
|
+
function autoCssModulesHandler(opts) {
|
|
8
|
+
let { code } = opts;
|
|
9
|
+
let offset = 0;
|
|
10
|
+
opts.imports.forEach((i) => {
|
|
11
|
+
if (i.d < 0 && (0, utils_1.isStyleFile)({ filename: i.n })) {
|
|
12
|
+
// import x from './index.less'
|
|
13
|
+
// => import x from '
|
|
14
|
+
const importSegment = code.substring(i.ss + offset, i.s + offset);
|
|
15
|
+
// is css module
|
|
16
|
+
if (~importSegment.indexOf(' from')) {
|
|
17
|
+
code = `${code.substring(0, i.e + offset)}${CSS_MODULES_QUERY}${code.substring(i.e + offset)}`;
|
|
18
|
+
offset += QUERY_LENGTH;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
return code;
|
|
23
|
+
}
|
|
24
|
+
exports.autoCssModulesHandler = autoCssModulesHandler;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ImportSpecifier } from '@umijs/bundler-utils/compiled/es-module-lexer';
|
|
2
|
+
interface IParams {
|
|
3
|
+
cache: Map<string, any>;
|
|
4
|
+
opts: any;
|
|
5
|
+
}
|
|
6
|
+
interface IOpts {
|
|
7
|
+
code: string;
|
|
8
|
+
imports: ImportSpecifier[];
|
|
9
|
+
filePath: string;
|
|
10
|
+
}
|
|
11
|
+
export default function getAwaitImportHandler(params: IParams): (opts: IOpts) => string;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const checkMatch_1 = require("../../babelPlugins/awaitImport/checkMatch");
|
|
4
|
+
function getAwaitImportHandler(params) {
|
|
5
|
+
return function awaitImportHandler(opts) {
|
|
6
|
+
var _a, _b;
|
|
7
|
+
let offset = 0;
|
|
8
|
+
let { code } = opts;
|
|
9
|
+
const { filePath, imports } = opts;
|
|
10
|
+
imports.forEach((i) => {
|
|
11
|
+
if (!i.n)
|
|
12
|
+
return;
|
|
13
|
+
const isLazyImport = i.d > 0;
|
|
14
|
+
const from = i.n;
|
|
15
|
+
const { isMatch, replaceValue } = (0, checkMatch_1.checkMatch)({
|
|
16
|
+
cache: params.cache,
|
|
17
|
+
value: from,
|
|
18
|
+
opts: params.opts,
|
|
19
|
+
filename: filePath,
|
|
20
|
+
});
|
|
21
|
+
if (isMatch) {
|
|
22
|
+
// case: import x from './index.ts';
|
|
23
|
+
// import('./index.ts');
|
|
24
|
+
// import x from '
|
|
25
|
+
// import(
|
|
26
|
+
const preSeg = code.substring(0, i.s + offset);
|
|
27
|
+
// ';
|
|
28
|
+
// );
|
|
29
|
+
const tailSeg = code.substring(i.e + offset);
|
|
30
|
+
const quote = isLazyImport ? '"' : '';
|
|
31
|
+
code = `${preSeg}${quote}${replaceValue}${quote}${tailSeg}`;
|
|
32
|
+
offset += replaceValue.length - from.length;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
if (params.cache.has(filePath)) {
|
|
36
|
+
(_b = (_a = params.opts).onCollect) === null || _b === void 0 ? void 0 : _b.call(_a, {
|
|
37
|
+
file: filePath,
|
|
38
|
+
data: params.cache.get(filePath),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return code;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
exports.default = getAwaitImportHandler;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.esbuildLoader = void 0;
|
|
18
|
+
__exportStar(require("./constants"), exports);
|
|
19
|
+
__exportStar(require("./esbuildHandlers/autoCssModules"), exports);
|
|
20
|
+
// for independent use `esbuild-loader`
|
|
21
|
+
var esbuild_1 = require("./loader/esbuild");
|
|
22
|
+
Object.defineProperty(exports, "esbuildLoader", { enumerable: true, get: function () { return esbuild_1.esbuildLoader; } });
|
|
23
|
+
__exportStar(require("./mfsu"), exports);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { LoaderContext } from 'webpack';
|
|
2
|
+
import type { IEsbuildLoaderOpts } from '../types';
|
|
3
|
+
declare function esbuildTranspiler(this: LoaderContext<IEsbuildLoaderOpts>, source: string): Promise<void>;
|
|
4
|
+
export default esbuildTranspiler;
|
|
5
|
+
export declare const esbuildLoader: string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.esbuildLoader = void 0;
|
|
4
|
+
const es_module_lexer_1 = require("@umijs/bundler-utils/compiled/es-module-lexer");
|
|
5
|
+
const esbuild_1 = require("@umijs/bundler-utils/compiled/esbuild");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
async function esbuildTranspiler(source) {
|
|
8
|
+
var _a;
|
|
9
|
+
const done = this.async();
|
|
10
|
+
const options = this.getOptions();
|
|
11
|
+
const { handler = [], implementation, ...otherOptions } = options;
|
|
12
|
+
const transform = (implementation === null || implementation === void 0 ? void 0 : implementation.transform) || esbuild_1.transform;
|
|
13
|
+
const filePath = this.resourcePath;
|
|
14
|
+
const ext = (0, path_1.extname)(filePath).slice(1);
|
|
15
|
+
const transformOptions = {
|
|
16
|
+
...otherOptions,
|
|
17
|
+
target: (_a = options.target) !== null && _a !== void 0 ? _a : 'es2015',
|
|
18
|
+
loader: ext !== null && ext !== void 0 ? ext : 'js',
|
|
19
|
+
sourcemap: this.sourceMap,
|
|
20
|
+
sourcefile: filePath,
|
|
21
|
+
};
|
|
22
|
+
try {
|
|
23
|
+
let { code, map } = await transform(source, transformOptions);
|
|
24
|
+
if (handler.length) {
|
|
25
|
+
await es_module_lexer_1.init;
|
|
26
|
+
handler.forEach((handle) => {
|
|
27
|
+
const [imports, exports] = (0, es_module_lexer_1.parse)(code);
|
|
28
|
+
code = handle({ code, imports, exports, filePath });
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
done(null, code, map && JSON.parse(map));
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
done(error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.default = esbuildTranspiler;
|
|
38
|
+
exports.esbuildLoader = __filename;
|
package/dist/mfsu.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { NextFunction, Request, Response } from '@umijs/bundler-utils/compiled/express';
|
|
2
|
+
import webpack, { Configuration } from 'webpack';
|
|
3
|
+
import awaitImport from './babelPlugins/awaitImport/awaitImport';
|
|
4
|
+
import { DepBuilder } from './depBuilder/depBuilder';
|
|
5
|
+
import { DepInfo } from './depInfo';
|
|
6
|
+
import { Mode } from './types';
|
|
7
|
+
interface IOpts {
|
|
8
|
+
cwd?: string;
|
|
9
|
+
excludeNodeNatives?: boolean;
|
|
10
|
+
exportAllMembers?: Record<string, string[]>;
|
|
11
|
+
getCacheDependency?: Function;
|
|
12
|
+
onMFSUProgress?: Function;
|
|
13
|
+
mfName?: string;
|
|
14
|
+
mode?: Mode;
|
|
15
|
+
tmpBase?: string;
|
|
16
|
+
unMatchLibs?: string[];
|
|
17
|
+
runtimePublicPath?: boolean | string;
|
|
18
|
+
implementor: typeof webpack;
|
|
19
|
+
buildDepWithESBuild?: boolean;
|
|
20
|
+
depBuildConfig: any;
|
|
21
|
+
}
|
|
22
|
+
export declare class MFSU {
|
|
23
|
+
opts: IOpts;
|
|
24
|
+
alias: Record<string, string>;
|
|
25
|
+
externals: (Record<string, string> | Function)[];
|
|
26
|
+
depInfo: DepInfo;
|
|
27
|
+
depBuilder: DepBuilder;
|
|
28
|
+
depConfig: Configuration | null;
|
|
29
|
+
buildDepsAgain: boolean;
|
|
30
|
+
progress: any;
|
|
31
|
+
onProgress: Function;
|
|
32
|
+
publicPath: string;
|
|
33
|
+
constructor(opts: IOpts);
|
|
34
|
+
asyncImport(content: string): string;
|
|
35
|
+
setWebpackConfig(opts: {
|
|
36
|
+
config: Configuration;
|
|
37
|
+
depConfig: Configuration;
|
|
38
|
+
}): Promise<void>;
|
|
39
|
+
buildDeps(): Promise<void>;
|
|
40
|
+
getMiddlewares(): ((req: Request, res: Response, next: NextFunction) => void)[];
|
|
41
|
+
private getAwaitImportCollectOpts;
|
|
42
|
+
getBabelPlugins(): ({
|
|
43
|
+
onTransformDeps: () => void;
|
|
44
|
+
onCollect: ({ file, data, }: {
|
|
45
|
+
file: string;
|
|
46
|
+
data: {
|
|
47
|
+
unMatched: Set<{
|
|
48
|
+
sourceValue: string;
|
|
49
|
+
}>;
|
|
50
|
+
matched: Set<{
|
|
51
|
+
sourceValue: string;
|
|
52
|
+
}>;
|
|
53
|
+
};
|
|
54
|
+
}) => void;
|
|
55
|
+
exportAllMembers: Record<string, string[]> | undefined;
|
|
56
|
+
unMatchLibs: string[] | undefined;
|
|
57
|
+
remoteName: string | undefined;
|
|
58
|
+
alias: Record<string, string>;
|
|
59
|
+
externals: (Function | Record<string, string>)[];
|
|
60
|
+
} | typeof awaitImport)[][];
|
|
61
|
+
getEsbuildLoaderHandler(): any[];
|
|
62
|
+
}
|
|
63
|
+
export {};
|
package/dist/mfsu.js
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MFSU = void 0;
|
|
7
|
+
const bundler_utils_1 = require("@umijs/bundler-utils");
|
|
8
|
+
const utils_1 = require("@umijs/utils");
|
|
9
|
+
const assert_1 = __importDefault(require("assert"));
|
|
10
|
+
const fs_1 = require("fs");
|
|
11
|
+
const path_1 = require("path");
|
|
12
|
+
const mrmime_1 = require("../compiled/mrmime");
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
const webpack_virtual_modules_1 = __importDefault(require("../compiled/webpack-virtual-modules"));
|
|
15
|
+
const awaitImport_1 = __importDefault(require("./babelPlugins/awaitImport/awaitImport"));
|
|
16
|
+
const getRealPath_1 = require("./babelPlugins/awaitImport/getRealPath");
|
|
17
|
+
const constants_1 = require("./constants");
|
|
18
|
+
const dep_1 = require("./dep/dep");
|
|
19
|
+
const depBuilder_1 = require("./depBuilder/depBuilder");
|
|
20
|
+
const depInfo_1 = require("./depInfo");
|
|
21
|
+
const awaitImport_2 = __importDefault(require("./esbuildHandlers/awaitImport"));
|
|
22
|
+
const types_1 = require("./types");
|
|
23
|
+
const makeArray_1 = require("./utils/makeArray");
|
|
24
|
+
const buildDepPlugin_1 = require("./webpackPlugins/buildDepPlugin");
|
|
25
|
+
class MFSU {
|
|
26
|
+
constructor(opts) {
|
|
27
|
+
this.alias = {};
|
|
28
|
+
this.externals = [];
|
|
29
|
+
this.depConfig = null;
|
|
30
|
+
this.buildDepsAgain = false;
|
|
31
|
+
this.progress = { done: false };
|
|
32
|
+
this.publicPath = '/';
|
|
33
|
+
this.opts = opts;
|
|
34
|
+
this.opts.mfName = this.opts.mfName || constants_1.DEFAULT_MF_NAME;
|
|
35
|
+
this.opts.tmpBase =
|
|
36
|
+
this.opts.tmpBase || (0, path_1.join)(process.cwd(), constants_1.DEFAULT_TMP_DIR_NAME);
|
|
37
|
+
this.opts.mode = this.opts.mode || types_1.Mode.development;
|
|
38
|
+
this.opts.getCacheDependency = this.opts.getCacheDependency || (() => ({}));
|
|
39
|
+
this.onProgress = (progress) => {
|
|
40
|
+
var _a, _b;
|
|
41
|
+
this.progress = {
|
|
42
|
+
...this.progress,
|
|
43
|
+
...progress,
|
|
44
|
+
};
|
|
45
|
+
(_b = (_a = this.opts).onMFSUProgress) === null || _b === void 0 ? void 0 : _b.call(_a, this.progress);
|
|
46
|
+
};
|
|
47
|
+
this.opts.cwd = this.opts.cwd || process.cwd();
|
|
48
|
+
this.depInfo = new depInfo_1.DepInfo({ mfsu: this });
|
|
49
|
+
this.depBuilder = new depBuilder_1.DepBuilder({ mfsu: this });
|
|
50
|
+
this.depInfo.loadCache();
|
|
51
|
+
}
|
|
52
|
+
// swc don't support top-level await
|
|
53
|
+
// ref: https://github.com/vercel/next.js/issues/31054
|
|
54
|
+
asyncImport(content) {
|
|
55
|
+
return `await import('${(0, utils_1.winPath)(content)}');`;
|
|
56
|
+
// return `(async () => await import('${content}'))();`;
|
|
57
|
+
}
|
|
58
|
+
async setWebpackConfig(opts) {
|
|
59
|
+
var _a;
|
|
60
|
+
const { mfName } = this.opts;
|
|
61
|
+
/**
|
|
62
|
+
* config
|
|
63
|
+
*/
|
|
64
|
+
// set alias and externals with reference for babel plugin
|
|
65
|
+
Object.assign(this.alias, ((_a = opts.config.resolve) === null || _a === void 0 ? void 0 : _a.alias) || {});
|
|
66
|
+
this.externals.push(...(0, makeArray_1.makeArray)(opts.config.externals || []));
|
|
67
|
+
// entry
|
|
68
|
+
const entry = {};
|
|
69
|
+
const virtualModules = {};
|
|
70
|
+
// ensure entry object type
|
|
71
|
+
const entryObject = utils_1.lodash.isString(opts.config.entry)
|
|
72
|
+
? { default: [opts.config.entry] }
|
|
73
|
+
: opts.config.entry;
|
|
74
|
+
(0, assert_1.default)(utils_1.lodash.isPlainObject(entryObject), `webpack config 'entry' value must be a string or an object.`);
|
|
75
|
+
for (const key of Object.keys(entryObject)) {
|
|
76
|
+
const virtualPath = `./mfsu-virtual-entry/${key}.js`;
|
|
77
|
+
const virtualContent = [];
|
|
78
|
+
let index = 1;
|
|
79
|
+
let hasDefaultExport = false;
|
|
80
|
+
const entryFiles = utils_1.lodash.isArray(entryObject[key])
|
|
81
|
+
? entryObject[key]
|
|
82
|
+
: [entryObject[key]];
|
|
83
|
+
for (let entry of entryFiles) {
|
|
84
|
+
// ensure entry is a file
|
|
85
|
+
if ((0, fs_1.statSync)(entry).isDirectory()) {
|
|
86
|
+
const realEntry = (0, utils_1.tryPaths)([
|
|
87
|
+
(0, path_1.join)(entry, 'index.tsx'),
|
|
88
|
+
(0, path_1.join)(entry, 'index.ts'),
|
|
89
|
+
]);
|
|
90
|
+
(0, assert_1.default)(realEntry, `entry file not found, please configure the specific entry path. (e.g. 'src/index.tsx')`);
|
|
91
|
+
entry = realEntry;
|
|
92
|
+
}
|
|
93
|
+
const content = (0, fs_1.readFileSync)(entry, 'utf-8');
|
|
94
|
+
const [_imports, exports] = await (0, bundler_utils_1.parseModule)({ content, path: entry });
|
|
95
|
+
if (exports.length) {
|
|
96
|
+
virtualContent.push(`const k${index} = ${this.asyncImport(entry)}`);
|
|
97
|
+
for (const exportName of exports) {
|
|
98
|
+
if (exportName === 'default') {
|
|
99
|
+
hasDefaultExport = true;
|
|
100
|
+
virtualContent.push(`export default k${index}.${exportName}`);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
virtualContent.push(`export const ${exportName} = k${index}.${exportName}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
virtualContent.push(this.asyncImport(entry));
|
|
109
|
+
}
|
|
110
|
+
index += 1;
|
|
111
|
+
}
|
|
112
|
+
if (!hasDefaultExport) {
|
|
113
|
+
virtualContent.push(`export default 1;`);
|
|
114
|
+
}
|
|
115
|
+
virtualModules[virtualPath] = virtualContent.join('\n');
|
|
116
|
+
entry[key] = virtualPath;
|
|
117
|
+
}
|
|
118
|
+
opts.config.entry = entry;
|
|
119
|
+
// plugins
|
|
120
|
+
opts.config.plugins = opts.config.plugins || [];
|
|
121
|
+
// support publicPath auto
|
|
122
|
+
let publicPath = opts.config.output.publicPath;
|
|
123
|
+
if (publicPath === 'auto') {
|
|
124
|
+
publicPath = '/';
|
|
125
|
+
}
|
|
126
|
+
this.publicPath = publicPath;
|
|
127
|
+
opts.config.plugins.push(...[
|
|
128
|
+
new webpack_virtual_modules_1.default(virtualModules),
|
|
129
|
+
new this.opts.implementor.container.ModuleFederationPlugin({
|
|
130
|
+
name: '__',
|
|
131
|
+
remotes: {
|
|
132
|
+
[mfName]: this.opts.runtimePublicPath
|
|
133
|
+
? // ref:
|
|
134
|
+
// https://webpack.js.org/concepts/module-federation/#promise-based-dynamic-remotes
|
|
135
|
+
`
|
|
136
|
+
promise new Promise(resolve => {
|
|
137
|
+
const remoteUrlWithVersion = window.publicPath + '${constants_1.REMOTE_FILE_FULL}';
|
|
138
|
+
const script = document.createElement('script');
|
|
139
|
+
script.src = remoteUrlWithVersion;
|
|
140
|
+
script.onload = () => {
|
|
141
|
+
// the injected script has loaded and is available on window
|
|
142
|
+
// we can now resolve this Promise
|
|
143
|
+
const proxy = {
|
|
144
|
+
get: (request) => window['${mfName}'].get(request),
|
|
145
|
+
init: (arg) => {
|
|
146
|
+
try {
|
|
147
|
+
return window['${mfName}'].init(arg);
|
|
148
|
+
} catch(e) {
|
|
149
|
+
console.log('remote container already initialized');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
resolve(proxy);
|
|
154
|
+
}
|
|
155
|
+
// inject this script with the src set to the versioned remoteEntry.js
|
|
156
|
+
document.head.appendChild(script);
|
|
157
|
+
})
|
|
158
|
+
`.trimLeft()
|
|
159
|
+
: `${mfName}@${publicPath}${constants_1.REMOTE_FILE_FULL}`,
|
|
160
|
+
},
|
|
161
|
+
}),
|
|
162
|
+
new buildDepPlugin_1.BuildDepPlugin({
|
|
163
|
+
onCompileDone: () => {
|
|
164
|
+
if (this.depBuilder.isBuilding) {
|
|
165
|
+
this.buildDepsAgain = true;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
this.buildDeps()
|
|
169
|
+
.then(() => {
|
|
170
|
+
this.onProgress({
|
|
171
|
+
done: true,
|
|
172
|
+
});
|
|
173
|
+
})
|
|
174
|
+
.catch((e) => {
|
|
175
|
+
utils_1.logger.error(e);
|
|
176
|
+
this.onProgress({
|
|
177
|
+
done: true,
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
}),
|
|
183
|
+
// new WriteCachePlugin({
|
|
184
|
+
// onWriteCache: lodash.debounce(() => {
|
|
185
|
+
// this.depInfo.writeCache();
|
|
186
|
+
// }, 300),
|
|
187
|
+
// }),
|
|
188
|
+
]);
|
|
189
|
+
// ensure topLevelAwait enabled
|
|
190
|
+
utils_1.lodash.set(opts.config, 'experiments.topLevelAwait', true);
|
|
191
|
+
/**
|
|
192
|
+
* depConfig
|
|
193
|
+
*/
|
|
194
|
+
this.depConfig = opts.depConfig;
|
|
195
|
+
}
|
|
196
|
+
async buildDeps() {
|
|
197
|
+
const shouldBuild = this.depInfo.shouldBuild();
|
|
198
|
+
if (!shouldBuild) {
|
|
199
|
+
utils_1.logger.info('MFSU skip buildDeps');
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
this.depInfo.snapshot();
|
|
203
|
+
const deps = dep_1.Dep.buildDeps({
|
|
204
|
+
deps: this.depInfo.moduleGraph.depSnapshotModules,
|
|
205
|
+
cwd: this.opts.cwd,
|
|
206
|
+
mfsu: this,
|
|
207
|
+
});
|
|
208
|
+
utils_1.logger.info(`MFSU buildDeps since ${shouldBuild}`);
|
|
209
|
+
utils_1.logger.debug(deps.map((dep) => dep.file).join(', '));
|
|
210
|
+
await this.depBuilder.build({
|
|
211
|
+
deps,
|
|
212
|
+
});
|
|
213
|
+
// Write cache
|
|
214
|
+
this.depInfo.writeCache();
|
|
215
|
+
if (this.buildDepsAgain) {
|
|
216
|
+
utils_1.logger.info('MFSU buildDepsAgain');
|
|
217
|
+
this.buildDepsAgain = false;
|
|
218
|
+
this.buildDeps().catch((e) => {
|
|
219
|
+
utils_1.logger.error(e);
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
getMiddlewares() {
|
|
224
|
+
return [
|
|
225
|
+
(req, res, next) => {
|
|
226
|
+
const publicPath = this.publicPath;
|
|
227
|
+
const isMF = req.path.startsWith(`${publicPath}${constants_1.MF_VA_PREFIX}`) ||
|
|
228
|
+
req.path.startsWith(`${publicPath}${constants_1.MF_DEP_PREFIX}`) ||
|
|
229
|
+
req.path.startsWith(`${publicPath}${constants_1.MF_STATIC_PREFIX}`);
|
|
230
|
+
if (isMF) {
|
|
231
|
+
this.depBuilder.onBuildComplete(() => {
|
|
232
|
+
if (!req.path.includes(constants_1.REMOTE_FILE)) {
|
|
233
|
+
res.setHeader('cache-control', 'max-age=31536000,immutable');
|
|
234
|
+
}
|
|
235
|
+
res.setHeader('content-type', (0, mrmime_1.lookup)((0, path_1.extname)(req.path)) || 'text/plain');
|
|
236
|
+
const relativePath = req.path.replace(new RegExp(`^${publicPath}`), '/');
|
|
237
|
+
const content = (0, fs_1.readFileSync)((0, path_1.join)(this.opts.tmpBase, relativePath));
|
|
238
|
+
res.send(content);
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
next();
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
];
|
|
246
|
+
}
|
|
247
|
+
getAwaitImportCollectOpts() {
|
|
248
|
+
return {
|
|
249
|
+
onTransformDeps: () => { },
|
|
250
|
+
onCollect: ({ file, data, }) => {
|
|
251
|
+
this.depInfo.moduleGraph.onFileChange({
|
|
252
|
+
file,
|
|
253
|
+
// @ts-ignore
|
|
254
|
+
deps: [
|
|
255
|
+
...Array.from(data.matched).map((item) => ({
|
|
256
|
+
file: item.sourceValue,
|
|
257
|
+
isDependency: true,
|
|
258
|
+
version: dep_1.Dep.getDepVersion({
|
|
259
|
+
dep: item.sourceValue,
|
|
260
|
+
cwd: this.opts.cwd,
|
|
261
|
+
}),
|
|
262
|
+
})),
|
|
263
|
+
...Array.from(data.unMatched).map((item) => ({
|
|
264
|
+
file: (0, getRealPath_1.getRealPath)({
|
|
265
|
+
file,
|
|
266
|
+
dep: item.sourceValue,
|
|
267
|
+
}),
|
|
268
|
+
isDependency: false,
|
|
269
|
+
})),
|
|
270
|
+
],
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
exportAllMembers: this.opts.exportAllMembers,
|
|
274
|
+
unMatchLibs: this.opts.unMatchLibs,
|
|
275
|
+
remoteName: this.opts.mfName,
|
|
276
|
+
alias: this.alias,
|
|
277
|
+
externals: this.externals,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
getBabelPlugins() {
|
|
281
|
+
return [[awaitImport_1.default, this.getAwaitImportCollectOpts()]];
|
|
282
|
+
}
|
|
283
|
+
getEsbuildLoaderHandler() {
|
|
284
|
+
const cache = new Map();
|
|
285
|
+
const checkOpts = this.getAwaitImportCollectOpts();
|
|
286
|
+
return [
|
|
287
|
+
(0, awaitImport_2.default)({
|
|
288
|
+
cache,
|
|
289
|
+
opts: checkOpts,
|
|
290
|
+
}),
|
|
291
|
+
];
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
exports.MFSU = MFSU;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
declare class ModuleNode {
|
|
2
|
+
file: string;
|
|
3
|
+
importers: Set<ModuleNode>;
|
|
4
|
+
importedModules: Set<ModuleNode>;
|
|
5
|
+
isDependency: boolean;
|
|
6
|
+
isRoot: boolean;
|
|
7
|
+
version: string | null;
|
|
8
|
+
constructor(file: string);
|
|
9
|
+
}
|
|
10
|
+
interface IDep {
|
|
11
|
+
file: string;
|
|
12
|
+
isDependency: boolean;
|
|
13
|
+
version?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare class ModuleGraph {
|
|
16
|
+
fileToModules: Map<string, ModuleNode>;
|
|
17
|
+
depToModules: Map<string, ModuleNode>;
|
|
18
|
+
depSnapshotModules: Record<string, {
|
|
19
|
+
file: string;
|
|
20
|
+
version: string;
|
|
21
|
+
}>;
|
|
22
|
+
rootModules: Set<ModuleNode>;
|
|
23
|
+
constructor();
|
|
24
|
+
restore(data: {
|
|
25
|
+
roots: any;
|
|
26
|
+
fileModules: any;
|
|
27
|
+
depModules: any;
|
|
28
|
+
depSnapshotModules: any;
|
|
29
|
+
}): void;
|
|
30
|
+
toJSON(): {
|
|
31
|
+
roots: string[];
|
|
32
|
+
fileModules: Record<string, {
|
|
33
|
+
importedModules: string[];
|
|
34
|
+
isRoot?: boolean | undefined;
|
|
35
|
+
}>;
|
|
36
|
+
depModules: Record<string, {
|
|
37
|
+
version: string | null;
|
|
38
|
+
}>;
|
|
39
|
+
depSnapshotModules: Record<string, {
|
|
40
|
+
file: string;
|
|
41
|
+
version: string;
|
|
42
|
+
}>;
|
|
43
|
+
};
|
|
44
|
+
snapshotDeps(): void;
|
|
45
|
+
getDepsInfo(mods: Map<string, ModuleNode>): Record<string, {
|
|
46
|
+
file: string;
|
|
47
|
+
version: string;
|
|
48
|
+
}>;
|
|
49
|
+
getDepInfo(mod: ModuleNode): {
|
|
50
|
+
file: string;
|
|
51
|
+
version: string;
|
|
52
|
+
};
|
|
53
|
+
hasDepChanged(): boolean;
|
|
54
|
+
onFileChange(opts: {
|
|
55
|
+
file: string;
|
|
56
|
+
deps: IDep[];
|
|
57
|
+
}): void;
|
|
58
|
+
updateModule(opts: {
|
|
59
|
+
mod: ModuleNode;
|
|
60
|
+
deps: IDep[];
|
|
61
|
+
}): void;
|
|
62
|
+
addNode(opts: {
|
|
63
|
+
file: string;
|
|
64
|
+
isDependency: boolean;
|
|
65
|
+
importer: ModuleNode;
|
|
66
|
+
version?: string | null;
|
|
67
|
+
}): void;
|
|
68
|
+
deleteNode(opts: {
|
|
69
|
+
mod: ModuleNode;
|
|
70
|
+
importer: ModuleNode;
|
|
71
|
+
}): void;
|
|
72
|
+
}
|
|
73
|
+
export {};
|