@lark-apaas/fullstack-rspack-preset 1.0.32-alpha.3 → 1.0.32-alpha.31
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/lib/index.js +1 -0
- package/lib/module-alias/echarts-for-react.d.ts +14 -0
- package/lib/module-alias/echarts-for-react.js +137 -0
- package/lib/module-alias/echarts.d.ts +4 -0
- package/lib/module-alias/echarts.js +36 -0
- package/lib/module-alias/registry_echarts_theme.d.ts +2 -6
- package/lib/module-alias/registry_echarts_theme.js +1 -1
- package/lib/overlay/index.js +20 -1
- package/lib/polyfills/index.d.ts +14 -0
- package/lib/polyfills/index.js +35 -0
- package/lib/preset.js +106 -16
- package/lib/rspack-plugins/css-legacy-plugin.d.ts +30 -0
- package/lib/rspack-plugins/css-legacy-plugin.js +218 -0
- package/lib/rspack-plugins/polyfill-plugin.d.ts +12 -0
- package/lib/rspack-plugins/polyfill-plugin.js +73 -0
- package/lib/rspack-plugins/route-parser-plugin.d.ts +11 -0
- package/lib/rspack-plugins/route-parser-plugin.js +188 -4
- package/lib/rspack-plugins/runtime-injection-plugin.d.ts +13 -0
- package/lib/rspack-plugins/runtime-injection-plugin.js +38 -0
- package/lib/rspack-plugins/slardar-performance-monitor-plugin.js +6 -2
- package/lib/rspack-plugins/source-map-upload-plugin.js +7 -2
- package/lib/rspack-plugins/static-assets-plugin.d.ts +59 -0
- package/lib/rspack-plugins/static-assets-plugin.js +383 -0
- package/package.json +9 -6
package/lib/index.js
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EChartsReact wrapper component
|
|
3
|
+
* - Automatically converts HSL colors to hex in option
|
|
4
|
+
* - Removes label.color from funnel series
|
|
5
|
+
*/
|
|
6
|
+
export class EChartsReact extends React.Component<any, any, any> {
|
|
7
|
+
constructor(props: any);
|
|
8
|
+
constructor(props: any, context: any);
|
|
9
|
+
render(): React.CElement<import("echarts-for-react").EChartsReactProps, OriginalReactECharts>;
|
|
10
|
+
}
|
|
11
|
+
export * from "echarts-for-react";
|
|
12
|
+
export default EChartsReact;
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import OriginalReactECharts from 'echarts-for-react';
|
|
@@ -0,0 +1,137 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.EChartsReact = void 0;
|
|
21
|
+
const react_1 = __importDefault(require("react"));
|
|
22
|
+
const echarts_for_react_1 = __importDefault(require("echarts-for-react"));
|
|
23
|
+
const colorjs_io_1 = __importDefault(require("colorjs.io"));
|
|
24
|
+
/**
|
|
25
|
+
* Convert HSL/HSLA color to hex or rgba
|
|
26
|
+
*/
|
|
27
|
+
function convertColorToHex(color) {
|
|
28
|
+
if (typeof color !== 'string')
|
|
29
|
+
return color;
|
|
30
|
+
const trimmed = color.trim();
|
|
31
|
+
if (!trimmed.startsWith('hsl')) {
|
|
32
|
+
return color;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const colorObj = new colorjs_io_1.default(trimmed);
|
|
36
|
+
if (colorObj.alpha < 1) {
|
|
37
|
+
return colorObj.to('srgb').toString({ format: 'rgba' });
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
return colorObj.to('srgb').toString({ format: 'hex' });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
console.warn(`Failed to convert color: ${color}`, error);
|
|
45
|
+
return color;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function convertColorValue(propValue, visited) {
|
|
49
|
+
if (typeof propValue === 'string') {
|
|
50
|
+
return convertColorToHex(propValue);
|
|
51
|
+
}
|
|
52
|
+
if (Array.isArray(propValue)) {
|
|
53
|
+
return propValue.map((item) => typeof item === 'string' ? convertColorToHex(item) : transformColors(item, visited));
|
|
54
|
+
}
|
|
55
|
+
return transformColors(propValue, visited);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Deep traverse object to transform all HSL colors in 'color' property
|
|
59
|
+
*/
|
|
60
|
+
function transformColors(value, visited = new WeakSet()) {
|
|
61
|
+
if (value === null || value === undefined)
|
|
62
|
+
return value;
|
|
63
|
+
if (typeof value !== 'object')
|
|
64
|
+
return value;
|
|
65
|
+
if (visited.has(value))
|
|
66
|
+
return value;
|
|
67
|
+
if (value instanceof Date || value instanceof RegExp)
|
|
68
|
+
return value;
|
|
69
|
+
visited.add(value);
|
|
70
|
+
if (Array.isArray(value)) {
|
|
71
|
+
return value.map((item) => transformColors(item, visited));
|
|
72
|
+
}
|
|
73
|
+
const result = {};
|
|
74
|
+
for (const key in value) {
|
|
75
|
+
if (!Object.prototype.hasOwnProperty.call(value, key))
|
|
76
|
+
continue;
|
|
77
|
+
const propValue = value[key];
|
|
78
|
+
if (key === 'color') {
|
|
79
|
+
if (typeof propValue === 'function') {
|
|
80
|
+
result[key] = (...args) => convertColorValue(propValue(...args), visited);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
result[key] = convertColorValue(propValue, visited);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
result[key] = transformColors(propValue, visited);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Remove label.color and emphasis.label.color from funnel series
|
|
94
|
+
* to let ECharts use default contrast colors
|
|
95
|
+
*/
|
|
96
|
+
function removeFunnelLabelColor(option) {
|
|
97
|
+
if (!Array.isArray(option.series))
|
|
98
|
+
return option;
|
|
99
|
+
const series = option.series.map((item) => {
|
|
100
|
+
if (item?.type !== 'funnel')
|
|
101
|
+
return item;
|
|
102
|
+
let result = { ...item };
|
|
103
|
+
// remove label.color
|
|
104
|
+
if (result.label && typeof result.label === 'object') {
|
|
105
|
+
const { color: _, ...labelRest } = result.label;
|
|
106
|
+
result = { ...result, label: labelRest };
|
|
107
|
+
}
|
|
108
|
+
// remove emphasis.label.color
|
|
109
|
+
const emphasis = result.emphasis;
|
|
110
|
+
if (emphasis?.label && typeof emphasis.label === 'object') {
|
|
111
|
+
const { color: _, ...emphasisLabelRest } = emphasis.label;
|
|
112
|
+
result = { ...result, emphasis: { ...emphasis, label: emphasisLabelRest } };
|
|
113
|
+
}
|
|
114
|
+
return result;
|
|
115
|
+
});
|
|
116
|
+
return { ...option, series };
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* EChartsReact wrapper component
|
|
120
|
+
* - Automatically converts HSL colors to hex in option
|
|
121
|
+
* - Removes label.color from funnel series
|
|
122
|
+
*/
|
|
123
|
+
class EChartsReact extends react_1.default.Component {
|
|
124
|
+
render() {
|
|
125
|
+
const { option, ...rest } = this.props;
|
|
126
|
+
const transformedOption = option
|
|
127
|
+
? removeFunnelLabelColor(transformColors(option))
|
|
128
|
+
: option;
|
|
129
|
+
return react_1.default.createElement(echarts_for_react_1.default, {
|
|
130
|
+
option: transformedOption,
|
|
131
|
+
...rest,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
exports.EChartsReact = EChartsReact;
|
|
136
|
+
__exportStar(require("echarts-for-react"), exports);
|
|
137
|
+
exports.default = EChartsReact;
|
|
@@ -10,21 +10,56 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
10
10
|
if (k2 === undefined) k2 = k;
|
|
11
11
|
o[k2] = m[k];
|
|
12
12
|
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
13
18
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
19
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
20
|
};
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
16
38
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
39
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
40
|
};
|
|
19
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
42
|
exports.echarts = void 0;
|
|
43
|
+
exports.registerEchartsToWindow = registerEchartsToWindow;
|
|
21
44
|
exports.resgisterEchartsTheme = resgisterEchartsTheme;
|
|
22
45
|
var echarts_1 = require("echarts");
|
|
23
46
|
Object.defineProperty(exports, "echarts", { enumerable: true, get: function () { return __importDefault(echarts_1).default; } });
|
|
24
47
|
__exportStar(require("echarts"), exports);
|
|
48
|
+
const echarts = __importStar(require("echarts"));
|
|
25
49
|
const echarts_2 = require("echarts");
|
|
26
50
|
const registry_echarts_theme_1 = require("./registry_echarts_theme");
|
|
27
51
|
let isRegistered = false;
|
|
52
|
+
let isWindowMounted = false;
|
|
53
|
+
/**
|
|
54
|
+
* Mount echarts to window for debugging
|
|
55
|
+
*/
|
|
56
|
+
function registerEchartsToWindow() {
|
|
57
|
+
if (isWindowMounted || typeof globalThis.window === 'undefined') {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
isWindowMounted = true;
|
|
61
|
+
globalThis.echarts = echarts;
|
|
62
|
+
}
|
|
28
63
|
function resgisterEchartsTheme() {
|
|
29
64
|
// 注册 ud 主题,全局仅注册一次
|
|
30
65
|
if (isRegistered) {
|
|
@@ -45,4 +80,5 @@ function resgisterEchartsTheme() {
|
|
|
45
80
|
}
|
|
46
81
|
}
|
|
47
82
|
}
|
|
83
|
+
registerEchartsToWindow();
|
|
48
84
|
resgisterEchartsTheme();
|
|
@@ -8,9 +8,7 @@ export declare function getCssVariable(varName: string, element?: HTMLElement):
|
|
|
8
8
|
export declare function generateEChartsTheme(element?: HTMLElement): {
|
|
9
9
|
color: string[];
|
|
10
10
|
backgroundColor: string;
|
|
11
|
-
textStyle: {
|
|
12
|
-
color: string;
|
|
13
|
-
};
|
|
11
|
+
textStyle: {};
|
|
14
12
|
title: {
|
|
15
13
|
textStyle: {
|
|
16
14
|
color: string;
|
|
@@ -352,9 +350,7 @@ export declare function generateEChartsTheme(element?: HTMLElement): {
|
|
|
352
350
|
export declare function getShadcnEChartsTheme(): {
|
|
353
351
|
color: string[];
|
|
354
352
|
backgroundColor: string;
|
|
355
|
-
textStyle: {
|
|
356
|
-
color: string;
|
|
357
|
-
};
|
|
353
|
+
textStyle: {};
|
|
358
354
|
title: {
|
|
359
355
|
textStyle: {
|
|
360
356
|
color: string;
|
package/lib/overlay/index.js
CHANGED
|
@@ -129,6 +129,25 @@ function removeAllChildren(element, skip) {
|
|
|
129
129
|
element.removeChild(childList[i]);
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
|
+
function getParentOriginFromParams() {
|
|
133
|
+
try {
|
|
134
|
+
var params = new URLSearchParams(window.location.search);
|
|
135
|
+
var origin = params.get('__parentOrigin');
|
|
136
|
+
if (origin) {
|
|
137
|
+
sessionStorage.setItem('__parentOrigin', origin);
|
|
138
|
+
return origin;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
// ignore
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
return sessionStorage.getItem('__parentOrigin') || '';
|
|
146
|
+
}
|
|
147
|
+
catch (e) {
|
|
148
|
+
return '';
|
|
149
|
+
}
|
|
150
|
+
}
|
|
132
151
|
function getLegacyParentOrigin() {
|
|
133
152
|
const currentOrigin = window.location?.origin || '';
|
|
134
153
|
if (currentOrigin.includes('force.feishuapp.net')) {
|
|
@@ -150,7 +169,7 @@ function getLegacyParentOrigin() {
|
|
|
150
169
|
}
|
|
151
170
|
function sendPostMessage(message, targetOrigin) {
|
|
152
171
|
try {
|
|
153
|
-
const parentOrigin = process?.env?.FORCE_FRAMEWORK_DOMAIN_MAIN || getLegacyParentOrigin();
|
|
172
|
+
const parentOrigin = getParentOriginFromParams() || process?.env?.FORCE_FRAMEWORK_DOMAIN_MAIN || getLegacyParentOrigin();
|
|
154
173
|
const origin = targetOrigin || parentOrigin;
|
|
155
174
|
window.parent.postMessage(message, origin);
|
|
156
175
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iOS 兼容性 Polyfills
|
|
3
|
+
*
|
|
4
|
+
* 使用 core-js 提供 iOS 15.4 以下版本需要的 polyfill
|
|
5
|
+
* 此文件会被单独打包成 polyfills.js,按需加载
|
|
6
|
+
*/
|
|
7
|
+
import 'core-js/actual/array/at';
|
|
8
|
+
import 'core-js/actual/string/at';
|
|
9
|
+
import 'core-js/actual/array/find-last';
|
|
10
|
+
import 'core-js/actual/array/find-last-index';
|
|
11
|
+
import 'core-js/actual/object/has-own';
|
|
12
|
+
import 'core-js/actual/promise/any';
|
|
13
|
+
import 'core-js/actual/aggregate-error';
|
|
14
|
+
import 'core-js/actual/structured-clone';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* iOS 兼容性 Polyfills
|
|
4
|
+
*
|
|
5
|
+
* 使用 core-js 提供 iOS 15.4 以下版本需要的 polyfill
|
|
6
|
+
* 此文件会被单独打包成 polyfills.js,按需加载
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
// ECMAScript polyfills (core-js)
|
|
10
|
+
require("core-js/actual/array/at");
|
|
11
|
+
require("core-js/actual/string/at");
|
|
12
|
+
require("core-js/actual/array/find-last");
|
|
13
|
+
require("core-js/actual/array/find-last-index");
|
|
14
|
+
require("core-js/actual/object/has-own");
|
|
15
|
+
require("core-js/actual/promise/any");
|
|
16
|
+
require("core-js/actual/aggregate-error");
|
|
17
|
+
require("core-js/actual/structured-clone");
|
|
18
|
+
// Web Crypto API polyfill (不在 core-js 范围内)
|
|
19
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID !== 'function') {
|
|
20
|
+
Object.defineProperty(crypto, 'randomUUID', {
|
|
21
|
+
value: function randomUUID() {
|
|
22
|
+
const bytes = new Uint8Array(16);
|
|
23
|
+
crypto.getRandomValues(bytes);
|
|
24
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
25
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
26
|
+
let hex = '';
|
|
27
|
+
for (let i = 0; i < 16; i++) {
|
|
28
|
+
hex += (bytes[i] < 16 ? '0' : '') + bytes[i].toString(16);
|
|
29
|
+
}
|
|
30
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
31
|
+
},
|
|
32
|
+
writable: true,
|
|
33
|
+
configurable: true,
|
|
34
|
+
});
|
|
35
|
+
}
|
package/lib/preset.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createRecommendRspackConfig = createRecommendRspackConfig;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
8
|
const path_1 = __importDefault(require("path"));
|
|
8
9
|
const core_1 = __importDefault(require("@rspack/core"));
|
|
9
10
|
const devtool_kits_1 = require("@lark-apaas/devtool-kits");
|
|
@@ -13,6 +14,10 @@ const route_parser_plugin_1 = __importDefault(require("./rspack-plugins/route-pa
|
|
|
13
14
|
const slardar_performance_monitor_plugin_1 = __importDefault(require("./rspack-plugins/slardar-performance-monitor-plugin"));
|
|
14
15
|
const view_context_injection_plugin_1 = __importDefault(require("./rspack-plugins/view-context-injection-plugin"));
|
|
15
16
|
const og_meta_injection_plugin_1 = __importDefault(require("./rspack-plugins/og-meta-injection-plugin"));
|
|
17
|
+
const runtime_injection_plugin_1 = __importDefault(require("./rspack-plugins/runtime-injection-plugin"));
|
|
18
|
+
const css_legacy_plugin_1 = __importDefault(require("./rspack-plugins/css-legacy-plugin"));
|
|
19
|
+
const polyfill_plugin_1 = __importDefault(require("./rspack-plugins/polyfill-plugin"));
|
|
20
|
+
const static_assets_plugin_1 = __importDefault(require("./rspack-plugins/static-assets-plugin"));
|
|
16
21
|
const source_map_upload_plugin_1 = __importDefault(require("./rspack-plugins/source-map-upload-plugin"));
|
|
17
22
|
const dev_server_snapdom_proxy_1 = require("./utils/dev-server-snapdom-proxy");
|
|
18
23
|
function sendBackendUnavailable502(_err, _req, res) {
|
|
@@ -26,14 +31,51 @@ function sendBackendUnavailable502(_err, _req, res) {
|
|
|
26
31
|
}
|
|
27
32
|
// 检查是否启用宽松 build 模式
|
|
28
33
|
const isLooseMode = process.env.FORCE_FRAMEWORK_BUILD_LOOSE_MODE === 'true';
|
|
34
|
+
function readAppFlags(rootDir) {
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(rootDir, 'package.json'), 'utf-8')).flags || {};
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return {};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
29
42
|
function createRecommendRspackConfig(options) {
|
|
30
43
|
const { isDev = true, enableReactRefresh = isDev, needRoutes = true, clientBasePath = '', publicPath = '', // 静态资源路径
|
|
31
44
|
} = options;
|
|
32
45
|
const assetsCDNPath = publicPath + '/';
|
|
33
46
|
const rootDir = process.cwd();
|
|
34
47
|
const serverPort = process.env.SERVER_PORT || '3000';
|
|
48
|
+
const appFlags = readAppFlags(rootDir);
|
|
49
|
+
// 从 clientBasePath(如 /app/app123)中提取 appId,用于构造旧路径代理规则
|
|
50
|
+
// 仅在新路径格式(/app/:appId)下启用旧路径兼容
|
|
51
|
+
const isNewPathFormat = /^\/app\/[^/]/.test(clientBasePath);
|
|
52
|
+
const appId = isNewPathFormat
|
|
53
|
+
? clientBasePath.replace(/\/+$/, '').split('/').pop()
|
|
54
|
+
: '';
|
|
55
|
+
// 提前创建实例,以便在 plugins 和 setupMiddlewares 中复用
|
|
56
|
+
const staticAssetsPlugin = new static_assets_plugin_1.default({ clientBasePath, rootDir });
|
|
35
57
|
// 优先从环境变量获取 RELEASE_ID,否则使用时间戳作为兜底
|
|
36
58
|
const releaseId = process.env.RELEASE_ID || new Date().toISOString();
|
|
59
|
+
// 读取构建前生成的路由定义 JSON,供 DefinePlugin 注入到 bundle
|
|
60
|
+
// build.sh 在 client 构建之前已将 page-routes.json / api-routes.json 写入 dist/
|
|
61
|
+
let pageRouteDefinitions = [];
|
|
62
|
+
let apiRouteDefinitions = [];
|
|
63
|
+
if (needRoutes) {
|
|
64
|
+
try {
|
|
65
|
+
const pageRoutesPath = path_1.default.resolve(rootDir, 'dist/page-routes.json');
|
|
66
|
+
if (fs_1.default.existsSync(pageRoutesPath)) {
|
|
67
|
+
pageRouteDefinitions = JSON.parse(fs_1.default.readFileSync(pageRoutesPath, 'utf-8'));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch { /* ignore */ }
|
|
71
|
+
try {
|
|
72
|
+
const apiRoutesPath = path_1.default.resolve(rootDir, 'dist/api-routes.json');
|
|
73
|
+
if (fs_1.default.existsSync(apiRoutesPath)) {
|
|
74
|
+
apiRouteDefinitions = JSON.parse(fs_1.default.readFileSync(apiRoutesPath, 'utf-8'));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch { /* ignore */ }
|
|
78
|
+
}
|
|
37
79
|
return {
|
|
38
80
|
mode: isDev ? 'development' : 'production',
|
|
39
81
|
cache: false,
|
|
@@ -43,9 +85,20 @@ function createRecommendRspackConfig(options) {
|
|
|
43
85
|
resolve: {
|
|
44
86
|
mainFields: ['module', 'browser', 'main'],
|
|
45
87
|
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
|
|
88
|
+
alias: {
|
|
89
|
+
// 确保所有 echarts 子路径导入(如 echarts/core, echarts/lib/...)
|
|
90
|
+
// 都解析到 preset 自带的 echarts,避免第三方扩展(如 echarts-wordcloud)
|
|
91
|
+
// 安装了独立的 echarts 副本导致注册不到同一个实例上
|
|
92
|
+
echarts: path_1.default.dirname(require.resolve('echarts/package.json')),
|
|
93
|
+
},
|
|
46
94
|
},
|
|
47
95
|
module: {
|
|
48
96
|
rules: [
|
|
97
|
+
// Support ?raw query to import file content as string (like Vite's ?raw)
|
|
98
|
+
{
|
|
99
|
+
resourceQuery: /\?raw$/,
|
|
100
|
+
type: 'asset/source',
|
|
101
|
+
},
|
|
49
102
|
{
|
|
50
103
|
test: /\.svg$/,
|
|
51
104
|
type: 'asset',
|
|
@@ -120,11 +173,6 @@ function createRecommendRspackConfig(options) {
|
|
|
120
173
|
transform: {
|
|
121
174
|
react: {
|
|
122
175
|
runtime: 'automatic',
|
|
123
|
-
...(isDev
|
|
124
|
-
? {
|
|
125
|
-
importSource: path_1.default.dirname(require.resolve('@lark-apaas/miaoda-inspector-jsx-runtime')),
|
|
126
|
-
}
|
|
127
|
-
: {}),
|
|
128
176
|
development: isDev,
|
|
129
177
|
refresh: enableReactRefresh,
|
|
130
178
|
},
|
|
@@ -146,14 +194,19 @@ function createRecommendRspackConfig(options) {
|
|
|
146
194
|
],
|
|
147
195
|
},
|
|
148
196
|
plugins: [
|
|
197
|
+
// 运行时注入插件 - 自动将 @lark-apaas/client-toolkit/runtime 注入到所有入口之前
|
|
198
|
+
new runtime_injection_plugin_1.default(),
|
|
149
199
|
new core_1.default.BannerPlugin({
|
|
150
200
|
banner: `window.__RELEASE_COMMIT_ID__ = '${releaseId}';`,
|
|
151
201
|
raw: true,
|
|
152
202
|
}),
|
|
153
|
-
// 针对 clsx/echarts 等包,让其默认好用
|
|
154
|
-
new core_1.default.NormalModuleReplacementPlugin(/^(clsx|echarts)$/, function (resource) {
|
|
203
|
+
// 针对 clsx/echarts/echarts-for-react 等包,让其默认好用
|
|
204
|
+
new core_1.default.NormalModuleReplacementPlugin(/^(clsx|echarts|echarts-for-react)$/, function (resource) {
|
|
155
205
|
if (!resource.context.endsWith('module-alias')) {
|
|
156
|
-
if (resource.request
|
|
206
|
+
if (resource.request === 'echarts-for-react') {
|
|
207
|
+
resource.request = require.resolve('./module-alias/echarts-for-react');
|
|
208
|
+
}
|
|
209
|
+
else if (resource.request === 'echarts') {
|
|
157
210
|
resource.request = require.resolve('./module-alias/echarts');
|
|
158
211
|
}
|
|
159
212
|
else {
|
|
@@ -167,6 +220,15 @@ function createRecommendRspackConfig(options) {
|
|
|
167
220
|
'process.env.CLIENT_BASE_PATH': JSON.stringify(clientBasePath),
|
|
168
221
|
'process.env.FORCE_FRAMEWORK_DOMAIN_MAIN': JSON.stringify(process.env.FORCE_FRAMEWORK_DOMAIN_MAIN ?? ''),
|
|
169
222
|
'process.env.CWD': JSON.stringify(''),
|
|
223
|
+
// runtime 注入标志位,用于 client-toolkit 兼容性判断
|
|
224
|
+
'process.env.__RUNTIME_INJECTED__': JSON.stringify('true'),
|
|
225
|
+
// 构建工具标识,用于 source map 处理逻辑判断
|
|
226
|
+
'process.env.BUILD_TOOL': JSON.stringify('rspack'),
|
|
227
|
+
// 模板 flags 配置
|
|
228
|
+
'process.env.APP_FLAGS': JSON.stringify(appFlags),
|
|
229
|
+
// 路由定义,供客户端匹配 referer_path 和 api
|
|
230
|
+
'process.env.__PAGE_ROUTE_DEFINITIONS__': JSON.stringify(JSON.stringify(pageRouteDefinitions)),
|
|
231
|
+
'process.env.__API_ROUTE_DEFINITIONS__': JSON.stringify(JSON.stringify(apiRouteDefinitions)),
|
|
170
232
|
// 解决 window 未定义问题
|
|
171
233
|
'typeof window': JSON.stringify('object'),
|
|
172
234
|
window: 'globalThis',
|
|
@@ -189,17 +251,24 @@ function createRecommendRspackConfig(options) {
|
|
|
189
251
|
},
|
|
190
252
|
minify: false, // 关闭 html 压缩,导致数据注入异常
|
|
191
253
|
}),
|
|
254
|
+
// 视图上下文注入插件(必须在 slardar 之前,确保 HTML 中 viewContext 先于 slardar)
|
|
255
|
+
new view_context_injection_plugin_1.default(),
|
|
192
256
|
// 性能监控&tea埋点sdk插件
|
|
193
257
|
new slardar_performance_monitor_plugin_1.default(),
|
|
194
|
-
// 视图上下文注入插件
|
|
195
|
-
new view_context_injection_plugin_1.default(),
|
|
196
258
|
// OG Meta 标签注入插件
|
|
197
259
|
new og_meta_injection_plugin_1.default(),
|
|
198
|
-
//
|
|
199
|
-
isDev &&
|
|
260
|
+
// 生产环境:生成 legacy CSS 并注入检测脚本
|
|
261
|
+
!isDev && new css_legacy_plugin_1.default(),
|
|
262
|
+
// 生产环境:为旧浏览器提供 polyfill(仅在需要时加载)
|
|
263
|
+
!isDev && new polyfill_plugin_1.default(),
|
|
264
|
+
// 静态资源插件 - 支持 @shared/static/* 导入
|
|
265
|
+
staticAssetsPlugin,
|
|
266
|
+
// 解析路由(dev + prod 均生成 routes.json 和 page-routes.json)
|
|
267
|
+
needRoutes &&
|
|
200
268
|
new route_parser_plugin_1.default({
|
|
201
269
|
appPath: './client/src/app.tsx',
|
|
202
270
|
outputPath: path_1.default.resolve(rootDir, 'dist/client/routes.json'),
|
|
271
|
+
...(isDev ? { basePath: '' } : {}),
|
|
203
272
|
}),
|
|
204
273
|
// 热更新
|
|
205
274
|
enableReactRefresh && new plugin_react_refresh_1.default({
|
|
@@ -223,10 +292,14 @@ function createRecommendRspackConfig(options) {
|
|
|
223
292
|
minimizerOptions: {
|
|
224
293
|
// 保持不压缩
|
|
225
294
|
minify: !isDev,
|
|
226
|
-
mangle
|
|
295
|
+
// mangle 配置:启用 Safari 10 兼容性
|
|
296
|
+
mangle: !isDev ? {
|
|
297
|
+
safari10: true, // 避免 Safari 严格模式的重复参数问题
|
|
298
|
+
} : false,
|
|
227
299
|
format: {
|
|
228
300
|
beautify: isDev,
|
|
229
301
|
comments: false,
|
|
302
|
+
safari10: true, // Safari 10/11 兼容性修复
|
|
230
303
|
},
|
|
231
304
|
compress: {
|
|
232
305
|
keep_classnames: true,
|
|
@@ -313,6 +386,23 @@ function createRecommendRspackConfig(options) {
|
|
|
313
386
|
changeOrigin: true,
|
|
314
387
|
onError: sendBackendUnavailable502,
|
|
315
388
|
},
|
|
389
|
+
// 旧路径(/af/p/:appId)兼容代理,转发到 Node Server 由 legacy-path-redirect 中间件处理
|
|
390
|
+
...(appId
|
|
391
|
+
? [
|
|
392
|
+
{
|
|
393
|
+
context: [`/af/p/${appId}/api`],
|
|
394
|
+
target: `http://localhost:${serverPort}`,
|
|
395
|
+
changeOrigin: true,
|
|
396
|
+
onError: sendBackendUnavailable502,
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
context: [`/af/p/${appId}/__innerapi__`],
|
|
400
|
+
target: `http://localhost:${serverPort}`,
|
|
401
|
+
changeOrigin: true,
|
|
402
|
+
onError: sendBackendUnavailable502,
|
|
403
|
+
},
|
|
404
|
+
]
|
|
405
|
+
: []),
|
|
316
406
|
{
|
|
317
407
|
context: (pathname, req) => {
|
|
318
408
|
// 代理所有请求 HTML 响应的请求(页面路由)
|
|
@@ -325,9 +415,7 @@ function createRecommendRspackConfig(options) {
|
|
|
325
415
|
changeOrigin: true,
|
|
326
416
|
logLevel: 'debug',
|
|
327
417
|
onError: (err, req, res) => (0, devtool_kits_1.handleDevProxyError)(err, req, res, {
|
|
328
|
-
|
|
329
|
-
logFileName: 'server.std.log',
|
|
330
|
-
maxErrorLogs: 100,
|
|
418
|
+
target: `http://localhost:${serverPort}`,
|
|
331
419
|
}),
|
|
332
420
|
},
|
|
333
421
|
],
|
|
@@ -337,6 +425,8 @@ function createRecommendRspackConfig(options) {
|
|
|
337
425
|
},
|
|
338
426
|
setupMiddlewares: (middlewares, devServer) => {
|
|
339
427
|
if (devServer.app) {
|
|
428
|
+
// 开发环境下提供 shared/static 文件服务,对齐 Vite preset 的 configureServer 中间件
|
|
429
|
+
devServer.app.use(staticAssetsPlugin.createDevMiddleware());
|
|
340
430
|
(0, dev_server_snapdom_proxy_1.registerSnapDomProxyMiddleware)(devServer.app, { baseUrl: clientBasePath });
|
|
341
431
|
(0, devtool_kits_1.registerMiddlewares)(devServer.app, [
|
|
342
432
|
(0, devtool_kits_1.createDevLogsMiddleware)({ logDir: process.env.LOG_DIR || './logs' }),
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Compiler } from '@rspack/core';
|
|
2
|
+
/**
|
|
3
|
+
* CSS Legacy Plugin
|
|
4
|
+
*
|
|
5
|
+
* 在构建完成后生成一份兼容旧浏览器的 CSS 文件(.legacy.css)
|
|
6
|
+
* 并在 HTML 中注入检测脚本,根据浏览器版本加载对应的 CSS
|
|
7
|
+
*/
|
|
8
|
+
export declare class CssLegacyPlugin {
|
|
9
|
+
static pluginName: string;
|
|
10
|
+
apply(compiler: Compiler): void;
|
|
11
|
+
/**
|
|
12
|
+
* 预处理 CSS:移除/转换 LightningCSS 不支持降级的特性
|
|
13
|
+
*/
|
|
14
|
+
private preprocessCss;
|
|
15
|
+
/**
|
|
16
|
+
* 后处理 CSS:清理可能残留的不支持特性
|
|
17
|
+
*/
|
|
18
|
+
private postprocessCss;
|
|
19
|
+
/**
|
|
20
|
+
* 展开 @layer 规则,保留内部样式
|
|
21
|
+
*/
|
|
22
|
+
private unwrapAtLayer;
|
|
23
|
+
/**
|
|
24
|
+
* 移除 @supports (color: color-mix(...)) 块
|
|
25
|
+
* 这些是渐进增强代码,旧浏览器可以使用 fallback
|
|
26
|
+
*/
|
|
27
|
+
private removeColorMixSupports;
|
|
28
|
+
private generateDetectionScript;
|
|
29
|
+
}
|
|
30
|
+
export default CssLegacyPlugin;
|