@umijs/preset-umi 4.0.0-beta.10 → 4.0.0-beta.14
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/commands/dev/createRouteMiddleware.js +7 -3
- package/dist/commands/dev/dev.js +4 -1
- package/dist/commands/dev/getMarkupArgs.d.ts +2 -0
- package/dist/commands/dev/getMarkupArgs.js +2 -0
- package/dist/commands/setup.js +19 -8
- package/dist/features/appData/appData.js +33 -0
- package/dist/features/check/check.js +11 -0
- package/dist/features/configPlugins/configPlugins.js +6 -2
- package/dist/features/configPlugins/schema.js +2 -0
- package/dist/features/esmi/Service.d.ts +75 -0
- package/dist/features/esmi/Service.js +122 -0
- package/dist/features/esmi/esmi.d.ts +1 -1
- package/dist/features/esmi/esmi.js +170 -10
- package/dist/features/favicon/favicon.js +4 -2
- package/dist/features/lowImport/babelPlugin.d.ts +2 -0
- package/dist/features/lowImport/babelPlugin.js +11 -2
- package/dist/features/lowImport/lowImport.js +8 -3
- package/dist/features/mock/mock.js +3 -0
- package/dist/features/tmpFiles/routes.js +10 -0
- package/dist/features/tmpFiles/tmpFiles.js +9 -3
- package/dist/index.js +1 -0
- package/dist/libs/scan.js +1 -0
- package/dist/registerMethods.js +11 -3
- package/dist/types.d.ts +4 -1
- package/dist/utils/transformIEAR.d.ts +22 -0
- package/dist/utils/transformIEAR.js +96 -0
- package/package.json +17 -15
- package/templates/plugin.tpl +14 -0
- package/templates/umi.tpl +29 -8
- package/dist/libs/moduleGraph.d.ts +0 -2
- package/dist/libs/moduleGraph.js +0 -6
|
@@ -24,11 +24,15 @@ window.__vite_plugin_react_preamble_installed__ = true
|
|
|
24
24
|
function createRouteMiddleware(opts) {
|
|
25
25
|
return (req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
26
26
|
const { vite } = opts.api.args;
|
|
27
|
+
const viteScripts = [
|
|
28
|
+
// add noshim attr for skip importmap shim logic for this modules
|
|
29
|
+
{ content: viteRefreshScript, noshim: '' },
|
|
30
|
+
{ src: '/@vite/client', noshim: '' },
|
|
31
|
+
'/.umi/umi.ts',
|
|
32
|
+
];
|
|
27
33
|
const markupArgs = yield (0, getMarkupArgs_1.getMarkupArgs)(opts);
|
|
28
34
|
// @ts-ignore
|
|
29
|
-
const requestHandler = yield (0, server_1.createRequestHandler)(Object.assign(Object.assign({}, markupArgs), { scripts: (vite
|
|
30
|
-
? [viteRefreshScript, '/@vite/client', '/.umi/umi.ts']
|
|
31
|
-
: ['/umi.js']).concat(markupArgs.scripts), esmScript: vite }));
|
|
35
|
+
const requestHandler = yield (0, server_1.createRequestHandler)(Object.assign(Object.assign({}, markupArgs), { scripts: (vite ? viteScripts : ['/umi.js']).concat(markupArgs.scripts), esmScript: vite }));
|
|
32
36
|
requestHandler(req, res, next);
|
|
33
37
|
});
|
|
34
38
|
}
|
package/dist/commands/dev/dev.js
CHANGED
|
@@ -230,7 +230,10 @@ PORT=8888 umi dev
|
|
|
230
230
|
: { babelPreset, chainWebpack, modifyWebpackConfig })), { beforeBabelPlugins,
|
|
231
231
|
beforeBabelPresets,
|
|
232
232
|
extraBabelPlugins,
|
|
233
|
-
extraBabelPresets, beforeMiddlewares: [
|
|
233
|
+
extraBabelPresets, beforeMiddlewares: [].concat([
|
|
234
|
+
...beforeMiddlewares,
|
|
235
|
+
faviconMiddleware_1.faviconMiddleware,
|
|
236
|
+
]), afterMiddlewares: [(0, createRouteMiddleware_1.createRouteMiddleware)({ api })].concat(middlewares), onDevCompileDone(opts) {
|
|
234
237
|
api.applyPlugins({
|
|
235
238
|
key: 'onDevCompileDone',
|
|
236
239
|
args: opts,
|
package/dist/commands/setup.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
const utils_1 = require("@umijs/utils");
|
|
4
13
|
exports.default = (api) => {
|
|
@@ -6,14 +15,16 @@ exports.default = (api) => {
|
|
|
6
15
|
name: 'setup',
|
|
7
16
|
description: 'setup project',
|
|
8
17
|
fn() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
// generate tmp files
|
|
20
|
+
utils_1.logger.info('generate files');
|
|
21
|
+
yield api.applyPlugins({
|
|
22
|
+
key: 'onGenerateFiles',
|
|
23
|
+
args: {
|
|
24
|
+
files: null,
|
|
25
|
+
isFirstTime: false,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
17
28
|
});
|
|
18
29
|
},
|
|
19
30
|
});
|
|
@@ -9,8 +9,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const bundler_utils_1 = require("@umijs/bundler-utils");
|
|
12
13
|
const utils_1 = require("@umijs/utils");
|
|
14
|
+
const fs_1 = require("fs");
|
|
13
15
|
const path_1 = require("path");
|
|
16
|
+
const watch_1 = require("../../commands/dev/watch");
|
|
14
17
|
const routes_1 = require("../tmpFiles/routes");
|
|
15
18
|
exports.default = (api) => {
|
|
16
19
|
api.modifyAppData((memo) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -25,6 +28,36 @@ exports.default = (api) => {
|
|
|
25
28
|
memo.react = {
|
|
26
29
|
version: require((0, path_1.join)(api.config.alias.react, 'package.json')).version,
|
|
27
30
|
};
|
|
31
|
+
memo.appJS = yield getAppJsInfo();
|
|
28
32
|
return memo;
|
|
29
33
|
}));
|
|
34
|
+
// Execute earliest, so that other onGenerateFiles can get it
|
|
35
|
+
api.register({
|
|
36
|
+
key: 'onGenerateFiles',
|
|
37
|
+
fn(args) {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
if (!args.isFirstTime) {
|
|
40
|
+
api.appData.appJS = yield getAppJsInfo();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
stage: Number.NEGATIVE_INFINITY,
|
|
45
|
+
});
|
|
46
|
+
function getAppJsInfo() {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
for (const path of (0, watch_1.expandJSPaths)((0, path_1.join)(api.paths.absSrcPath, 'app'))) {
|
|
49
|
+
if ((0, fs_1.existsSync)(path)) {
|
|
50
|
+
const [_, exports] = yield (0, bundler_utils_1.parseModule)({
|
|
51
|
+
path,
|
|
52
|
+
content: (0, fs_1.readFileSync)(path, 'utf-8'),
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
path,
|
|
56
|
+
exports,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
30
63
|
};
|
|
@@ -31,4 +31,15 @@ exports.default = (api) => {
|
|
|
31
31
|
},
|
|
32
32
|
});
|
|
33
33
|
}));
|
|
34
|
+
api.onCheckCode((args) => {
|
|
35
|
+
// Fixed version import is not allowed
|
|
36
|
+
// e.g. import { X } from '_@ant-design_icons@4.7.0@ant-design/icons'
|
|
37
|
+
if (['cnpm', 'tnpm'].includes(api.appData.npmClient)) {
|
|
38
|
+
args.imports.forEach(({ source }) => {
|
|
39
|
+
if (/@\d/.test(source)) {
|
|
40
|
+
throw new Error(`${source} is not allowed to import.`);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
});
|
|
34
45
|
};
|
|
@@ -8,7 +8,7 @@ function resolveProjectDep(opts) {
|
|
|
8
8
|
var _a, _b;
|
|
9
9
|
if (((_a = opts.pkg.dependencies) === null || _a === void 0 ? void 0 : _a[opts.dep]) ||
|
|
10
10
|
((_b = opts.pkg.devDependencies) === null || _b === void 0 ? void 0 : _b[opts.dep])) {
|
|
11
|
-
return (0, path_1.dirname)(utils_1.resolve.sync(`${opts.dep}/package`, {
|
|
11
|
+
return (0, path_1.dirname)(utils_1.resolve.sync(`${opts.dep}/package.json`, {
|
|
12
12
|
basedir: opts.cwd,
|
|
13
13
|
}));
|
|
14
14
|
}
|
|
@@ -34,6 +34,8 @@ exports.default = (api) => {
|
|
|
34
34
|
externals: {},
|
|
35
35
|
autoCSSModules: true,
|
|
36
36
|
publicPath: '/',
|
|
37
|
+
mountElementId: 'root',
|
|
38
|
+
base: '/',
|
|
37
39
|
};
|
|
38
40
|
const bundleSchemas = (0, schema_1.getSchemas)();
|
|
39
41
|
const extraSchemas = (0, schema_2.getSchemas)();
|
|
@@ -55,7 +57,9 @@ exports.default = (api) => {
|
|
|
55
57
|
}
|
|
56
58
|
// api.paths is ready after register
|
|
57
59
|
api.modifyConfig((memo, args) => {
|
|
58
|
-
memo.alias = Object.assign(Object.assign({}, memo.alias), { '@': args.paths.absSrcPath, '@@': args.paths.absTmpPath
|
|
60
|
+
memo.alias = Object.assign(Object.assign({}, memo.alias), { '@': args.paths.absSrcPath, '@@': args.paths.absTmpPath,
|
|
61
|
+
// like vite, use to pre-bundling dependencies in vite mode
|
|
62
|
+
'@fs': '/' });
|
|
59
63
|
return memo;
|
|
60
64
|
});
|
|
61
65
|
};
|
|
@@ -4,11 +4,13 @@ exports.getSchemas = void 0;
|
|
|
4
4
|
const utils_1 = require("@umijs/utils");
|
|
5
5
|
function getSchemas() {
|
|
6
6
|
return {
|
|
7
|
+
base: (Joi) => Joi.string(),
|
|
7
8
|
plugins: (Joi) => Joi.array().items(Joi.string()),
|
|
8
9
|
publicPath: (Joi) => Joi.string().regex(/\/$/).error(new Error('publicPath must end with /')),
|
|
9
10
|
favicon: (Joi) => Joi.string(),
|
|
10
11
|
headScripts: (Joi) => Joi.array().items(Joi.alternatives(Joi.string())),
|
|
11
12
|
scripts: (Joi) => Joi.array().items(Joi.alternatives(Joi.string())),
|
|
13
|
+
mountElementId: (Joi) => Joi.string(),
|
|
12
14
|
npmClient: (Joi) => Joi.string().valid(utils_1.NpmClientEnum.pnpm, utils_1.NpmClientEnum.tnpm, utils_1.NpmClientEnum.cnpm, utils_1.NpmClientEnum.yarn, utils_1.NpmClientEnum.npm),
|
|
13
15
|
routes: (Joi) => Joi.array().items(Joi.object()),
|
|
14
16
|
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { IApi } from '../../types';
|
|
2
|
+
export interface IImportmapData {
|
|
3
|
+
importMap: {
|
|
4
|
+
imports: Record<string, string>;
|
|
5
|
+
scopes: Record<string, any>;
|
|
6
|
+
};
|
|
7
|
+
deps: {
|
|
8
|
+
name: string;
|
|
9
|
+
version: string;
|
|
10
|
+
type: string;
|
|
11
|
+
}[];
|
|
12
|
+
}
|
|
13
|
+
export interface IPkgData {
|
|
14
|
+
pkgJsonContent: IApi['pkg'];
|
|
15
|
+
pkgInfo: {
|
|
16
|
+
name: string;
|
|
17
|
+
version: string;
|
|
18
|
+
type: 'esm';
|
|
19
|
+
exports: {
|
|
20
|
+
name: string;
|
|
21
|
+
path: string;
|
|
22
|
+
from: string;
|
|
23
|
+
deps: {
|
|
24
|
+
name: string;
|
|
25
|
+
version: string;
|
|
26
|
+
usedMap: Record<string, {
|
|
27
|
+
usedNamespace?: boolean;
|
|
28
|
+
usedDefault?: boolean;
|
|
29
|
+
usedNames: string[];
|
|
30
|
+
}>;
|
|
31
|
+
}[];
|
|
32
|
+
}[];
|
|
33
|
+
assets: any[];
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* class for connect esmi server
|
|
38
|
+
*/
|
|
39
|
+
export default class ESMIService {
|
|
40
|
+
cdnOrigin: string;
|
|
41
|
+
cacheDir: string;
|
|
42
|
+
cache: Record<string, IImportmapData>;
|
|
43
|
+
constructor(opts: {
|
|
44
|
+
cdnOrigin: string;
|
|
45
|
+
cacheDir: string;
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* get cache file path by cache key
|
|
49
|
+
* @param data pkg data
|
|
50
|
+
*/
|
|
51
|
+
static getCacheKey(data: IPkgData): string;
|
|
52
|
+
/**
|
|
53
|
+
* get importmap cache by cache key
|
|
54
|
+
* @param key cache key
|
|
55
|
+
*/
|
|
56
|
+
getCache(key: string): IImportmapData;
|
|
57
|
+
/**
|
|
58
|
+
* set importmap cache
|
|
59
|
+
* @param key cache key
|
|
60
|
+
* @param data importmap data
|
|
61
|
+
*/
|
|
62
|
+
setCache(key: string, data: IImportmapData): void;
|
|
63
|
+
/**
|
|
64
|
+
* build importmap from deps tree
|
|
65
|
+
* @param data package data
|
|
66
|
+
* @returns ticketId
|
|
67
|
+
*/
|
|
68
|
+
build(data: IPkgData): Promise<string | undefined>;
|
|
69
|
+
/**
|
|
70
|
+
* get importmap from deps tree
|
|
71
|
+
* @param data package data
|
|
72
|
+
* @returns importmap
|
|
73
|
+
*/
|
|
74
|
+
getImportmap(data: IPkgData): Promise<IImportmapData | undefined>;
|
|
75
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const utils_1 = require("@umijs/utils");
|
|
16
|
+
const crypto_1 = require("crypto");
|
|
17
|
+
const fs_1 = __importDefault(require("fs"));
|
|
18
|
+
const path_1 = __importDefault(require("path"));
|
|
19
|
+
/**
|
|
20
|
+
* class for connect esmi server
|
|
21
|
+
*/
|
|
22
|
+
class ESMIService {
|
|
23
|
+
constructor(opts) {
|
|
24
|
+
this.cdnOrigin = '';
|
|
25
|
+
this.cacheDir = '';
|
|
26
|
+
this.cache = {};
|
|
27
|
+
this.cdnOrigin = opts.cdnOrigin;
|
|
28
|
+
this.cacheDir = opts.cacheDir;
|
|
29
|
+
// restore local cache
|
|
30
|
+
const cacheFilePath = path_1.default.join(this.cacheDir, 'importmap.json');
|
|
31
|
+
if (fs_1.default.existsSync(cacheFilePath)) {
|
|
32
|
+
try {
|
|
33
|
+
this.cache = require(cacheFilePath);
|
|
34
|
+
}
|
|
35
|
+
catch (_a) {
|
|
36
|
+
/* nothing */
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* get cache file path by cache key
|
|
42
|
+
* @param data pkg data
|
|
43
|
+
*/
|
|
44
|
+
static getCacheKey(data) {
|
|
45
|
+
const hash = (0, crypto_1.createHash)('md4');
|
|
46
|
+
hash.update(JSON.stringify(data.pkgInfo.exports));
|
|
47
|
+
return hash.digest('hex');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* get importmap cache by cache key
|
|
51
|
+
* @param key cache key
|
|
52
|
+
*/
|
|
53
|
+
getCache(key) {
|
|
54
|
+
return this.cache[key];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* set importmap cache
|
|
58
|
+
* @param key cache key
|
|
59
|
+
* @param data importmap data
|
|
60
|
+
*/
|
|
61
|
+
setCache(key, data) {
|
|
62
|
+
this.cache[key] = data;
|
|
63
|
+
// create cache dir
|
|
64
|
+
if (!fs_1.default.existsSync(this.cacheDir)) {
|
|
65
|
+
fs_1.default.mkdirSync(this.cacheDir, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
// write cache to file system
|
|
68
|
+
fs_1.default.writeFileSync(path_1.default.join(this.cacheDir, 'importmap.json'), JSON.stringify(this.cache, null, 2));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* build importmap from deps tree
|
|
72
|
+
* @param data package data
|
|
73
|
+
* @returns ticketId
|
|
74
|
+
*/
|
|
75
|
+
build(data) {
|
|
76
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
return utils_1.axios
|
|
78
|
+
.post(`${this.cdnOrigin}/api/v1/esm/build`, data)
|
|
79
|
+
.then((a) => { var _a; return (_a = a.data.data) === null || _a === void 0 ? void 0 : _a.ticketId; });
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* get importmap from deps tree
|
|
84
|
+
* @param data package data
|
|
85
|
+
* @returns importmap
|
|
86
|
+
*/
|
|
87
|
+
getImportmap(data) {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
const cacheKey = ESMIService.getCacheKey(data);
|
|
90
|
+
const cache = this.getCache(cacheKey);
|
|
91
|
+
const stamp = +new Date();
|
|
92
|
+
// use valid cache first
|
|
93
|
+
if (cache) {
|
|
94
|
+
utils_1.logger.info('ESMi cache used');
|
|
95
|
+
return cache;
|
|
96
|
+
}
|
|
97
|
+
// log dependency list
|
|
98
|
+
utils_1.logger.info(utils_1.chalk.greenBright('Pre-compiling dependencies on esmi:'));
|
|
99
|
+
data.pkgInfo.exports[0].deps.forEach((dep) => {
|
|
100
|
+
console.log(utils_1.chalk.yellow(` ${dep.name}`));
|
|
101
|
+
});
|
|
102
|
+
// get the build ticket id
|
|
103
|
+
const ticketId = yield this.build(data);
|
|
104
|
+
// continue to the next request after 2s
|
|
105
|
+
const next = () => new Promise((resolve) => setTimeout(() => resolve(deferrer()), 2000));
|
|
106
|
+
const deferrer = () => {
|
|
107
|
+
return utils_1.axios
|
|
108
|
+
.get(`${this.cdnOrigin}/api/v1/esm/importmap/${ticketId}`)
|
|
109
|
+
.then((res) => {
|
|
110
|
+
if (res.data.success) {
|
|
111
|
+
this.setCache(cacheKey, res.data.data);
|
|
112
|
+
utils_1.logger.info(`Done, took ${((+new Date() - stamp) / 1000).toFixed(1)}s`);
|
|
113
|
+
return res.data.data;
|
|
114
|
+
}
|
|
115
|
+
return next();
|
|
116
|
+
}, next);
|
|
117
|
+
};
|
|
118
|
+
return deferrer();
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.default = ESMIService;
|
|
@@ -8,37 +8,197 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const es_module_lexer_1 = require("@umijs/bundler-utils/compiled/es-module-lexer");
|
|
16
|
+
const magic_string_1 = __importDefault(require("magic-string"));
|
|
12
17
|
const path_1 = require("path");
|
|
13
18
|
const scan_1 = require("../../libs/scan");
|
|
19
|
+
const Service_1 = __importDefault(require("./Service"));
|
|
20
|
+
let importmap = { imports: {}, scopes: {} };
|
|
21
|
+
/**
|
|
22
|
+
* esmi vite plugin
|
|
23
|
+
*/
|
|
24
|
+
function esmi(opts) {
|
|
25
|
+
return {
|
|
26
|
+
name: 'preset-umi:esmi',
|
|
27
|
+
configResolved(config) {
|
|
28
|
+
const { include, exclude } = config.optimizeDeps;
|
|
29
|
+
// do not pre-compile deps which will be loaded by importmap (for top-level deps)
|
|
30
|
+
if (include === null || include === void 0 ? void 0 : include.length) {
|
|
31
|
+
config.optimizeDeps.include = include.filter((item) => !importmap.imports[item]);
|
|
32
|
+
}
|
|
33
|
+
// exclude pre-compile deps which within importmap by default (for nested deps)
|
|
34
|
+
config.optimizeDeps.exclude = (exclude || []).concat(Object.keys(importmap.imports).filter((item) => exclude === null || exclude === void 0 ? void 0 : exclude.includes(item)));
|
|
35
|
+
},
|
|
36
|
+
transform(source) {
|
|
37
|
+
try {
|
|
38
|
+
// parse imports
|
|
39
|
+
const imports = (0, es_module_lexer_1.parse)(source)[0];
|
|
40
|
+
let s;
|
|
41
|
+
// process all imports
|
|
42
|
+
imports.forEach((item) => {
|
|
43
|
+
const { n: specifier, s: start, e: end } = item;
|
|
44
|
+
// replace npm package to CDN url for matched imports
|
|
45
|
+
if (specifier && importmap.imports[specifier]) {
|
|
46
|
+
s !== null && s !== void 0 ? s : (s = new magic_string_1.default(source));
|
|
47
|
+
s.overwrite(start, end, importmap.imports[specifier]);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return (s === null || s === void 0 ? void 0 : s.toString()) || source;
|
|
51
|
+
}
|
|
52
|
+
catch (_a) {
|
|
53
|
+
// syntax error or non-javascript files
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
handleHotUpdate(ctx) {
|
|
58
|
+
return opts.handleHotUpdate(ctx);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* generate package data
|
|
64
|
+
* @param api plugin api
|
|
65
|
+
*/
|
|
66
|
+
function generatePkgData(api) {
|
|
67
|
+
return {
|
|
68
|
+
pkgJsonContent: {
|
|
69
|
+
dependencies: api.pkg.dependencies || {},
|
|
70
|
+
devDependencies: api.pkg.devDependencies || {},
|
|
71
|
+
},
|
|
72
|
+
pkgInfo: {
|
|
73
|
+
name: api.pkg.name,
|
|
74
|
+
version: api.pkg.version,
|
|
75
|
+
type: 'esm',
|
|
76
|
+
exports: [
|
|
77
|
+
{
|
|
78
|
+
name: 'default',
|
|
79
|
+
path: 'es/index.js',
|
|
80
|
+
from: '',
|
|
81
|
+
deps: Object.entries(api.appData.deps).map(([name, version]) => ({
|
|
82
|
+
name,
|
|
83
|
+
version,
|
|
84
|
+
usedMap: {
|
|
85
|
+
[name]: { usedNamespace: true, usedNames: [] },
|
|
86
|
+
},
|
|
87
|
+
})),
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
assets: [],
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
14
94
|
exports.default = (api) => {
|
|
95
|
+
let service;
|
|
96
|
+
let resolver;
|
|
97
|
+
/**
|
|
98
|
+
* refresh importmap and save to the top-level variable
|
|
99
|
+
*/
|
|
100
|
+
function refreshImportMap() {
|
|
101
|
+
var _a;
|
|
102
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
103
|
+
// scan and module graph
|
|
104
|
+
// TODO: module graph
|
|
105
|
+
api.appData.deps = yield (0, scan_1.scan)({
|
|
106
|
+
entry: (0, path_1.join)(api.paths.absTmpPath, 'umi.ts'),
|
|
107
|
+
externals: api.config.externals,
|
|
108
|
+
resolver,
|
|
109
|
+
});
|
|
110
|
+
// skip umi by default
|
|
111
|
+
delete api.appData.deps['umi'];
|
|
112
|
+
// FIXME: force include react & react-dom
|
|
113
|
+
api.appData.deps['react'] = api.appData.react.version;
|
|
114
|
+
api.appData.deps['react-dom'] = api.appData.react.version;
|
|
115
|
+
const data = generatePkgData(api);
|
|
116
|
+
const deps = data.pkgInfo.exports.reduce((r, exp) => r.concat(exp.deps.map((dep) => dep.name)), []);
|
|
117
|
+
const hasNewDep = deps.some((i) => !importmap.imports[i]);
|
|
118
|
+
// update importmap from esm if there has new import
|
|
119
|
+
if (hasNewDep) {
|
|
120
|
+
// TODO: add local cache and restore
|
|
121
|
+
importmap = (_a = (yield service.getImportmap(data))) === null || _a === void 0 ? void 0 : _a.importMap;
|
|
122
|
+
// because we will replaced package name to CDN url in vite plugin
|
|
123
|
+
// so we must append scope rules for the CDN url like the import specifier
|
|
124
|
+
// example:
|
|
125
|
+
// origin:
|
|
126
|
+
// { imports: { a: 'aa', b: 'bb', c: 'cc1' }, scopes: { b: { c: 'cc2' } } }
|
|
127
|
+
// to:
|
|
128
|
+
// { imports: { a: 'aa', b: 'bb', c: 'cc1' }, scopes: { b: { c: 'cc2' }, 'bb': { c: 'cc2' } } }
|
|
129
|
+
Object.keys(importmap.scopes || {})
|
|
130
|
+
.filter((item) => importmap.imports[item])
|
|
131
|
+
.forEach((item) => {
|
|
132
|
+
importmap.scopes[importmap.imports[item]] = importmap.scopes[item];
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
// describe config
|
|
15
138
|
api.describe({
|
|
16
139
|
key: 'esmi',
|
|
17
140
|
config: {
|
|
18
141
|
schema(Joi) {
|
|
19
|
-
return Joi.object(
|
|
142
|
+
return Joi.object({
|
|
143
|
+
cdnOrigin: Joi.string(),
|
|
144
|
+
shimUrl: Joi.string(),
|
|
145
|
+
});
|
|
20
146
|
},
|
|
21
147
|
},
|
|
22
148
|
enableBy: api.EnableBy.config,
|
|
23
149
|
});
|
|
150
|
+
// check bundler type
|
|
24
151
|
api.onStart(() => {
|
|
25
152
|
if (!api.args.vite) {
|
|
26
153
|
throw new Error(`esmi can only be used in vite mode.`);
|
|
27
154
|
}
|
|
28
155
|
});
|
|
29
|
-
//
|
|
156
|
+
// collect all imports after tmp files generated
|
|
30
157
|
api.onBeforeCompiler(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
31
|
-
// scan and module graph
|
|
32
|
-
// TODO: module graph
|
|
33
158
|
if (api.args.vite) {
|
|
34
|
-
|
|
35
|
-
|
|
159
|
+
// init esmi service
|
|
160
|
+
service = new Service_1.default({
|
|
161
|
+
cdnOrigin: api.config.esmi.cdnOrigin,
|
|
162
|
+
cacheDir: (0, path_1.join)(api.cwd, '.esmi'),
|
|
36
163
|
});
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
resolver,
|
|
164
|
+
// init project resolver
|
|
165
|
+
resolver = (0, scan_1.createResolver)({
|
|
166
|
+
alias: api.config.alias,
|
|
41
167
|
});
|
|
168
|
+
// init importmap
|
|
169
|
+
yield refreshImportMap();
|
|
42
170
|
}
|
|
43
171
|
}));
|
|
172
|
+
// append ipmortmap script for HTML
|
|
173
|
+
api.modifyHTML(($) => {
|
|
174
|
+
const scp = $('<script type="importmap"></script>\n');
|
|
175
|
+
scp.html(JSON.stringify(importmap, null, 2));
|
|
176
|
+
$('head > script:eq(0)').before(scp);
|
|
177
|
+
// append importmap shim script
|
|
178
|
+
if (api.config.esmi.shimUrl) {
|
|
179
|
+
$('body > script:eq(0)').before($(`<script src="${api.config.esmi.shimUrl}"></script>\n`));
|
|
180
|
+
}
|
|
181
|
+
// preload for importmap modules
|
|
182
|
+
Object.values(importmap.imports).forEach((url) => {
|
|
183
|
+
scp.before($(`<link rel="modulepreload" href="${url}" />\n`));
|
|
184
|
+
});
|
|
185
|
+
return $;
|
|
186
|
+
});
|
|
187
|
+
if (api.args.vite) {
|
|
188
|
+
// apply esmi vite plugin
|
|
189
|
+
api.modifyViteConfig((memo) => {
|
|
190
|
+
memo.plugins = (memo.plugins || []).concat(esmi({
|
|
191
|
+
handleHotUpdate: (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
192
|
+
ctx.file;
|
|
193
|
+
// TODO: incremental refresh by ctx.file
|
|
194
|
+
yield refreshImportMap();
|
|
195
|
+
// TODO: refresh page when importmap changed
|
|
196
|
+
}),
|
|
197
|
+
}));
|
|
198
|
+
return memo;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
// TODO: webpack implementation
|
|
203
|
+
}
|
|
44
204
|
};
|
|
@@ -34,7 +34,7 @@ exports.default = (api) => {
|
|
|
34
34
|
}
|
|
35
35
|
return memo;
|
|
36
36
|
}));
|
|
37
|
-
api.
|
|
37
|
+
api.addBeforeMiddlewares(() => [
|
|
38
38
|
(req, res, next) => {
|
|
39
39
|
if (api.appData.faviconFile &&
|
|
40
40
|
req.path === `/${api.appData.faviconFile}`) {
|
|
@@ -53,6 +53,8 @@ exports.default = (api) => {
|
|
|
53
53
|
}
|
|
54
54
|
});
|
|
55
55
|
api.modifyHTMLFavicon((memo) => {
|
|
56
|
-
return
|
|
56
|
+
return api.appData.faviconFile
|
|
57
|
+
? `${api.config.publicPath}${api.appData.faviconFile}`
|
|
58
|
+
: memo;
|
|
57
59
|
});
|
|
58
60
|
};
|
|
@@ -3,11 +3,13 @@ import * as t from '@umijs/bundler-utils/compiled/babel/types';
|
|
|
3
3
|
import { IOpts } from './lowImport';
|
|
4
4
|
interface IPluginOpts {
|
|
5
5
|
opts: IOpts;
|
|
6
|
+
css: string;
|
|
6
7
|
}
|
|
7
8
|
export default function (): {
|
|
8
9
|
visitor: {
|
|
9
10
|
Identifier(path: Babel.NodePath<t.Identifier>, state: {
|
|
10
11
|
opts: IPluginOpts;
|
|
12
|
+
file: any;
|
|
11
13
|
}): void;
|
|
12
14
|
MemberExpression(path: Babel.NodePath<t.MemberExpression>, state: {
|
|
13
15
|
opts: IPluginOpts;
|
|
@@ -21,11 +21,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
22
|
const helper_module_imports_1 = require("@umijs/bundler-utils/compiled/babel/helper-module-imports");
|
|
23
23
|
const t = __importStar(require("@umijs/bundler-utils/compiled/babel/types"));
|
|
24
|
+
const path_1 = require("path");
|
|
24
25
|
function default_1() {
|
|
25
26
|
return {
|
|
26
27
|
visitor: {
|
|
27
28
|
Identifier(path, state) {
|
|
28
|
-
var _a, _b;
|
|
29
|
+
var _a, _b, _c;
|
|
29
30
|
const { name } = path.node;
|
|
30
31
|
if (path.scope.hasBinding(path.node.name)) {
|
|
31
32
|
return;
|
|
@@ -44,7 +45,15 @@ function default_1() {
|
|
|
44
45
|
nameHint: name,
|
|
45
46
|
}));
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
+
else if ((_c = state.opts.opts.namespaceToLib) === null || _c === void 0 ? void 0 : _c[name]) {
|
|
49
|
+
path.replaceWith((0, helper_module_imports_1.addNamespace)(path, state.opts.opts.namespaceToLib[name]));
|
|
50
|
+
}
|
|
51
|
+
// import css
|
|
52
|
+
if (name === 'styles' && state.opts.css) {
|
|
53
|
+
const { filename } = state.file.opts;
|
|
54
|
+
const cssFilename = (0, path_1.basename)(filename, (0, path_1.extname)(filename)) + '.' + state.opts.css;
|
|
55
|
+
path.replaceWith((0, helper_module_imports_1.addDefault)(path, './' + cssFilename, { nameHint: name }));
|
|
56
|
+
}
|
|
48
57
|
},
|
|
49
58
|
MemberExpression(path, state) {
|
|
50
59
|
const { object, property } = path.node;
|
|
@@ -25,6 +25,7 @@ exports.default = (api) => {
|
|
|
25
25
|
schema(Joi) {
|
|
26
26
|
return Joi.object({
|
|
27
27
|
libs: Joi.array(),
|
|
28
|
+
css: Joi.string(),
|
|
28
29
|
});
|
|
29
30
|
},
|
|
30
31
|
},
|
|
@@ -46,7 +47,7 @@ exports.default = (api) => {
|
|
|
46
47
|
const memberDts = (lib.members || [])
|
|
47
48
|
.map((member) => `${member}: typeof import('${lib.importFrom}')['${member}'],`)
|
|
48
49
|
.join('\n');
|
|
49
|
-
return `const ${lib.withObj}
|
|
50
|
+
return `const ${lib.withObj} : {\n${memberDts}\n};`;
|
|
50
51
|
}
|
|
51
52
|
else if (lib.namespaceImport) {
|
|
52
53
|
return `const ${lib.namespaceImport}: typeof import('${lib.importFrom}');`;
|
|
@@ -60,20 +61,24 @@ exports.default = (api) => {
|
|
|
60
61
|
.join('\n');
|
|
61
62
|
}
|
|
62
63
|
});
|
|
64
|
+
// TODO: styles 的类型提示
|
|
63
65
|
const content = `
|
|
64
66
|
// generated by umi
|
|
65
67
|
declare global {
|
|
66
|
-
${dts}
|
|
68
|
+
${dts.join('\n')}
|
|
69
|
+
const styles: any;
|
|
67
70
|
}
|
|
68
71
|
export {}
|
|
69
72
|
`.trim() + `\n`;
|
|
70
73
|
(0, fs_1.writeFileSync)((0, path_1.join)(api.paths.cwd, 'lowImport.d.ts'), content, 'utf-8');
|
|
71
74
|
});
|
|
72
75
|
api.addBeforeBabelPresets(() => {
|
|
76
|
+
var _a;
|
|
73
77
|
const opts = normalizeLibs(api.appData.lowImport);
|
|
78
|
+
const css = ((_a = api.config.lowImport) === null || _a === void 0 ? void 0 : _a.css) || 'less';
|
|
74
79
|
return [
|
|
75
80
|
{
|
|
76
|
-
plugins: [[babelPlugin_1.default, { opts }]],
|
|
81
|
+
plugins: [[babelPlugin_1.default, { opts, css }]],
|
|
77
82
|
},
|
|
78
83
|
];
|
|
79
84
|
});
|
|
@@ -51,6 +51,10 @@ function getRoutes(opts) {
|
|
|
51
51
|
routes,
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
|
+
routes = yield opts.api.applyPlugins({
|
|
55
|
+
key: 'modifyRoutes',
|
|
56
|
+
initialValue: routes,
|
|
57
|
+
});
|
|
54
58
|
return routes;
|
|
55
59
|
});
|
|
56
60
|
}
|
|
@@ -62,6 +66,12 @@ function getRouteComponents(opts) {
|
|
|
62
66
|
const route = opts.routes[key];
|
|
63
67
|
if (!route.file)
|
|
64
68
|
return `// ${key}: no file to import`;
|
|
69
|
+
// e.g.
|
|
70
|
+
// component: () => <h1>foo</h1>
|
|
71
|
+
// component: (() => () => <h1>foo</h1>)()
|
|
72
|
+
if (route.file.startsWith('(')) {
|
|
73
|
+
return `'${key}': () => Promise.resolve(${route.file}),`;
|
|
74
|
+
}
|
|
65
75
|
const path = (0, path_1.isAbsolute)(route.file) || route.file.startsWith('@/')
|
|
66
76
|
? route.file
|
|
67
77
|
: `${opts.prefix}${route.file}`;
|
|
@@ -27,9 +27,11 @@ exports.default = (api) => {
|
|
|
27
27
|
api.onGenerateFiles((opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
28
|
// umi.ts
|
|
29
29
|
api.writeTmpFile({
|
|
30
|
+
noPluginDir: true,
|
|
30
31
|
path: 'umi.ts',
|
|
31
32
|
tplPath: (0, path_1.join)(constants_1.TEMPLATES_DIR, 'umi.tpl'),
|
|
32
33
|
context: {
|
|
34
|
+
mountElementId: api.config.mountElementId,
|
|
33
35
|
rendererPath: yield api.applyPlugins({
|
|
34
36
|
key: 'modifyRendererPath',
|
|
35
37
|
initialValue: '@umijs/renderer-react',
|
|
@@ -54,6 +56,7 @@ exports.default = (api) => {
|
|
|
54
56
|
key: 'addEntryImports',
|
|
55
57
|
initialValue: [],
|
|
56
58
|
})).join('\n'),
|
|
59
|
+
basename: api.config.base,
|
|
57
60
|
},
|
|
58
61
|
});
|
|
59
62
|
// route.ts
|
|
@@ -70,7 +73,8 @@ exports.default = (api) => {
|
|
|
70
73
|
// @/pages/
|
|
71
74
|
const prefix = hasSrc ? '../../../src/pages/' : '../../pages/';
|
|
72
75
|
api.writeTmpFile({
|
|
73
|
-
|
|
76
|
+
noPluginDir: true,
|
|
77
|
+
path: 'core/route.tsx',
|
|
74
78
|
tplPath: (0, path_1.join)(constants_1.TEMPLATES_DIR, 'route.tpl'),
|
|
75
79
|
context: {
|
|
76
80
|
routes: JSON.stringify(routes),
|
|
@@ -99,17 +103,19 @@ exports.default = (api) => {
|
|
|
99
103
|
initialValue: [
|
|
100
104
|
// TODO: support these methods
|
|
101
105
|
// 'modifyClientRenderOpts',
|
|
102
|
-
|
|
106
|
+
'patchRoutes',
|
|
103
107
|
'rootContainer',
|
|
104
108
|
'innerProvider',
|
|
105
109
|
'i18nProvider',
|
|
110
|
+
'accessProvider',
|
|
106
111
|
'dataflowProvider',
|
|
107
112
|
'outerProvider',
|
|
108
|
-
|
|
113
|
+
'render',
|
|
109
114
|
// 'onRouteChange',
|
|
110
115
|
],
|
|
111
116
|
});
|
|
112
117
|
api.writeTmpFile({
|
|
118
|
+
noPluginDir: true,
|
|
113
119
|
path: 'core/plugin.ts',
|
|
114
120
|
tplPath: (0, path_1.join)(constants_1.TEMPLATES_DIR, 'plugin.tpl'),
|
|
115
121
|
context: {
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ exports.default = () => {
|
|
|
15
15
|
require.resolve('./features/polyfill/polyfill'),
|
|
16
16
|
require.resolve('./features/tmpFiles/tmpFiles'),
|
|
17
17
|
require.resolve('./features/transform/transform'),
|
|
18
|
+
require.resolve('./features/lowImport/lowImport'),
|
|
18
19
|
// commands
|
|
19
20
|
require.resolve('./commands/build'),
|
|
20
21
|
require.resolve('./commands/config/config'),
|
package/dist/libs/scan.js
CHANGED
|
@@ -87,6 +87,7 @@ function scan(opts) {
|
|
|
87
87
|
const depPath = queueDeps.shift();
|
|
88
88
|
if (cache.has(depPath))
|
|
89
89
|
continue;
|
|
90
|
+
// TODO: use parseModule in bundler-utils
|
|
90
91
|
const content = yield getContent(depPath);
|
|
91
92
|
const { deps } = yield scanContent({ content });
|
|
92
93
|
cache.set(depPath, deps);
|
package/dist/registerMethods.js
CHANGED
|
@@ -7,6 +7,7 @@ const utils_1 = require("@umijs/utils");
|
|
|
7
7
|
const assert_1 = __importDefault(require("assert"));
|
|
8
8
|
const fs_1 = require("fs");
|
|
9
9
|
const path_1 = require("path");
|
|
10
|
+
const transformIEAR_1 = __importDefault(require("./utils/transformIEAR"));
|
|
10
11
|
const isTypeScriptFile_1 = require("./utils/isTypeScriptFile");
|
|
11
12
|
exports.default = (api) => {
|
|
12
13
|
[
|
|
@@ -52,7 +53,7 @@ exports.default = (api) => {
|
|
|
52
53
|
// 'modifyExportRouteMap',
|
|
53
54
|
// 'modifyPublicPathStr',
|
|
54
55
|
'modifyRendererPath',
|
|
55
|
-
|
|
56
|
+
'modifyRoutes',
|
|
56
57
|
].forEach((name) => {
|
|
57
58
|
api.registerMethod({ name });
|
|
58
59
|
});
|
|
@@ -60,7 +61,9 @@ exports.default = (api) => {
|
|
|
60
61
|
name: 'writeTmpFile',
|
|
61
62
|
fn(opts) {
|
|
62
63
|
(0, assert_1.default)(api.service.stage >= api.ServiceStage.runCommand, `api.writeTmpFile() should not execute in register stage.`);
|
|
63
|
-
const absPath = (0, path_1.join)(api.paths.absTmpPath,
|
|
64
|
+
const absPath = (0, path_1.join)(api.paths.absTmpPath,
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
this.plugin.key && !opts.noPluginDir ? `plugin-${this.plugin.key}` : '', opts.path);
|
|
64
67
|
utils_1.fsExtra.mkdirpSync((0, path_1.dirname)(absPath));
|
|
65
68
|
let content = opts.content;
|
|
66
69
|
if (!content) {
|
|
@@ -77,10 +80,15 @@ exports.default = (api) => {
|
|
|
77
80
|
(0, isTypeScriptFile_1.isTypeScriptFile)(opts.path) && `// @ts-nocheck`,
|
|
78
81
|
'// This file is generated by Umi automatically',
|
|
79
82
|
'// DO NOT CHANGE IT MANUALLY!',
|
|
80
|
-
content,
|
|
83
|
+
content.trim(),
|
|
84
|
+
'',
|
|
81
85
|
]
|
|
82
86
|
.filter((text) => text !== false)
|
|
83
87
|
.join('\n');
|
|
88
|
+
// transform imports for all javascript-like files
|
|
89
|
+
if (/\.(t|j)sx?$/.test(absPath)) {
|
|
90
|
+
content = (0, transformIEAR_1.default)({ content, path: absPath }, api);
|
|
91
|
+
}
|
|
84
92
|
if (!(0, fs_1.existsSync)(absPath) || (0, fs_1.readFileSync)(absPath, 'utf-8') !== content) {
|
|
85
93
|
(0, fs_1.writeFileSync)(absPath, content, 'utf-8');
|
|
86
94
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type WebpackChain from '@umijs/bundler-webpack/compiled/webpack-5-chain';
|
|
|
4
4
|
import type { IAdd, IEvent, IModify, IRoute as ICoreRoute, IServicePluginAPI, PluginAPI } from '@umijs/core';
|
|
5
5
|
import { Env } from '@umijs/core';
|
|
6
6
|
import type { CheerioAPI } from '@umijs/utils/compiled/cheerio';
|
|
7
|
+
import type { InlineConfig as ViteInlineConfig } from 'vite';
|
|
7
8
|
export declare type IScript = Partial<{
|
|
8
9
|
async: boolean;
|
|
9
10
|
charset: string;
|
|
@@ -48,6 +49,7 @@ export declare type IApi = PluginAPI & IServicePluginAPI & {
|
|
|
48
49
|
restartServer: () => void;
|
|
49
50
|
writeTmpFile: (opts: {
|
|
50
51
|
path: string;
|
|
52
|
+
noPluginDir?: boolean;
|
|
51
53
|
content?: string;
|
|
52
54
|
tpl?: string;
|
|
53
55
|
tplPath?: string;
|
|
@@ -129,11 +131,12 @@ export declare type IApi = PluginAPI & IServicePluginAPI & {
|
|
|
129
131
|
path: string;
|
|
130
132
|
}>;
|
|
131
133
|
modifyRendererPath: IModify<string, {}>;
|
|
134
|
+
modifyRoutes: IModify<Record<string, IRoute>, {}>;
|
|
132
135
|
modifyWebpackConfig: IModify<webpack.Configuration, {
|
|
133
136
|
webpack: typeof webpack;
|
|
134
137
|
env: Env;
|
|
135
138
|
}>;
|
|
136
|
-
modifyViteConfig: IModify<
|
|
139
|
+
modifyViteConfig: IModify<ViteInlineConfig, {
|
|
137
140
|
env: Env;
|
|
138
141
|
}>;
|
|
139
142
|
chainWebpack: {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { IApi } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* import/export/await-import/require match regular expression
|
|
4
|
+
*
|
|
5
|
+
* WHY: REGEXP
|
|
6
|
+
* ref: https://github.com/umijs/umi-next/pull/230
|
|
7
|
+
*
|
|
8
|
+
* TODO: more choices
|
|
9
|
+
* 1. fork es-module-lexer, support jsx
|
|
10
|
+
* 2. use sourcemap of esbuild
|
|
11
|
+
*/
|
|
12
|
+
export declare const IEAR_REG_EXP: RegExp;
|
|
13
|
+
/**
|
|
14
|
+
* transform absolute import/export/await-import/require path
|
|
15
|
+
* @note use to vite can deps:
|
|
16
|
+
* transform to relative path for .umi dir imports
|
|
17
|
+
* prefix `@fs` for node_modules imports
|
|
18
|
+
*/
|
|
19
|
+
export default function transformIEAR({ content, path }: {
|
|
20
|
+
content: string;
|
|
21
|
+
path: string;
|
|
22
|
+
}, api: IApi): string;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IEAR_REG_EXP = void 0;
|
|
4
|
+
const utils_1 = require("@umijs/utils");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
/**
|
|
7
|
+
* import/export/await-import/require match regular expression
|
|
8
|
+
*
|
|
9
|
+
* WHY: REGEXP
|
|
10
|
+
* ref: https://github.com/umijs/umi-next/pull/230
|
|
11
|
+
*
|
|
12
|
+
* TODO: more choices
|
|
13
|
+
* 1. fork es-module-lexer, support jsx
|
|
14
|
+
* 2. use sourcemap of esbuild
|
|
15
|
+
*/
|
|
16
|
+
exports.IEAR_REG_EXP = new RegExp([
|
|
17
|
+
// match content before quote ($1)
|
|
18
|
+
'(',
|
|
19
|
+
[
|
|
20
|
+
// import/export statements
|
|
21
|
+
[
|
|
22
|
+
'(?:',
|
|
23
|
+
// match head
|
|
24
|
+
'(?:^|\\r|\\n|;)\\s*',
|
|
25
|
+
// match identifier
|
|
26
|
+
'(?:import|export)\\s+',
|
|
27
|
+
[
|
|
28
|
+
'(?:',
|
|
29
|
+
'(?:',
|
|
30
|
+
// match body
|
|
31
|
+
[
|
|
32
|
+
// match default & member import
|
|
33
|
+
[
|
|
34
|
+
// match default import
|
|
35
|
+
[
|
|
36
|
+
'(?:',
|
|
37
|
+
// match type import
|
|
38
|
+
'(?:type\\s*)?',
|
|
39
|
+
// match variable name
|
|
40
|
+
'[a-zA-Z_$][\\w_$]*\\s*,?\\s+',
|
|
41
|
+
// optional
|
|
42
|
+
')?',
|
|
43
|
+
].join(''),
|
|
44
|
+
// match member import/export (optional)
|
|
45
|
+
'(?:{[^}]+}\\s+)?',
|
|
46
|
+
].join(''),
|
|
47
|
+
// match contents import/export
|
|
48
|
+
'(?:type\\s*)?\\*\\s+(?:as\\s+[a-zA-Z][\\w_$]*\\s+)?',
|
|
49
|
+
].join('|'),
|
|
50
|
+
')',
|
|
51
|
+
// match from
|
|
52
|
+
'from\\s+',
|
|
53
|
+
// match direct file import
|
|
54
|
+
'|\\s*',
|
|
55
|
+
')',
|
|
56
|
+
].join(''),
|
|
57
|
+
')',
|
|
58
|
+
].join(''),
|
|
59
|
+
// import/require call
|
|
60
|
+
[
|
|
61
|
+
// match head (must be single function name)
|
|
62
|
+
'(?:^|[^a-zA-Z\\w_$\\.])',
|
|
63
|
+
// match call
|
|
64
|
+
'(?:import|require)\\(\\s*',
|
|
65
|
+
].join(''),
|
|
66
|
+
].join('|'),
|
|
67
|
+
')',
|
|
68
|
+
'(?:',
|
|
69
|
+
// match quotes ($2)
|
|
70
|
+
`('|")`,
|
|
71
|
+
// match absolute file path ($3)
|
|
72
|
+
`(\\/.*[^\\\\])\\2`,
|
|
73
|
+
')',
|
|
74
|
+
].join(''),
|
|
75
|
+
// match full-content
|
|
76
|
+
'g');
|
|
77
|
+
/**
|
|
78
|
+
* transform absolute import/export/await-import/require path
|
|
79
|
+
* @note use to vite can deps:
|
|
80
|
+
* transform to relative path for .umi dir imports
|
|
81
|
+
* prefix `@fs` for node_modules imports
|
|
82
|
+
*/
|
|
83
|
+
function transformIEAR({ content, path }, api) {
|
|
84
|
+
return content.replace(exports.IEAR_REG_EXP, (_, prefix, quote, absPath) => {
|
|
85
|
+
if (absPath.startsWith(api.paths.absTmpPath)) {
|
|
86
|
+
// transform .umi absolute imports
|
|
87
|
+
absPath = (0, utils_1.winPath)((0, path_1.relative)((0, path_1.dirname)(path), absPath));
|
|
88
|
+
}
|
|
89
|
+
else if (absPath.includes('node_modules')) {
|
|
90
|
+
// transform node_modules absolute imports
|
|
91
|
+
absPath = `@fs${absPath}`;
|
|
92
|
+
}
|
|
93
|
+
return `${prefix}${quote}${absPath}${quote}`;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
exports.default = transformIEAR;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umijs/preset-umi",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.14",
|
|
4
4
|
"description": "@umijs/preset-umi",
|
|
5
5
|
"homepage": "https://github.com/umijs/umi-next/tree/master/packages/preset-umi#readme",
|
|
6
6
|
"bugs": "https://github.com/umijs/umi-next/issues",
|
|
@@ -24,28 +24,30 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@types/multer": "1.4.7",
|
|
27
|
-
"@umijs/ast": "4.0.0-beta.
|
|
28
|
-
"@umijs/babel-preset-umi": "4.0.0-beta.
|
|
29
|
-
"@umijs/bundler-utils": "4.0.0-beta.
|
|
30
|
-
"@umijs/bundler-vite": "4.0.0-beta.
|
|
31
|
-
"@umijs/bundler-webpack": "4.0.0-beta.
|
|
32
|
-
"@umijs/core": "4.0.0-beta.
|
|
33
|
-
"@umijs/renderer-react": "4.0.0-beta.
|
|
34
|
-
"@umijs/server": "4.0.0-beta.
|
|
35
|
-
"@umijs/utils": "4.0.0-beta.
|
|
27
|
+
"@umijs/ast": "4.0.0-beta.14",
|
|
28
|
+
"@umijs/babel-preset-umi": "4.0.0-beta.14",
|
|
29
|
+
"@umijs/bundler-utils": "4.0.0-beta.14",
|
|
30
|
+
"@umijs/bundler-vite": "4.0.0-beta.14",
|
|
31
|
+
"@umijs/bundler-webpack": "4.0.0-beta.14",
|
|
32
|
+
"@umijs/core": "4.0.0-beta.14",
|
|
33
|
+
"@umijs/renderer-react": "4.0.0-beta.14",
|
|
34
|
+
"@umijs/server": "4.0.0-beta.14",
|
|
35
|
+
"@umijs/utils": "4.0.0-beta.14",
|
|
36
36
|
"current-script-polyfill": "1.0.0",
|
|
37
37
|
"enhanced-resolve": "5.8.3",
|
|
38
|
+
"magic-string": "0.25.7",
|
|
38
39
|
"path-to-regexp": "1.7.0",
|
|
39
|
-
"react": "18.0.0-
|
|
40
|
-
"react-dom": "18.0.0-
|
|
41
|
-
"react-router": "6.
|
|
42
|
-
"react-router-dom": "6.
|
|
40
|
+
"react": "18.0.0-rc.0",
|
|
41
|
+
"react-dom": "18.0.0-rc.0",
|
|
42
|
+
"react-router": "6.1.1",
|
|
43
|
+
"react-router-dom": "6.1.1"
|
|
43
44
|
},
|
|
44
45
|
"devDependencies": {
|
|
45
46
|
"@types/body-parser": "1.19.2",
|
|
46
47
|
"@types/multer": "1.4.7",
|
|
47
48
|
"body-parser": "1.19.0",
|
|
48
|
-
"multer": "1.4.3"
|
|
49
|
+
"multer": "1.4.3",
|
|
50
|
+
"vite": "2.7.6"
|
|
49
51
|
},
|
|
50
52
|
"publishConfig": {
|
|
51
53
|
"access": "public"
|
package/templates/plugin.tpl
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{{#plugins}}
|
|
2
2
|
import * as Plugin_{{{ index }}} from '{{{ path }}}';
|
|
3
3
|
{{/plugins}}
|
|
4
|
+
import { PluginManager } from 'umi';
|
|
4
5
|
|
|
5
6
|
export function getPlugins() {
|
|
6
7
|
return [
|
|
@@ -16,3 +17,16 @@ export function getPlugins() {
|
|
|
16
17
|
export function getValidKeys() {
|
|
17
18
|
return [{{#validKeys}}'{{{ . }}}',{{/validKeys}}];
|
|
18
19
|
}
|
|
20
|
+
|
|
21
|
+
let pluginManager = null;
|
|
22
|
+
export function createPluginManager() {
|
|
23
|
+
pluginManager = PluginManager.create({
|
|
24
|
+
plugins: getPlugins(),
|
|
25
|
+
validKeys: getValidKeys(),
|
|
26
|
+
});
|
|
27
|
+
return pluginManager;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function getPluginManager() {
|
|
31
|
+
return pluginManager;
|
|
32
|
+
}
|
package/templates/umi.tpl
CHANGED
|
@@ -2,19 +2,40 @@
|
|
|
2
2
|
{{{ importsAhead }}}
|
|
3
3
|
import { renderClient } from '{{{ rendererPath }}}';
|
|
4
4
|
import { getRoutes } from './core/route';
|
|
5
|
-
import {
|
|
6
|
-
import { PluginManager } from 'umi';
|
|
5
|
+
import { createPluginManager } from './core/plugin';
|
|
6
|
+
import { ApplyPluginsType, PluginManager } from 'umi';
|
|
7
7
|
{{{ imports }}}
|
|
8
8
|
|
|
9
9
|
async function render() {
|
|
10
|
+
const pluginManager = createPluginManager();
|
|
11
|
+
const { routes, routeComponents } = await getRoutes(pluginManager);
|
|
12
|
+
|
|
13
|
+
// allow user to extend routes
|
|
14
|
+
pluginManager.applyPlugins({
|
|
15
|
+
key: 'patchRoutes',
|
|
16
|
+
type: 'event',
|
|
17
|
+
args: {
|
|
18
|
+
routes,
|
|
19
|
+
routeComponents,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
10
22
|
const context = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
23
|
+
routes,
|
|
24
|
+
routeComponents,
|
|
25
|
+
pluginManager,
|
|
26
|
+
rootElement: document.getElementById('{{{ mountElementId }}}'),
|
|
27
|
+
{{#basename}}
|
|
28
|
+
basename: '{{{ basename }}}',
|
|
29
|
+
{{/basename}}
|
|
16
30
|
};
|
|
17
|
-
|
|
31
|
+
|
|
32
|
+
return (pluginManager.applyPlugins({
|
|
33
|
+
key: 'render',
|
|
34
|
+
type: ApplyPluginsType.compose,
|
|
35
|
+
initialValue() {
|
|
36
|
+
return renderClient(context);
|
|
37
|
+
},
|
|
38
|
+
}))();
|
|
18
39
|
}
|
|
19
40
|
|
|
20
41
|
{{{ entryCodeAhead }}}
|