@modern-js/runtime 2.37.2 → 2.38.0
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/cjs/ssr/cli/index.js +4 -1
- package/dist/cjs/ssr/serverRender/renderToString/entry.js +7 -4
- package/dist/cjs/ssr/serverRender/renderToString/loadable.js +80 -35
- package/dist/cjs/ssr/serverRender/renderToString/render.js +2 -4
- package/dist/cjs/ssr/serverRender/utils.js +2 -12
- package/dist/esm/ssr/cli/index.js +4 -1
- package/dist/esm/ssr/serverRender/renderToString/entry.js +74 -27
- package/dist/esm/ssr/serverRender/renderToString/loadable.js +166 -53
- package/dist/esm/ssr/serverRender/renderToString/render.js +27 -8
- package/dist/esm/ssr/serverRender/utils.js +1 -14
- package/dist/esm-node/ssr/cli/index.js +4 -1
- package/dist/esm-node/ssr/serverRender/renderToString/entry.js +7 -4
- package/dist/esm-node/ssr/serverRender/renderToString/loadable.js +80 -35
- package/dist/esm-node/ssr/serverRender/renderToString/render.js +2 -4
- package/dist/esm-node/ssr/serverRender/utils.js +1 -10
- package/dist/types/ssr/serverRender/renderToString/entry.d.ts +1 -0
- package/dist/types/ssr/serverRender/renderToString/loadable.d.ts +6 -1
- package/dist/types/ssr/serverRender/renderToString/render.d.ts +2 -2
- package/dist/types/ssr/serverRender/types.d.ts +2 -0
- package/dist/types/ssr/serverRender/utils.d.ts +0 -2
- package/package.json +11 -11
|
@@ -157,6 +157,7 @@ const ssrPlugin = () => ({
|
|
|
157
157
|
var _bundlerConfigs_find_output, _bundlerConfigs_find, _config_server;
|
|
158
158
|
const chunkLoadingGlobal = bundlerConfigs === null || bundlerConfigs === void 0 ? void 0 : (_bundlerConfigs_find = bundlerConfigs.find((config2) => config2.name === "client")) === null || _bundlerConfigs_find === void 0 ? void 0 : (_bundlerConfigs_find_output = _bundlerConfigs_find.output) === null || _bundlerConfigs_find_output === void 0 ? void 0 : _bundlerConfigs_find_output.chunkLoadingGlobal;
|
|
159
159
|
const config = api.useResolvedConfigContext();
|
|
160
|
+
const { enableInlineScripts, enableInlineStyles } = config.output;
|
|
160
161
|
const { crossorigin, scriptLoading } = config.html;
|
|
161
162
|
const disablePrerender = typeof ((_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.ssr) === "object" ? Boolean(config.server.ssr.disablePrerender) : false;
|
|
162
163
|
plugins.push({
|
|
@@ -166,7 +167,9 @@ const ssrPlugin = () => ({
|
|
|
166
167
|
crossorigin,
|
|
167
168
|
scriptLoading,
|
|
168
169
|
chunkLoadingGlobal,
|
|
169
|
-
disablePrerender
|
|
170
|
+
disablePrerender,
|
|
171
|
+
enableInlineScripts: typeof enableInlineScripts === "function" ? void 0 : enableInlineScripts,
|
|
172
|
+
enableInlineStyles: typeof enableInlineStyles === "function" ? void 0 : enableInlineStyles
|
|
170
173
|
})
|
|
171
174
|
});
|
|
172
175
|
}
|
|
@@ -81,7 +81,7 @@ class Entry {
|
|
|
81
81
|
return "";
|
|
82
82
|
}
|
|
83
83
|
if (this.result.renderLevel >= import_types.RenderLevel.SERVER_PREFETCH) {
|
|
84
|
-
this.result.html = this.renderToString(context);
|
|
84
|
+
this.result.html = await this.renderToString(context);
|
|
85
85
|
}
|
|
86
86
|
if ((_ssrContext_redirection2 = ssrContext.redirection) === null || _ssrContext_redirection2 === void 0 ? void 0 : _ssrContext_redirection2.url) {
|
|
87
87
|
return "";
|
|
@@ -117,7 +117,7 @@ class Entry {
|
|
|
117
117
|
}
|
|
118
118
|
return prefetchData || {};
|
|
119
119
|
}
|
|
120
|
-
renderToString(context) {
|
|
120
|
+
async renderToString(context) {
|
|
121
121
|
let html = "";
|
|
122
122
|
const end = (0, import_time.time)();
|
|
123
123
|
const { ssrContext } = context;
|
|
@@ -127,13 +127,14 @@ class Entry {
|
|
|
127
127
|
ssr: true
|
|
128
128
|
})
|
|
129
129
|
});
|
|
130
|
-
html = (0, import_render.createRender)(App).addCollector((0, import_styledComponent.createStyledCollector)(this.result)).addCollector((0, import_loadable.createLoadableCollector)({
|
|
130
|
+
html = await (0, import_render.createRender)(App).addCollector((0, import_styledComponent.createStyledCollector)(this.result)).addCollector((0, import_loadable.createLoadableCollector)({
|
|
131
131
|
stats: ssrContext.loadableStats,
|
|
132
132
|
result: this.result,
|
|
133
133
|
entryName: this.entryName,
|
|
134
134
|
config: this.pluginConfig,
|
|
135
135
|
nonce: this.nonce,
|
|
136
|
-
template: this.template
|
|
136
|
+
template: this.template,
|
|
137
|
+
routeManifest: this.routeManifest
|
|
137
138
|
})).finish();
|
|
138
139
|
const cost = end();
|
|
139
140
|
this.tracker.trackTiming(import_tracker.SSRTimings.SSR_RENDER_HTML, cost);
|
|
@@ -168,12 +169,14 @@ class Entry {
|
|
|
168
169
|
(0, import_define_property._)(this, "pluginConfig", void 0);
|
|
169
170
|
(0, import_define_property._)(this, "htmlModifiers", void 0);
|
|
170
171
|
(0, import_define_property._)(this, "nonce", void 0);
|
|
172
|
+
(0, import_define_property._)(this, "routeManifest", void 0);
|
|
171
173
|
const { ctx, config } = options;
|
|
172
174
|
const { entryName, template, nonce } = ctx;
|
|
173
175
|
this.template = template;
|
|
174
176
|
this.entryName = entryName;
|
|
175
177
|
this.App = options.App;
|
|
176
178
|
this.pluginConfig = config;
|
|
179
|
+
this.routeManifest = ctx.routeManifest;
|
|
177
180
|
this.tracker = ctx.tracker;
|
|
178
181
|
this.metrics = ctx.metrics;
|
|
179
182
|
this.htmlModifiers = ctx.htmlModifiers;
|
|
@@ -23,14 +23,32 @@ __export(loadable_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(loadable_exports);
|
|
24
24
|
var import_define_property = require("@swc/helpers/_/_define_property");
|
|
25
25
|
var import_server = require("@loadable/server");
|
|
26
|
-
var import_utils = require("
|
|
26
|
+
var import_utils = require("@modern-js/utils");
|
|
27
|
+
var import_utils2 = require("../utils");
|
|
27
28
|
const extname = (uri) => {
|
|
28
29
|
if (typeof uri !== "string" || !uri.includes(".")) {
|
|
29
30
|
return "";
|
|
30
31
|
}
|
|
31
32
|
return `.${uri === null || uri === void 0 ? void 0 : uri.split(".").pop()}` || "";
|
|
32
33
|
};
|
|
34
|
+
const generateChunks = (chunks, ext) => chunks.filter((chunk) => Boolean(chunk.url)).filter((chunk) => extname(chunk.url).slice(1) === ext);
|
|
35
|
+
const checkIsInline = (chunk, enableInline) => {
|
|
36
|
+
if (process.env.NODE_ENV === "production") {
|
|
37
|
+
if (enableInline instanceof RegExp) {
|
|
38
|
+
return enableInline.test(chunk.url);
|
|
39
|
+
} else {
|
|
40
|
+
return Boolean(enableInline);
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
33
46
|
class LoadableCollector {
|
|
47
|
+
get existsAssets() {
|
|
48
|
+
var _routeManifest_routeAssets_entryName, _routeManifest_routeAssets;
|
|
49
|
+
const { routeManifest, entryName } = this.options;
|
|
50
|
+
return routeManifest === null || routeManifest === void 0 ? void 0 : (_routeManifest_routeAssets = routeManifest.routeAssets) === null || _routeManifest_routeAssets === void 0 ? void 0 : (_routeManifest_routeAssets_entryName = _routeManifest_routeAssets[entryName]) === null || _routeManifest_routeAssets_entryName === void 0 ? void 0 : _routeManifest_routeAssets_entryName.assets;
|
|
51
|
+
}
|
|
34
52
|
collect(comopnent) {
|
|
35
53
|
const { stats, entryName } = this.options;
|
|
36
54
|
if (!stats) {
|
|
@@ -44,54 +62,81 @@ class LoadableCollector {
|
|
|
44
62
|
});
|
|
45
63
|
return this.extractor.collectChunks(comopnent);
|
|
46
64
|
}
|
|
47
|
-
effect() {
|
|
65
|
+
async effect() {
|
|
48
66
|
if (!this.extractor) {
|
|
49
67
|
return;
|
|
50
68
|
}
|
|
51
|
-
const { result: { chunksMap }, config, template, nonce } = this.options;
|
|
52
69
|
const { extractor } = this;
|
|
53
70
|
const chunks = extractor.getChunkAssets(extractor.chunks);
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
71
|
+
const scriptChunks = generateChunks(chunks, "js");
|
|
72
|
+
const styleChunks = generateChunks(chunks, "css");
|
|
73
|
+
this.emitLoadableScripts(extractor);
|
|
74
|
+
await this.emitScriptAssets(scriptChunks);
|
|
75
|
+
await this.emitStyleAssets(styleChunks);
|
|
76
|
+
}
|
|
77
|
+
emitLoadableScripts(extractor) {
|
|
78
|
+
const check = (scripts2) => (scripts2 || "").includes("__LOADABLE_REQUIRED_CHUNKS___ext");
|
|
79
|
+
const scripts = extractor.getScriptTags();
|
|
80
|
+
if (!check(scripts)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const { result: { chunksMap } } = this.options;
|
|
84
|
+
const s = scripts.split("</script>").slice(0, 2).map((i) => `${i}</script>`).join("");
|
|
85
|
+
chunksMap.js += s;
|
|
86
|
+
}
|
|
87
|
+
async emitScriptAssets(chunks) {
|
|
88
|
+
const { template, config, nonce, result } = this.options;
|
|
89
|
+
const { chunksMap } = result;
|
|
90
|
+
const { scriptLoading = "defer", enableInlineScripts } = config;
|
|
91
|
+
const scriptLoadingAtr = {
|
|
92
|
+
defer: scriptLoading === "defer" ? true : void 0,
|
|
93
|
+
type: scriptLoading === "module" ? "module" : void 0
|
|
94
|
+
};
|
|
95
|
+
const attributes = (0, import_utils2.attributesToString)(this.generateAttributes({
|
|
96
|
+
nonce,
|
|
97
|
+
...scriptLoadingAtr
|
|
98
|
+
}));
|
|
99
|
+
const scripts = await Promise.all(chunks.filter((chunk) => {
|
|
100
|
+
var _this_existsAssets;
|
|
101
|
+
const jsChunkReg = new RegExp(`<script .*src="${chunk.url}".*>`);
|
|
102
|
+
return !jsChunkReg.test(template) && !((_this_existsAssets = this.existsAssets) === null || _this_existsAssets === void 0 ? void 0 : _this_existsAssets.includes(chunk.path));
|
|
103
|
+
}).map((chunk) => {
|
|
104
|
+
if (checkIsInline(chunk, enableInlineScripts)) {
|
|
105
|
+
const filepath = chunk.path;
|
|
106
|
+
return import_utils.fs.readFile(filepath, "utf-8").then((content) => `<script>${content}</script>`);
|
|
107
|
+
} else {
|
|
108
|
+
return `<script${attributes} src="${chunk.url}"></script>`;
|
|
59
109
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const attrsStr = (0, import_utils.attributesToString)(attributes);
|
|
76
|
-
chunksMap[fileType] += `<script${attrsStr} src="${v.url}"></script>`;
|
|
77
|
-
}
|
|
78
|
-
} else if (fileType === "css") {
|
|
79
|
-
const cssChunkReg = new RegExp(`<link .*href="${v.url}".*>`);
|
|
80
|
-
if (!cssChunkReg.test(template)) {
|
|
81
|
-
const attrsStr = (0, import_utils.attributesToString)(attributes);
|
|
82
|
-
chunksMap[fileType] += `<link${attrsStr} href="${v.url}" rel="stylesheet" />`;
|
|
83
|
-
}
|
|
110
|
+
}));
|
|
111
|
+
chunksMap.js += scripts.join("");
|
|
112
|
+
}
|
|
113
|
+
async emitStyleAssets(chunks) {
|
|
114
|
+
const { template, result: { chunksMap }, config: { enableInlineStyles } } = this.options;
|
|
115
|
+
const atrributes = (0, import_utils2.attributesToString)(this.generateAttributes());
|
|
116
|
+
const css = await Promise.all(chunks.filter((chunk) => {
|
|
117
|
+
var _this_existsAssets;
|
|
118
|
+
const cssChunkReg = new RegExp(`<link .*href="${chunk.url}".*>`);
|
|
119
|
+
return !cssChunkReg.test(template) && !((_this_existsAssets = this.existsAssets) === null || _this_existsAssets === void 0 ? void 0 : _this_existsAssets.includes(chunk.path));
|
|
120
|
+
}).map((chunk) => {
|
|
121
|
+
if (checkIsInline(chunk, enableInlineStyles)) {
|
|
122
|
+
return import_utils.fs.readFile(chunk.path).then((content) => `<style>${content}</style>`);
|
|
123
|
+
} else {
|
|
124
|
+
return `<link${atrributes} href="${chunk.url}" rel="stylesheet" />`;
|
|
84
125
|
}
|
|
85
|
-
}
|
|
126
|
+
}));
|
|
127
|
+
chunksMap.css += css.join("");
|
|
86
128
|
}
|
|
87
|
-
generateAttributes() {
|
|
129
|
+
generateAttributes(extraAtr = {}) {
|
|
88
130
|
const { config } = this.options;
|
|
89
131
|
const { crossorigin } = config;
|
|
90
132
|
const attributes = {};
|
|
91
133
|
if (crossorigin) {
|
|
92
134
|
attributes.crossorigin = crossorigin === true ? "anonymous" : crossorigin;
|
|
93
135
|
}
|
|
94
|
-
return
|
|
136
|
+
return {
|
|
137
|
+
...attributes,
|
|
138
|
+
...extraAtr
|
|
139
|
+
};
|
|
95
140
|
}
|
|
96
141
|
constructor(options) {
|
|
97
142
|
(0, import_define_property._)(this, "options", void 0);
|
|
@@ -38,12 +38,10 @@ class Render {
|
|
|
38
38
|
this.collectors.push(collector);
|
|
39
39
|
return this;
|
|
40
40
|
}
|
|
41
|
-
finish() {
|
|
41
|
+
async finish() {
|
|
42
42
|
const App = this.collectors.reduce((pre, collector) => collector.collect(pre), this.App);
|
|
43
43
|
const html = import_server.default.renderToString(App);
|
|
44
|
-
this.collectors.
|
|
45
|
-
component.effect();
|
|
46
|
-
});
|
|
44
|
+
await Promise.all(this.collectors.map((component) => component.effect()));
|
|
47
45
|
return html;
|
|
48
46
|
}
|
|
49
47
|
constructor(App) {
|
|
@@ -21,21 +21,12 @@ __export(utils_exports, {
|
|
|
21
21
|
CSS_CHUNKS_PLACEHOLDER: () => CSS_CHUNKS_PLACEHOLDER,
|
|
22
22
|
ROUTER_DATA_JSON_ID: () => ROUTER_DATA_JSON_ID,
|
|
23
23
|
SSR_DATA_JSON_ID: () => SSR_DATA_JSON_ID,
|
|
24
|
-
attributesToString: () => attributesToString
|
|
25
|
-
getLoadableScripts: () => getLoadableScripts
|
|
24
|
+
attributesToString: () => attributesToString
|
|
26
25
|
});
|
|
27
26
|
module.exports = __toCommonJS(utils_exports);
|
|
28
27
|
const CSS_CHUNKS_PLACEHOLDER = "<!--<?- chunksMap.css ?>-->";
|
|
29
28
|
const SSR_DATA_JSON_ID = "__MODERN_SSR_DATA__";
|
|
30
29
|
const ROUTER_DATA_JSON_ID = "__MODERN_ROUTER_DATA__";
|
|
31
|
-
function getLoadableScripts(extractor) {
|
|
32
|
-
const check = (scripts2) => (scripts2 || "").includes("__LOADABLE_REQUIRED_CHUNKS___ext");
|
|
33
|
-
const scripts = extractor.getScriptTags();
|
|
34
|
-
if (!check(scripts)) {
|
|
35
|
-
return "";
|
|
36
|
-
}
|
|
37
|
-
return scripts.split("</script>").slice(0, 2).map((i) => `${i}</script>`).join("");
|
|
38
|
-
}
|
|
39
30
|
function attributesToString(attributes) {
|
|
40
31
|
return Object.entries(attributes).reduce((str, [key, value]) => {
|
|
41
32
|
return value === void 0 ? str : `${str} ${key}="${value}"`;
|
|
@@ -46,6 +37,5 @@ function attributesToString(attributes) {
|
|
|
46
37
|
CSS_CHUNKS_PLACEHOLDER,
|
|
47
38
|
ROUTER_DATA_JSON_ID,
|
|
48
39
|
SSR_DATA_JSON_ID,
|
|
49
|
-
attributesToString
|
|
50
|
-
getLoadableScripts
|
|
40
|
+
attributesToString
|
|
51
41
|
});
|
|
@@ -151,6 +151,7 @@ var ssrPlugin = function() {
|
|
|
151
151
|
return config2.name === "client";
|
|
152
152
|
})) === null || _bundlerConfigs_find === void 0 ? void 0 : (_bundlerConfigs_find_output = _bundlerConfigs_find.output) === null || _bundlerConfigs_find_output === void 0 ? void 0 : _bundlerConfigs_find_output.chunkLoadingGlobal;
|
|
153
153
|
var config = api.useResolvedConfigContext();
|
|
154
|
+
var _config_output = config.output, enableInlineScripts = _config_output.enableInlineScripts, enableInlineStyles = _config_output.enableInlineStyles;
|
|
154
155
|
var _config_html = config.html, crossorigin = _config_html.crossorigin, scriptLoading = _config_html.scriptLoading;
|
|
155
156
|
var disablePrerender = typeof ((_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.ssr) === "object" ? Boolean(config.server.ssr.disablePrerender) : false;
|
|
156
157
|
plugins.push({
|
|
@@ -159,7 +160,9 @@ var ssrPlugin = function() {
|
|
|
159
160
|
crossorigin,
|
|
160
161
|
scriptLoading,
|
|
161
162
|
chunkLoadingGlobal,
|
|
162
|
-
disablePrerender
|
|
163
|
+
disablePrerender,
|
|
164
|
+
enableInlineScripts: typeof enableInlineScripts === "function" ? void 0 : enableInlineScripts,
|
|
165
|
+
enableInlineStyles: typeof enableInlineStyles === "function" ? void 0 : enableInlineStyles
|
|
163
166
|
}))
|
|
164
167
|
});
|
|
165
168
|
}
|
|
@@ -54,12 +54,14 @@ var Entry = /* @__PURE__ */ function() {
|
|
|
54
54
|
_define_property(this, "pluginConfig", void 0);
|
|
55
55
|
_define_property(this, "htmlModifiers", void 0);
|
|
56
56
|
_define_property(this, "nonce", void 0);
|
|
57
|
+
_define_property(this, "routeManifest", void 0);
|
|
57
58
|
var ctx = options.ctx, config = options.config;
|
|
58
59
|
var entryName = ctx.entryName, template = ctx.template, nonce = ctx.nonce;
|
|
59
60
|
this.template = template;
|
|
60
61
|
this.entryName = entryName;
|
|
61
62
|
this.App = options.App;
|
|
62
63
|
this.pluginConfig = config;
|
|
64
|
+
this.routeManifest = ctx.routeManifest;
|
|
63
65
|
this.tracker = ctx.tracker;
|
|
64
66
|
this.metrics = ctx.metrics;
|
|
65
67
|
this.htmlModifiers = ctx.htmlModifiers;
|
|
@@ -79,7 +81,7 @@ var Entry = /* @__PURE__ */ function() {
|
|
|
79
81
|
value: function renderToHtml(context) {
|
|
80
82
|
var _this = this;
|
|
81
83
|
return _async_to_generator(function() {
|
|
82
|
-
var _ssrContext_redirection, _ssrContext_redirection1, _ssrContext_redirection2, ssrContext, prefetchData, routerContext, routerData, templateData, ssrDataScripts, html, helmetData;
|
|
84
|
+
var _ssrContext_redirection, _ssrContext_redirection1, _ssrContext_redirection2, ssrContext, prefetchData, _, routerContext, routerData, templateData, ssrDataScripts, html, helmetData;
|
|
83
85
|
return _ts_generator(this, function(_state) {
|
|
84
86
|
switch (_state.label) {
|
|
85
87
|
case 0:
|
|
@@ -102,9 +104,20 @@ var Entry = /* @__PURE__ */ function() {
|
|
|
102
104
|
""
|
|
103
105
|
];
|
|
104
106
|
}
|
|
105
|
-
if (_this.result.renderLevel >= RenderLevel.SERVER_PREFETCH)
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
if (!(_this.result.renderLevel >= RenderLevel.SERVER_PREFETCH))
|
|
108
|
+
return [
|
|
109
|
+
3,
|
|
110
|
+
3
|
|
111
|
+
];
|
|
112
|
+
_ = _this.result;
|
|
113
|
+
return [
|
|
114
|
+
4,
|
|
115
|
+
_this.renderToString(context)
|
|
116
|
+
];
|
|
117
|
+
case 2:
|
|
118
|
+
_.html = _state.sent();
|
|
119
|
+
_state.label = 3;
|
|
120
|
+
case 3:
|
|
108
121
|
if ((_ssrContext_redirection2 = ssrContext.redirection) === null || _ssrContext_redirection2 === void 0 ? void 0 : _ssrContext_redirection2.url) {
|
|
109
122
|
return [
|
|
110
123
|
2,
|
|
@@ -186,30 +199,64 @@ var Entry = /* @__PURE__ */ function() {
|
|
|
186
199
|
{
|
|
187
200
|
key: "renderToString",
|
|
188
201
|
value: function renderToString(context) {
|
|
189
|
-
var
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
202
|
+
var _this = this;
|
|
203
|
+
return _async_to_generator(function() {
|
|
204
|
+
var html, end, ssrContext, App, cost, e;
|
|
205
|
+
return _ts_generator(this, function(_state) {
|
|
206
|
+
switch (_state.label) {
|
|
207
|
+
case 0:
|
|
208
|
+
html = "";
|
|
209
|
+
end = time();
|
|
210
|
+
ssrContext = context.ssrContext;
|
|
211
|
+
_state.label = 1;
|
|
212
|
+
case 1:
|
|
213
|
+
_state.trys.push([
|
|
214
|
+
1,
|
|
215
|
+
3,
|
|
216
|
+
,
|
|
217
|
+
4
|
|
218
|
+
]);
|
|
219
|
+
App = React.createElement(_this.App, {
|
|
220
|
+
context: Object.assign(context, {
|
|
221
|
+
ssr: true
|
|
222
|
+
})
|
|
223
|
+
});
|
|
224
|
+
return [
|
|
225
|
+
4,
|
|
226
|
+
createRender(App).addCollector(createStyledCollector(_this.result)).addCollector(createLoadableCollector({
|
|
227
|
+
stats: ssrContext.loadableStats,
|
|
228
|
+
result: _this.result,
|
|
229
|
+
entryName: _this.entryName,
|
|
230
|
+
config: _this.pluginConfig,
|
|
231
|
+
nonce: _this.nonce,
|
|
232
|
+
template: _this.template,
|
|
233
|
+
routeManifest: _this.routeManifest
|
|
234
|
+
})).finish()
|
|
235
|
+
];
|
|
236
|
+
case 2:
|
|
237
|
+
html = _state.sent();
|
|
238
|
+
cost = end();
|
|
239
|
+
_this.tracker.trackTiming(SSRTimings.SSR_RENDER_HTML, cost);
|
|
240
|
+
_this.result.renderLevel = RenderLevel.SERVER_RENDER;
|
|
241
|
+
return [
|
|
242
|
+
3,
|
|
243
|
+
4
|
|
244
|
+
];
|
|
245
|
+
case 3:
|
|
246
|
+
e = _state.sent();
|
|
247
|
+
_this.tracker.trackError(SSRErrors.RENDER_HTML, e);
|
|
248
|
+
return [
|
|
249
|
+
3,
|
|
250
|
+
4
|
|
251
|
+
];
|
|
252
|
+
case 4:
|
|
253
|
+
return [
|
|
254
|
+
2,
|
|
255
|
+
html
|
|
256
|
+
];
|
|
257
|
+
}
|
|
197
258
|
});
|
|
198
|
-
|
|
199
|
-
stats: ssrContext.loadableStats,
|
|
200
|
-
result: this.result,
|
|
201
|
-
entryName: this.entryName,
|
|
202
|
-
config: this.pluginConfig,
|
|
203
|
-
nonce: this.nonce,
|
|
204
|
-
template: this.template
|
|
205
|
-
})).finish();
|
|
206
|
-
var cost = end();
|
|
207
|
-
this.tracker.trackTiming(SSRTimings.SSR_RENDER_HTML, cost);
|
|
208
|
-
this.result.renderLevel = RenderLevel.SERVER_RENDER;
|
|
209
|
-
} catch (e) {
|
|
210
|
-
this.tracker.trackError(SSRErrors.RENDER_HTML, e);
|
|
211
|
-
}
|
|
212
|
-
return html;
|
|
259
|
+
})();
|
|
213
260
|
}
|
|
214
261
|
},
|
|
215
262
|
{
|
|
@@ -1,14 +1,37 @@
|
|
|
1
|
+
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
|
|
1
2
|
import { _ as _class_call_check } from "@swc/helpers/_/_class_call_check";
|
|
2
3
|
import { _ as _create_class } from "@swc/helpers/_/_create_class";
|
|
3
4
|
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
5
|
+
import { _ as _instanceof } from "@swc/helpers/_/_instanceof";
|
|
6
|
+
import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
|
|
7
|
+
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
|
|
4
8
|
import { ChunkExtractor } from "@loadable/server";
|
|
5
|
-
import {
|
|
9
|
+
import { fs } from "@modern-js/utils";
|
|
10
|
+
import { attributesToString } from "../utils";
|
|
6
11
|
var extname = function(uri) {
|
|
7
12
|
if (typeof uri !== "string" || !uri.includes(".")) {
|
|
8
13
|
return "";
|
|
9
14
|
}
|
|
10
15
|
return ".".concat(uri === null || uri === void 0 ? void 0 : uri.split(".").pop()) || "";
|
|
11
16
|
};
|
|
17
|
+
var generateChunks = function(chunks, ext) {
|
|
18
|
+
return chunks.filter(function(chunk) {
|
|
19
|
+
return Boolean(chunk.url);
|
|
20
|
+
}).filter(function(chunk) {
|
|
21
|
+
return extname(chunk.url).slice(1) === ext;
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
var checkIsInline = function(chunk, enableInline) {
|
|
25
|
+
if (process.env.NODE_ENV === "production") {
|
|
26
|
+
if (_instanceof(enableInline, RegExp)) {
|
|
27
|
+
return enableInline.test(chunk.url);
|
|
28
|
+
} else {
|
|
29
|
+
return Boolean(enableInline);
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
12
35
|
var LoadableCollector = /* @__PURE__ */ function() {
|
|
13
36
|
"use strict";
|
|
14
37
|
function LoadableCollector2(options) {
|
|
@@ -18,6 +41,14 @@ var LoadableCollector = /* @__PURE__ */ function() {
|
|
|
18
41
|
this.options = options;
|
|
19
42
|
}
|
|
20
43
|
_create_class(LoadableCollector2, [
|
|
44
|
+
{
|
|
45
|
+
key: "existsAssets",
|
|
46
|
+
get: function get() {
|
|
47
|
+
var _routeManifest_routeAssets_entryName, _routeManifest_routeAssets;
|
|
48
|
+
var _this_options = this.options, routeManifest = _this_options.routeManifest, entryName = _this_options.entryName;
|
|
49
|
+
return routeManifest === null || routeManifest === void 0 ? void 0 : (_routeManifest_routeAssets = routeManifest.routeAssets) === null || _routeManifest_routeAssets === void 0 ? void 0 : (_routeManifest_routeAssets_entryName = _routeManifest_routeAssets[entryName]) === null || _routeManifest_routeAssets_entryName === void 0 ? void 0 : _routeManifest_routeAssets_entryName.assets;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
21
52
|
{
|
|
22
53
|
key: "collect",
|
|
23
54
|
value: function collect(comopnent) {
|
|
@@ -37,73 +68,155 @@ var LoadableCollector = /* @__PURE__ */ function() {
|
|
|
37
68
|
{
|
|
38
69
|
key: "effect",
|
|
39
70
|
value: function effect() {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
for (var _iterator = chunks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
51
|
-
var v = _step.value;
|
|
52
|
-
if (!v.url) {
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
var fileType = extname(v.url).slice(1);
|
|
56
|
-
if (fileType === "js") {
|
|
57
|
-
var jsChunkReg = new RegExp('<script .*src="'.concat(v.url, '".*>'));
|
|
58
|
-
if (!jsChunkReg.test(template)) {
|
|
59
|
-
var _config_scriptLoading = config.scriptLoading, scriptLoading = _config_scriptLoading === void 0 ? "defer" : _config_scriptLoading;
|
|
60
|
-
switch (scriptLoading) {
|
|
61
|
-
case "defer":
|
|
62
|
-
attributes.defer = true;
|
|
63
|
-
break;
|
|
64
|
-
case "module":
|
|
65
|
-
attributes.type = "module";
|
|
66
|
-
break;
|
|
67
|
-
default:
|
|
71
|
+
var _this = this;
|
|
72
|
+
return _async_to_generator(function() {
|
|
73
|
+
var extractor, chunks, scriptChunks, styleChunks;
|
|
74
|
+
return _ts_generator(this, function(_state) {
|
|
75
|
+
switch (_state.label) {
|
|
76
|
+
case 0:
|
|
77
|
+
if (!_this.extractor) {
|
|
78
|
+
return [
|
|
79
|
+
2
|
|
80
|
+
];
|
|
68
81
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
82
|
+
extractor = _this.extractor;
|
|
83
|
+
chunks = extractor.getChunkAssets(extractor.chunks);
|
|
84
|
+
scriptChunks = generateChunks(chunks, "js");
|
|
85
|
+
styleChunks = generateChunks(chunks, "css");
|
|
86
|
+
_this.emitLoadableScripts(extractor);
|
|
87
|
+
return [
|
|
88
|
+
4,
|
|
89
|
+
_this.emitScriptAssets(scriptChunks)
|
|
90
|
+
];
|
|
91
|
+
case 1:
|
|
92
|
+
_state.sent();
|
|
93
|
+
return [
|
|
94
|
+
4,
|
|
95
|
+
_this.emitStyleAssets(styleChunks)
|
|
96
|
+
];
|
|
97
|
+
case 2:
|
|
98
|
+
_state.sent();
|
|
99
|
+
return [
|
|
100
|
+
2
|
|
101
|
+
];
|
|
79
102
|
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
103
|
+
});
|
|
104
|
+
})();
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
key: "emitLoadableScripts",
|
|
109
|
+
value: function emitLoadableScripts(extractor) {
|
|
110
|
+
var check = function(scripts2) {
|
|
111
|
+
return (scripts2 || "").includes("__LOADABLE_REQUIRED_CHUNKS___ext");
|
|
112
|
+
};
|
|
113
|
+
var scripts = extractor.getScriptTags();
|
|
114
|
+
if (!check(scripts)) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
var _this_options = this.options, chunksMap = _this_options.result.chunksMap;
|
|
118
|
+
var s = scripts.split("</script>").slice(0, 2).map(function(i) {
|
|
119
|
+
return "".concat(i, "</script>");
|
|
120
|
+
}).join("");
|
|
121
|
+
chunksMap.js += s;
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
key: "emitScriptAssets",
|
|
126
|
+
value: function emitScriptAssets(chunks) {
|
|
127
|
+
var _this = this;
|
|
128
|
+
return _async_to_generator(function() {
|
|
129
|
+
var _this_options, template, config, nonce, result, chunksMap, _config_scriptLoading, scriptLoading, enableInlineScripts, scriptLoadingAtr, attributes, scripts;
|
|
130
|
+
return _ts_generator(this, function(_state) {
|
|
131
|
+
switch (_state.label) {
|
|
132
|
+
case 0:
|
|
133
|
+
_this_options = _this.options, template = _this_options.template, config = _this_options.config, nonce = _this_options.nonce, result = _this_options.result;
|
|
134
|
+
chunksMap = result.chunksMap;
|
|
135
|
+
_config_scriptLoading = config.scriptLoading, scriptLoading = _config_scriptLoading === void 0 ? "defer" : _config_scriptLoading, enableInlineScripts = config.enableInlineScripts;
|
|
136
|
+
scriptLoadingAtr = {
|
|
137
|
+
defer: scriptLoading === "defer" ? true : void 0,
|
|
138
|
+
type: scriptLoading === "module" ? "module" : void 0
|
|
139
|
+
};
|
|
140
|
+
attributes = attributesToString(_this.generateAttributes(_object_spread({
|
|
141
|
+
nonce
|
|
142
|
+
}, scriptLoadingAtr)));
|
|
143
|
+
return [
|
|
144
|
+
4,
|
|
145
|
+
Promise.all(chunks.filter(function(chunk) {
|
|
146
|
+
var _this_existsAssets;
|
|
147
|
+
var jsChunkReg = new RegExp('<script .*src="'.concat(chunk.url, '".*>'));
|
|
148
|
+
return !jsChunkReg.test(template) && !((_this_existsAssets = _this.existsAssets) === null || _this_existsAssets === void 0 ? void 0 : _this_existsAssets.includes(chunk.path));
|
|
149
|
+
}).map(function(chunk) {
|
|
150
|
+
if (checkIsInline(chunk, enableInlineScripts)) {
|
|
151
|
+
var filepath = chunk.path;
|
|
152
|
+
return fs.readFile(filepath, "utf-8").then(function(content) {
|
|
153
|
+
return "<script>".concat(content, "</script>");
|
|
154
|
+
});
|
|
155
|
+
} else {
|
|
156
|
+
return "<script".concat(attributes, ' src="').concat(chunk.url, '"></script>');
|
|
157
|
+
}
|
|
158
|
+
}))
|
|
159
|
+
];
|
|
160
|
+
case 1:
|
|
161
|
+
scripts = _state.sent();
|
|
162
|
+
chunksMap.js += scripts.join("");
|
|
163
|
+
return [
|
|
164
|
+
2
|
|
165
|
+
];
|
|
88
166
|
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
167
|
+
});
|
|
168
|
+
})();
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
key: "emitStyleAssets",
|
|
173
|
+
value: function emitStyleAssets(chunks) {
|
|
174
|
+
var _this = this;
|
|
175
|
+
return _async_to_generator(function() {
|
|
176
|
+
var _this_options, template, chunksMap, enableInlineStyles, atrributes, css;
|
|
177
|
+
return _ts_generator(this, function(_state) {
|
|
178
|
+
switch (_state.label) {
|
|
179
|
+
case 0:
|
|
180
|
+
_this_options = _this.options, template = _this_options.template, chunksMap = _this_options.result.chunksMap, enableInlineStyles = _this_options.config.enableInlineStyles;
|
|
181
|
+
atrributes = attributesToString(_this.generateAttributes());
|
|
182
|
+
return [
|
|
183
|
+
4,
|
|
184
|
+
Promise.all(chunks.filter(function(chunk) {
|
|
185
|
+
var _this_existsAssets;
|
|
186
|
+
var cssChunkReg = new RegExp('<link .*href="'.concat(chunk.url, '".*>'));
|
|
187
|
+
return !cssChunkReg.test(template) && !((_this_existsAssets = _this.existsAssets) === null || _this_existsAssets === void 0 ? void 0 : _this_existsAssets.includes(chunk.path));
|
|
188
|
+
}).map(function(chunk) {
|
|
189
|
+
if (checkIsInline(chunk, enableInlineStyles)) {
|
|
190
|
+
return fs.readFile(chunk.path).then(function(content) {
|
|
191
|
+
return "<style>".concat(content, "</style>");
|
|
192
|
+
});
|
|
193
|
+
} else {
|
|
194
|
+
return "<link".concat(atrributes, ' href="').concat(chunk.url, '" rel="stylesheet" />');
|
|
195
|
+
}
|
|
196
|
+
}))
|
|
197
|
+
];
|
|
198
|
+
case 1:
|
|
199
|
+
css = _state.sent();
|
|
200
|
+
chunksMap.css += css.join("");
|
|
201
|
+
return [
|
|
202
|
+
2
|
|
203
|
+
];
|
|
92
204
|
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
205
|
+
});
|
|
206
|
+
})();
|
|
95
207
|
}
|
|
96
208
|
},
|
|
97
209
|
{
|
|
98
210
|
key: "generateAttributes",
|
|
99
211
|
value: function generateAttributes() {
|
|
212
|
+
var extraAtr = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
100
213
|
var config = this.options.config;
|
|
101
214
|
var crossorigin = config.crossorigin;
|
|
102
215
|
var attributes = {};
|
|
103
216
|
if (crossorigin) {
|
|
104
217
|
attributes.crossorigin = crossorigin === true ? "anonymous" : crossorigin;
|
|
105
218
|
}
|
|
106
|
-
return attributes;
|
|
219
|
+
return _object_spread({}, attributes, extraAtr);
|
|
107
220
|
}
|
|
108
221
|
}
|
|
109
222
|
]);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
|
|
1
2
|
import { _ as _class_call_check } from "@swc/helpers/_/_class_call_check";
|
|
2
3
|
import { _ as _create_class } from "@swc/helpers/_/_create_class";
|
|
3
4
|
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
5
|
+
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
|
|
4
6
|
import ReactDomServer from "react-dom/server";
|
|
5
7
|
var Render = /* @__PURE__ */ function() {
|
|
6
8
|
"use strict";
|
|
@@ -21,14 +23,31 @@ var Render = /* @__PURE__ */ function() {
|
|
|
21
23
|
{
|
|
22
24
|
key: "finish",
|
|
23
25
|
value: function finish() {
|
|
24
|
-
var
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
var _this = this;
|
|
27
|
+
return _async_to_generator(function() {
|
|
28
|
+
var App, html;
|
|
29
|
+
return _ts_generator(this, function(_state) {
|
|
30
|
+
switch (_state.label) {
|
|
31
|
+
case 0:
|
|
32
|
+
App = _this.collectors.reduce(function(pre, collector) {
|
|
33
|
+
return collector.collect(pre);
|
|
34
|
+
}, _this.App);
|
|
35
|
+
html = ReactDomServer.renderToString(App);
|
|
36
|
+
return [
|
|
37
|
+
4,
|
|
38
|
+
Promise.all(_this.collectors.map(function(component) {
|
|
39
|
+
return component.effect();
|
|
40
|
+
}))
|
|
41
|
+
];
|
|
42
|
+
case 1:
|
|
43
|
+
_state.sent();
|
|
44
|
+
return [
|
|
45
|
+
2,
|
|
46
|
+
html
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
})();
|
|
32
51
|
}
|
|
33
52
|
}
|
|
34
53
|
]);
|
|
@@ -2,18 +2,6 @@ import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
|
|
|
2
2
|
var CSS_CHUNKS_PLACEHOLDER = "<!--<?- chunksMap.css ?>-->";
|
|
3
3
|
var SSR_DATA_JSON_ID = "__MODERN_SSR_DATA__";
|
|
4
4
|
var ROUTER_DATA_JSON_ID = "__MODERN_ROUTER_DATA__";
|
|
5
|
-
function getLoadableScripts(extractor) {
|
|
6
|
-
var check = function(scripts2) {
|
|
7
|
-
return (scripts2 || "").includes("__LOADABLE_REQUIRED_CHUNKS___ext");
|
|
8
|
-
};
|
|
9
|
-
var scripts = extractor.getScriptTags();
|
|
10
|
-
if (!check(scripts)) {
|
|
11
|
-
return "";
|
|
12
|
-
}
|
|
13
|
-
return scripts.split("</script>").slice(0, 2).map(function(i) {
|
|
14
|
-
return "".concat(i, "</script>");
|
|
15
|
-
}).join("");
|
|
16
|
-
}
|
|
17
5
|
function attributesToString(attributes) {
|
|
18
6
|
return Object.entries(attributes).reduce(function(str, param) {
|
|
19
7
|
var _param = _sliced_to_array(param, 2), key = _param[0], value = _param[1];
|
|
@@ -24,6 +12,5 @@ export {
|
|
|
24
12
|
CSS_CHUNKS_PLACEHOLDER,
|
|
25
13
|
ROUTER_DATA_JSON_ID,
|
|
26
14
|
SSR_DATA_JSON_ID,
|
|
27
|
-
attributesToString
|
|
28
|
-
getLoadableScripts
|
|
15
|
+
attributesToString
|
|
29
16
|
};
|
|
@@ -123,6 +123,7 @@ const ssrPlugin = () => ({
|
|
|
123
123
|
var _bundlerConfigs_find_output, _bundlerConfigs_find, _config_server;
|
|
124
124
|
const chunkLoadingGlobal = bundlerConfigs === null || bundlerConfigs === void 0 ? void 0 : (_bundlerConfigs_find = bundlerConfigs.find((config2) => config2.name === "client")) === null || _bundlerConfigs_find === void 0 ? void 0 : (_bundlerConfigs_find_output = _bundlerConfigs_find.output) === null || _bundlerConfigs_find_output === void 0 ? void 0 : _bundlerConfigs_find_output.chunkLoadingGlobal;
|
|
125
125
|
const config = api.useResolvedConfigContext();
|
|
126
|
+
const { enableInlineScripts, enableInlineStyles } = config.output;
|
|
126
127
|
const { crossorigin, scriptLoading } = config.html;
|
|
127
128
|
const disablePrerender = typeof ((_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.ssr) === "object" ? Boolean(config.server.ssr.disablePrerender) : false;
|
|
128
129
|
plugins.push({
|
|
@@ -132,7 +133,9 @@ const ssrPlugin = () => ({
|
|
|
132
133
|
crossorigin,
|
|
133
134
|
scriptLoading,
|
|
134
135
|
chunkLoadingGlobal,
|
|
135
|
-
disablePrerender
|
|
136
|
+
disablePrerender,
|
|
137
|
+
enableInlineScripts: typeof enableInlineScripts === "function" ? void 0 : enableInlineScripts,
|
|
138
|
+
enableInlineStyles: typeof enableInlineStyles === "function" ? void 0 : enableInlineStyles
|
|
136
139
|
})
|
|
137
140
|
});
|
|
138
141
|
}
|
|
@@ -48,7 +48,7 @@ class Entry {
|
|
|
48
48
|
return "";
|
|
49
49
|
}
|
|
50
50
|
if (this.result.renderLevel >= RenderLevel.SERVER_PREFETCH) {
|
|
51
|
-
this.result.html = this.renderToString(context);
|
|
51
|
+
this.result.html = await this.renderToString(context);
|
|
52
52
|
}
|
|
53
53
|
if ((_ssrContext_redirection2 = ssrContext.redirection) === null || _ssrContext_redirection2 === void 0 ? void 0 : _ssrContext_redirection2.url) {
|
|
54
54
|
return "";
|
|
@@ -84,7 +84,7 @@ class Entry {
|
|
|
84
84
|
}
|
|
85
85
|
return prefetchData || {};
|
|
86
86
|
}
|
|
87
|
-
renderToString(context) {
|
|
87
|
+
async renderToString(context) {
|
|
88
88
|
let html = "";
|
|
89
89
|
const end = time();
|
|
90
90
|
const { ssrContext } = context;
|
|
@@ -94,13 +94,14 @@ class Entry {
|
|
|
94
94
|
ssr: true
|
|
95
95
|
})
|
|
96
96
|
});
|
|
97
|
-
html = createRender(App).addCollector(createStyledCollector(this.result)).addCollector(createLoadableCollector({
|
|
97
|
+
html = await createRender(App).addCollector(createStyledCollector(this.result)).addCollector(createLoadableCollector({
|
|
98
98
|
stats: ssrContext.loadableStats,
|
|
99
99
|
result: this.result,
|
|
100
100
|
entryName: this.entryName,
|
|
101
101
|
config: this.pluginConfig,
|
|
102
102
|
nonce: this.nonce,
|
|
103
|
-
template: this.template
|
|
103
|
+
template: this.template,
|
|
104
|
+
routeManifest: this.routeManifest
|
|
104
105
|
})).finish();
|
|
105
106
|
const cost = end();
|
|
106
107
|
this.tracker.trackTiming(SSRTimings.SSR_RENDER_HTML, cost);
|
|
@@ -135,12 +136,14 @@ class Entry {
|
|
|
135
136
|
_define_property(this, "pluginConfig", void 0);
|
|
136
137
|
_define_property(this, "htmlModifiers", void 0);
|
|
137
138
|
_define_property(this, "nonce", void 0);
|
|
139
|
+
_define_property(this, "routeManifest", void 0);
|
|
138
140
|
const { ctx, config } = options;
|
|
139
141
|
const { entryName, template, nonce } = ctx;
|
|
140
142
|
this.template = template;
|
|
141
143
|
this.entryName = entryName;
|
|
142
144
|
this.App = options.App;
|
|
143
145
|
this.pluginConfig = config;
|
|
146
|
+
this.routeManifest = ctx.routeManifest;
|
|
144
147
|
this.tracker = ctx.tracker;
|
|
145
148
|
this.metrics = ctx.metrics;
|
|
146
149
|
this.htmlModifiers = ctx.htmlModifiers;
|
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
2
2
|
import { ChunkExtractor } from "@loadable/server";
|
|
3
|
-
import {
|
|
3
|
+
import { fs } from "@modern-js/utils";
|
|
4
|
+
import { attributesToString } from "../utils";
|
|
4
5
|
const extname = (uri) => {
|
|
5
6
|
if (typeof uri !== "string" || !uri.includes(".")) {
|
|
6
7
|
return "";
|
|
7
8
|
}
|
|
8
9
|
return `.${uri === null || uri === void 0 ? void 0 : uri.split(".").pop()}` || "";
|
|
9
10
|
};
|
|
11
|
+
const generateChunks = (chunks, ext) => chunks.filter((chunk) => Boolean(chunk.url)).filter((chunk) => extname(chunk.url).slice(1) === ext);
|
|
12
|
+
const checkIsInline = (chunk, enableInline) => {
|
|
13
|
+
if (process.env.NODE_ENV === "production") {
|
|
14
|
+
if (enableInline instanceof RegExp) {
|
|
15
|
+
return enableInline.test(chunk.url);
|
|
16
|
+
} else {
|
|
17
|
+
return Boolean(enableInline);
|
|
18
|
+
}
|
|
19
|
+
} else {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
10
23
|
class LoadableCollector {
|
|
24
|
+
get existsAssets() {
|
|
25
|
+
var _routeManifest_routeAssets_entryName, _routeManifest_routeAssets;
|
|
26
|
+
const { routeManifest, entryName } = this.options;
|
|
27
|
+
return routeManifest === null || routeManifest === void 0 ? void 0 : (_routeManifest_routeAssets = routeManifest.routeAssets) === null || _routeManifest_routeAssets === void 0 ? void 0 : (_routeManifest_routeAssets_entryName = _routeManifest_routeAssets[entryName]) === null || _routeManifest_routeAssets_entryName === void 0 ? void 0 : _routeManifest_routeAssets_entryName.assets;
|
|
28
|
+
}
|
|
11
29
|
collect(comopnent) {
|
|
12
30
|
const { stats, entryName } = this.options;
|
|
13
31
|
if (!stats) {
|
|
@@ -21,54 +39,81 @@ class LoadableCollector {
|
|
|
21
39
|
});
|
|
22
40
|
return this.extractor.collectChunks(comopnent);
|
|
23
41
|
}
|
|
24
|
-
effect() {
|
|
42
|
+
async effect() {
|
|
25
43
|
if (!this.extractor) {
|
|
26
44
|
return;
|
|
27
45
|
}
|
|
28
|
-
const { result: { chunksMap }, config, template, nonce } = this.options;
|
|
29
46
|
const { extractor } = this;
|
|
30
47
|
const chunks = extractor.getChunkAssets(extractor.chunks);
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
48
|
+
const scriptChunks = generateChunks(chunks, "js");
|
|
49
|
+
const styleChunks = generateChunks(chunks, "css");
|
|
50
|
+
this.emitLoadableScripts(extractor);
|
|
51
|
+
await this.emitScriptAssets(scriptChunks);
|
|
52
|
+
await this.emitStyleAssets(styleChunks);
|
|
53
|
+
}
|
|
54
|
+
emitLoadableScripts(extractor) {
|
|
55
|
+
const check = (scripts2) => (scripts2 || "").includes("__LOADABLE_REQUIRED_CHUNKS___ext");
|
|
56
|
+
const scripts = extractor.getScriptTags();
|
|
57
|
+
if (!check(scripts)) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const { result: { chunksMap } } = this.options;
|
|
61
|
+
const s = scripts.split("</script>").slice(0, 2).map((i) => `${i}</script>`).join("");
|
|
62
|
+
chunksMap.js += s;
|
|
63
|
+
}
|
|
64
|
+
async emitScriptAssets(chunks) {
|
|
65
|
+
const { template, config, nonce, result } = this.options;
|
|
66
|
+
const { chunksMap } = result;
|
|
67
|
+
const { scriptLoading = "defer", enableInlineScripts } = config;
|
|
68
|
+
const scriptLoadingAtr = {
|
|
69
|
+
defer: scriptLoading === "defer" ? true : void 0,
|
|
70
|
+
type: scriptLoading === "module" ? "module" : void 0
|
|
71
|
+
};
|
|
72
|
+
const attributes = attributesToString(this.generateAttributes({
|
|
73
|
+
nonce,
|
|
74
|
+
...scriptLoadingAtr
|
|
75
|
+
}));
|
|
76
|
+
const scripts = await Promise.all(chunks.filter((chunk) => {
|
|
77
|
+
var _this_existsAssets;
|
|
78
|
+
const jsChunkReg = new RegExp(`<script .*src="${chunk.url}".*>`);
|
|
79
|
+
return !jsChunkReg.test(template) && !((_this_existsAssets = this.existsAssets) === null || _this_existsAssets === void 0 ? void 0 : _this_existsAssets.includes(chunk.path));
|
|
80
|
+
}).map((chunk) => {
|
|
81
|
+
if (checkIsInline(chunk, enableInlineScripts)) {
|
|
82
|
+
const filepath = chunk.path;
|
|
83
|
+
return fs.readFile(filepath, "utf-8").then((content) => `<script>${content}</script>`);
|
|
84
|
+
} else {
|
|
85
|
+
return `<script${attributes} src="${chunk.url}"></script>`;
|
|
36
86
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const attrsStr = attributesToString(attributes);
|
|
53
|
-
chunksMap[fileType] += `<script${attrsStr} src="${v.url}"></script>`;
|
|
54
|
-
}
|
|
55
|
-
} else if (fileType === "css") {
|
|
56
|
-
const cssChunkReg = new RegExp(`<link .*href="${v.url}".*>`);
|
|
57
|
-
if (!cssChunkReg.test(template)) {
|
|
58
|
-
const attrsStr = attributesToString(attributes);
|
|
59
|
-
chunksMap[fileType] += `<link${attrsStr} href="${v.url}" rel="stylesheet" />`;
|
|
60
|
-
}
|
|
87
|
+
}));
|
|
88
|
+
chunksMap.js += scripts.join("");
|
|
89
|
+
}
|
|
90
|
+
async emitStyleAssets(chunks) {
|
|
91
|
+
const { template, result: { chunksMap }, config: { enableInlineStyles } } = this.options;
|
|
92
|
+
const atrributes = attributesToString(this.generateAttributes());
|
|
93
|
+
const css = await Promise.all(chunks.filter((chunk) => {
|
|
94
|
+
var _this_existsAssets;
|
|
95
|
+
const cssChunkReg = new RegExp(`<link .*href="${chunk.url}".*>`);
|
|
96
|
+
return !cssChunkReg.test(template) && !((_this_existsAssets = this.existsAssets) === null || _this_existsAssets === void 0 ? void 0 : _this_existsAssets.includes(chunk.path));
|
|
97
|
+
}).map((chunk) => {
|
|
98
|
+
if (checkIsInline(chunk, enableInlineStyles)) {
|
|
99
|
+
return fs.readFile(chunk.path).then((content) => `<style>${content}</style>`);
|
|
100
|
+
} else {
|
|
101
|
+
return `<link${atrributes} href="${chunk.url}" rel="stylesheet" />`;
|
|
61
102
|
}
|
|
62
|
-
}
|
|
103
|
+
}));
|
|
104
|
+
chunksMap.css += css.join("");
|
|
63
105
|
}
|
|
64
|
-
generateAttributes() {
|
|
106
|
+
generateAttributes(extraAtr = {}) {
|
|
65
107
|
const { config } = this.options;
|
|
66
108
|
const { crossorigin } = config;
|
|
67
109
|
const attributes = {};
|
|
68
110
|
if (crossorigin) {
|
|
69
111
|
attributes.crossorigin = crossorigin === true ? "anonymous" : crossorigin;
|
|
70
112
|
}
|
|
71
|
-
return
|
|
113
|
+
return {
|
|
114
|
+
...attributes,
|
|
115
|
+
...extraAtr
|
|
116
|
+
};
|
|
72
117
|
}
|
|
73
118
|
constructor(options) {
|
|
74
119
|
_define_property(this, "options", void 0);
|
|
@@ -5,12 +5,10 @@ class Render {
|
|
|
5
5
|
this.collectors.push(collector);
|
|
6
6
|
return this;
|
|
7
7
|
}
|
|
8
|
-
finish() {
|
|
8
|
+
async finish() {
|
|
9
9
|
const App = this.collectors.reduce((pre, collector) => collector.collect(pre), this.App);
|
|
10
10
|
const html = ReactDomServer.renderToString(App);
|
|
11
|
-
this.collectors.
|
|
12
|
-
component.effect();
|
|
13
|
-
});
|
|
11
|
+
await Promise.all(this.collectors.map((component) => component.effect()));
|
|
14
12
|
return html;
|
|
15
13
|
}
|
|
16
14
|
constructor(App) {
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
const CSS_CHUNKS_PLACEHOLDER = "<!--<?- chunksMap.css ?>-->";
|
|
2
2
|
const SSR_DATA_JSON_ID = "__MODERN_SSR_DATA__";
|
|
3
3
|
const ROUTER_DATA_JSON_ID = "__MODERN_ROUTER_DATA__";
|
|
4
|
-
function getLoadableScripts(extractor) {
|
|
5
|
-
const check = (scripts2) => (scripts2 || "").includes("__LOADABLE_REQUIRED_CHUNKS___ext");
|
|
6
|
-
const scripts = extractor.getScriptTags();
|
|
7
|
-
if (!check(scripts)) {
|
|
8
|
-
return "";
|
|
9
|
-
}
|
|
10
|
-
return scripts.split("</script>").slice(0, 2).map((i) => `${i}</script>`).join("");
|
|
11
|
-
}
|
|
12
4
|
function attributesToString(attributes) {
|
|
13
5
|
return Object.entries(attributes).reduce((str, [key, value]) => {
|
|
14
6
|
return value === void 0 ? str : `${str} ${key}="${value}"`;
|
|
@@ -18,6 +10,5 @@ export {
|
|
|
18
10
|
CSS_CHUNKS_PLACEHOLDER,
|
|
19
11
|
ROUTER_DATA_JSON_ID,
|
|
20
12
|
SSR_DATA_JSON_ID,
|
|
21
|
-
attributesToString
|
|
22
|
-
getLoadableScripts
|
|
13
|
+
attributesToString
|
|
23
14
|
};
|
|
@@ -16,6 +16,7 @@ export default class Entry {
|
|
|
16
16
|
private readonly pluginConfig;
|
|
17
17
|
private readonly htmlModifiers;
|
|
18
18
|
private readonly nonce?;
|
|
19
|
+
private readonly routeManifest?;
|
|
19
20
|
constructor(options: EntryOptions);
|
|
20
21
|
renderToHtml(context: RuntimeContext): Promise<string>;
|
|
21
22
|
private prefetch;
|
|
@@ -6,13 +6,18 @@ declare class LoadableCollector implements Collector {
|
|
|
6
6
|
private options;
|
|
7
7
|
private extractor?;
|
|
8
8
|
constructor(options: LoadableCollectorOptions);
|
|
9
|
+
private get existsAssets();
|
|
9
10
|
collect(comopnent: ReactElement): ReactElement;
|
|
10
|
-
effect(): void
|
|
11
|
+
effect(): Promise<void>;
|
|
12
|
+
private emitLoadableScripts;
|
|
13
|
+
private emitScriptAssets;
|
|
14
|
+
private emitStyleAssets;
|
|
11
15
|
private generateAttributes;
|
|
12
16
|
}
|
|
13
17
|
export interface LoadableCollectorOptions {
|
|
14
18
|
nonce?: string;
|
|
15
19
|
stats?: Record<string, any>;
|
|
20
|
+
routeManifest?: Record<string, any>;
|
|
16
21
|
template: string;
|
|
17
22
|
config: SSRPluginConfig;
|
|
18
23
|
entryName: string;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import type { ReactElement } from 'react';
|
|
2
2
|
export interface Collector {
|
|
3
3
|
collect: (comopnent: ReactElement) => ReactElement;
|
|
4
|
-
effect: () => void
|
|
4
|
+
effect: () => void | Promise<void>;
|
|
5
5
|
}
|
|
6
6
|
declare class Render {
|
|
7
7
|
private App;
|
|
8
8
|
private collectors;
|
|
9
9
|
constructor(App: ReactElement);
|
|
10
10
|
addCollector(collector: Collector): this;
|
|
11
|
-
finish(): string
|
|
11
|
+
finish(): Promise<string>;
|
|
12
12
|
}
|
|
13
13
|
export declare function createRender(App: ReactElement): Render;
|
|
14
14
|
export {};
|
|
@@ -19,6 +19,8 @@ export { RuntimeContext, RenderLevel };
|
|
|
19
19
|
export type SSRPluginConfig = {
|
|
20
20
|
crossorigin?: boolean | 'anonymous' | 'use-credentials';
|
|
21
21
|
scriptLoading?: 'defer' | 'blocking' | 'module';
|
|
22
|
+
enableInlineStyles?: boolean | RegExp;
|
|
23
|
+
enableInlineScripts?: boolean | RegExp;
|
|
22
24
|
disablePrerender?: boolean;
|
|
23
25
|
chunkLoadingGlobal?: string;
|
|
24
26
|
} & Exclude<ServerUserConfig['ssr'], boolean>;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type { ChunkExtractor } from '@loadable/server';
|
|
2
1
|
export declare const CSS_CHUNKS_PLACEHOLDER = "<!--<?- chunksMap.css ?>-->";
|
|
3
2
|
export declare const SSR_DATA_JSON_ID = "__MODERN_SSR_DATA__";
|
|
4
3
|
export declare const ROUTER_DATA_JSON_ID = "__MODERN_ROUTER_DATA__";
|
|
5
|
-
export declare function getLoadableScripts(extractor: ChunkExtractor): string;
|
|
6
4
|
export declare function attributesToString(attributes: Record<string, any>): string;
|
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"modern",
|
|
16
16
|
"modern.js"
|
|
17
17
|
],
|
|
18
|
-
"version": "2.
|
|
18
|
+
"version": "2.38.0",
|
|
19
19
|
"engines": {
|
|
20
20
|
"node": ">=14.17.6"
|
|
21
21
|
},
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
}
|
|
147
147
|
},
|
|
148
148
|
"dependencies": {
|
|
149
|
-
"@babel/core": "^7.
|
|
149
|
+
"@babel/core": "^7.23.2",
|
|
150
150
|
"@babel/types": "^7.22.15",
|
|
151
151
|
"cookie": "0.5.0",
|
|
152
152
|
"@loadable/babel-plugin": "5.15.3",
|
|
@@ -171,10 +171,10 @@
|
|
|
171
171
|
"react-side-effect": "^2.1.1",
|
|
172
172
|
"styled-components": "^5.3.1",
|
|
173
173
|
"@swc/helpers": "0.5.1",
|
|
174
|
-
"@modern-js/plugin": "2.
|
|
175
|
-
"@modern-js/
|
|
176
|
-
"@modern-js/
|
|
177
|
-
"@modern-js/runtime-utils": "2.
|
|
174
|
+
"@modern-js/plugin": "2.38.0",
|
|
175
|
+
"@modern-js/types": "2.38.0",
|
|
176
|
+
"@modern-js/utils": "2.38.0",
|
|
177
|
+
"@modern-js/runtime-utils": "2.38.0"
|
|
178
178
|
},
|
|
179
179
|
"peerDependencies": {
|
|
180
180
|
"react": ">=17",
|
|
@@ -195,11 +195,11 @@
|
|
|
195
195
|
"ts-jest": "^29.1.0",
|
|
196
196
|
"typescript": "^5",
|
|
197
197
|
"webpack": "^5.88.1",
|
|
198
|
-
"@modern-js/app-tools": "2.
|
|
199
|
-
"@modern-js/core": "2.
|
|
200
|
-
"@modern-js/server-core": "2.
|
|
201
|
-
"@scripts/build": "2.
|
|
202
|
-
"@scripts/jest-config": "2.
|
|
198
|
+
"@modern-js/app-tools": "2.38.0",
|
|
199
|
+
"@modern-js/core": "2.38.0",
|
|
200
|
+
"@modern-js/server-core": "2.38.0",
|
|
201
|
+
"@scripts/build": "2.38.0",
|
|
202
|
+
"@scripts/jest-config": "2.38.0"
|
|
203
203
|
},
|
|
204
204
|
"sideEffects": false,
|
|
205
205
|
"publishConfig": {
|