@modern-js/runtime 2.70.3 → 2.70.4

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.
Files changed (31) hide show
  1. package/dist/cjs/core/context/index.js +1 -1
  2. package/dist/cjs/core/react/wrapper.js +6 -3
  3. package/dist/cjs/core/server/helmet.js +12 -12
  4. package/dist/cjs/core/server/stream/beforeTemplate.js +3 -4
  5. package/dist/cjs/core/server/stream/createReadableStream.js +5 -3
  6. package/dist/cjs/core/server/stream/shared.js +3 -1
  7. package/dist/cjs/core/server/string/index.js +7 -7
  8. package/dist/cjs/exports/head.js +4 -14
  9. package/dist/esm/core/context/index.js +1 -1
  10. package/dist/esm/core/react/wrapper.js +6 -3
  11. package/dist/esm/core/server/helmet.js +13 -13
  12. package/dist/esm/core/server/stream/beforeTemplate.js +4 -5
  13. package/dist/esm/core/server/stream/createReadableStream.js +6 -4
  14. package/dist/esm/core/server/stream/shared.js +4 -2
  15. package/dist/esm/core/server/string/index.js +9 -9
  16. package/dist/esm/exports/head.js +3 -3
  17. package/dist/esm-node/core/context/index.js +1 -1
  18. package/dist/esm-node/core/react/wrapper.js +6 -3
  19. package/dist/esm-node/core/server/helmet.js +12 -12
  20. package/dist/esm-node/core/server/stream/beforeTemplate.js +3 -4
  21. package/dist/esm-node/core/server/stream/createReadableStream.js +5 -3
  22. package/dist/esm-node/core/server/stream/shared.js +3 -1
  23. package/dist/esm-node/core/server/string/index.js +7 -7
  24. package/dist/esm-node/exports/head.js +3 -3
  25. package/dist/types/core/context/index.d.ts +3 -3
  26. package/dist/types/core/react/wrapper.d.ts +4 -1
  27. package/dist/types/core/server/helmet.d.ts +3 -3
  28. package/dist/types/core/server/stream/beforeTemplate.d.ts +1 -0
  29. package/dist/types/core/server/stream/shared.d.ts +1 -0
  30. package/dist/types/exports/head.d.ts +3 -3
  31. package/package.json +13 -14
@@ -37,7 +37,7 @@ __export(context_exports, {
37
37
  });
38
38
  module.exports = __toCommonJS(context_exports);
39
39
  var import_runtime = require("./runtime");
40
- var import_serverPayload = require("./serverPayload/index");
40
+ var import_serverPayload = require("./serverPayload");
41
41
  const globalContext = {};
42
42
  function getGlobalIsRscClient() {
43
43
  return globalContext.isRscClient;
@@ -32,11 +32,14 @@ __export(wrapper_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(wrapper_exports);
34
34
  var import_react = __toESM(require("react"));
35
+ var import_react_helmet_async = require("react-helmet-async");
35
36
  var import_context = require("../context");
36
- function wrapRuntimeContextProvider(App, contextValue) {
37
- return /* @__PURE__ */ import_react.default.createElement(import_context.RuntimeReactContext.Provider, {
37
+ function wrapRuntimeContextProvider(App, contextValue, helmetContext) {
38
+ return /* @__PURE__ */ import_react.default.createElement(import_react_helmet_async.HelmetProvider, {
39
+ context: helmetContext || {}
40
+ }, /* @__PURE__ */ import_react.default.createElement(import_context.RuntimeReactContext.Provider, {
38
41
  value: contextValue
39
- }, App);
42
+ }, App));
40
43
  }
41
44
  // Annotate the CommonJS export names for ESM import in node:
42
45
  0 && (module.exports = {
@@ -29,26 +29,26 @@ const RE_BODY_ATTR = /<body[^>]*>/;
29
29
  const RE_LAST_IN_HEAD = /<\/head>/;
30
30
  const RE_TITLE = /<title[^>]*>([\s\S\n\r]*?)<\/title>/;
31
31
  const TEST_TITLE_CONTENT = RegExp("(?<=<title[^>]*>)([\\s\\S\\n\\r]*?)([.|\\S])([\\s\\S\\n\\r]*?)(?=<\\/title>)");
32
- function createReplaceHelemt(helmetData) {
33
- return helmetData ? (template) => helmetReplace(template, helmetData) : (tempalte) => tempalte;
32
+ function createReplaceHelemt(helmetServerState) {
33
+ return helmetServerState ? (template) => helmetReplace(template, helmetServerState) : (tempalte) => tempalte;
34
34
  }
35
- function helmetReplace(content, helmetData) {
35
+ function helmetReplace(content, helmetServerState) {
36
36
  let result = content;
37
- const bodyAttributes = helmetData.bodyAttributes.toString();
37
+ const bodyAttributes = helmetServerState.bodyAttributes.toString();
38
38
  if (bodyAttributes) {
39
39
  result = (0, import_utils.safeReplace)(result, RE_BODY_ATTR, `<body ${bodyAttributes}>`);
40
40
  }
41
- const htmlAttributes = helmetData.htmlAttributes.toString();
41
+ const htmlAttributes = helmetServerState.htmlAttributes.toString();
42
42
  if (htmlAttributes) {
43
43
  result = (0, import_utils.safeReplace)(result, RE_HTML_ATTR, `<html ${htmlAttributes}>`);
44
44
  }
45
- const base = helmetData.base.toString();
46
- const link = helmetData.link.toString();
47
- const meta = helmetData.meta.toString();
48
- const noscript = helmetData.noscript.toString();
49
- const script = helmetData.script.toString();
50
- const style = helmetData.style.toString();
51
- const title = helmetData.title.toString();
45
+ const base = helmetServerState.base.toString();
46
+ const link = helmetServerState.link.toString();
47
+ const meta = helmetServerState.meta.toString();
48
+ const noscript = helmetServerState.noscript.toString();
49
+ const script = helmetServerState.script.toString();
50
+ const style = helmetServerState.style.toString();
51
+ const title = helmetServerState.title.toString();
52
52
  const existTitleTag = RE_TITLE.test(content);
53
53
  const shouldReplaceTitle = existTitleTag && TEST_TITLE_CONTENT.test(title.trim());
54
54
  if (shouldReplaceTitle) {
@@ -32,7 +32,6 @@ __export(beforeTemplate_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(beforeTemplate_exports);
34
34
  var import_router = require("@modern-js/runtime-utils/router");
35
- var import_react_helmet = __toESM(require("react-helmet"));
36
35
  var import_constants = require("../constants");
37
36
  var import_helmet = require("../helmet");
38
37
  var import_shared = require("../shared");
@@ -55,10 +54,10 @@ const checkIsInline = (chunk, enableInline) => {
55
54
  }
56
55
  };
57
56
  async function buildShellBeforeTemplate(beforeAppTemplate, options) {
58
- const { config, runtimeContext, styledComponentsStyleTags, entryName } = options;
59
- const helmetData = import_react_helmet.default.renderStatic();
57
+ const { config, runtimeContext, styledComponentsStyleTags, entryName, helmetContext } = options;
58
+ const helmetServerState = helmetContext ? helmetContext.helmet : void 0;
60
59
  const callbacks = [
61
- (0, import_helmet.createReplaceHelemt)(helmetData),
60
+ (0, import_helmet.createReplaceHelemt)(helmetServerState),
62
61
  // @TODO: prefetch scripts of lazy component
63
62
  (template) => injectCss(template, entryName, styledComponentsStyleTags)
64
63
  ];
@@ -42,7 +42,7 @@ var import_shared = require("./shared");
42
42
  var import_template = require("./template");
43
43
  const createReadableStreamFromElement = async (request, rootElement, options) => {
44
44
  const { renderToPipeableStream } = await Promise.resolve().then(() => __toESM(require("react-dom/server")));
45
- const { runtimeContext, htmlTemplate, config, ssrConfig, entryName } = options;
45
+ const { runtimeContext, htmlTemplate, config, ssrConfig, entryName, helmetContext } = options;
46
46
  let shellChunkStatus = import_shared.ShellChunkStatus.START;
47
47
  let renderLevel = import_constants.RenderLevel.SERVER_RENDER;
48
48
  const forceStream2String = Boolean(process.env.MODERN_JS_STREAM_TO_STRING);
@@ -64,7 +64,8 @@ const createReadableStreamFromElement = async (request, rootElement, options) =>
64
64
  runtimeContext,
65
65
  config,
66
66
  entryName,
67
- styledComponentsStyleTags
67
+ styledComponentsStyleTags,
68
+ helmetContext
68
69
  }).then(({ shellAfter, shellBefore }) => {
69
70
  const pendingScripts = [];
70
71
  const body = new import_stream.Transform({
@@ -132,7 +133,8 @@ const createReadableStreamFromElement = async (request, rootElement, options) =>
132
133
  renderLevel,
133
134
  runtimeContext,
134
135
  entryName,
135
- config
136
+ config,
137
+ helmetContext
136
138
  }).then(({ shellAfter, shellBefore }) => {
137
139
  var _options_onShellError;
138
140
  const fallbackHtml = `${shellBefore}${shellAfter}`;
@@ -119,9 +119,10 @@ function createRenderStreaming(createReadableStreamPromise) {
119
119
  ]
120
120
  });
121
121
  };
122
+ const helmetContext = {};
122
123
  let rootElement = (0, import_wrapper.wrapRuntimeContextProvider)(serverRoot, Object.assign(runtimeContext, {
123
124
  ssr: true
124
- }));
125
+ }), helmetContext);
125
126
  rootElement = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StreamServerRootWrapper, {
126
127
  children: rootElement
127
128
  });
@@ -135,6 +136,7 @@ function createRenderStreaming(createReadableStreamPromise) {
135
136
  rscSSRManifest: options.rscSSRManifest,
136
137
  rscServerManifest: options.rscServerManifest,
137
138
  rscRoot: options.rscRoot,
139
+ helmetContext,
138
140
  onShellReady() {
139
141
  const cost = end();
140
142
  onTiming(import_tracer.SSRTimings.RENDER_SHELL, cost);
@@ -33,7 +33,6 @@ __export(string_exports, {
33
33
  module.exports = __toCommonJS(string_exports);
34
34
  var import_time = require("@modern-js/runtime-utils/time");
35
35
  var import_server = __toESM(require("react-dom/server"));
36
- var import_react_helmet = __toESM(require("react-helmet"));
37
36
  var import_constants = require("../../constants");
38
37
  var import_wrapper = require("../../react/wrapper");
39
38
  var import_constants2 = require("../constants");
@@ -91,15 +90,16 @@ const renderString = async (request, serverRoot, options) => {
91
90
  useJsonScript: config.useJsonScript
92
91
  })
93
92
  ];
93
+ const helmetContext = {};
94
94
  const rootElement = (0, import_wrapper.wrapRuntimeContextProvider)(serverRoot, Object.assign(runtimeContext, {
95
95
  ssr: true
96
- }));
97
- const html = await generateHtml(rootElement, htmlTemplate, chunkSet, collectors, ((_runtimeContext_ssrContext = runtimeContext.ssrContext) === null || _runtimeContext_ssrContext === void 0 ? void 0 : _runtimeContext_ssrContext.htmlModifiers) || [], tracer);
96
+ }), helmetContext);
97
+ const html = await generateHtml(rootElement, htmlTemplate, chunkSet, collectors, ((_runtimeContext_ssrContext = runtimeContext.ssrContext) === null || _runtimeContext_ssrContext === void 0 ? void 0 : _runtimeContext_ssrContext.htmlModifiers) || [], tracer, helmetContext);
98
98
  return html;
99
99
  };
100
- async function generateHtml(App, htmlTemplate, chunkSet, collectors, htmlModifiers, { onError, onTiming }) {
100
+ async function generateHtml(App, htmlTemplate, chunkSet, collectors, htmlModifiers, { onError, onTiming }, helmetContext) {
101
101
  let html = "";
102
- let helmetData;
102
+ let helmetServerState;
103
103
  const finalApp = collectors.reduce((pre, creator) => {
104
104
  var _creator_collect;
105
105
  return ((_creator_collect = creator.collect) === null || _creator_collect === void 0 ? void 0 : _creator_collect.call(creator, pre)) || pre;
@@ -110,7 +110,7 @@ async function generateHtml(App, htmlTemplate, chunkSet, collectors, htmlModifie
110
110
  html = import_server.default.renderToString(finalApp);
111
111
  chunkSet.renderLevel = import_constants.RenderLevel.SERVER_RENDER;
112
112
  }
113
- helmetData = import_react_helmet.default.renderStatic();
113
+ helmetServerState = helmetContext.helmet;
114
114
  const cost = end();
115
115
  onTiming(import_tracer.SSRTimings.RENDER_HTML, cost);
116
116
  } catch (e) {
@@ -124,7 +124,7 @@ async function generateHtml(App, htmlTemplate, chunkSet, collectors, htmlModifie
124
124
  createReplaceChunkJs(jsChunk),
125
125
  createReplaceChunkCss(cssChunk),
126
126
  createReplaceSSRDataScript(ssrScripts),
127
- (0, import_helmet.createReplaceHelemt)(helmetData),
127
+ (0, import_helmet.createReplaceHelemt)(helmetServerState),
128
128
  ...htmlModifiers
129
129
  ]);
130
130
  return finalHtml;
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -18,24 +16,16 @@ var __copyProps = (to, from, except, desc) => {
18
16
  return to;
19
17
  };
20
18
  var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
21
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
- // If the importer is in node compatibility mode or this is not an ESM
23
- // file that has been converted to a CommonJS file using a Babel-
24
- // compatible transform (i.e. "__esModule" has not been set), then set
25
- // "default" to the CommonJS "module.exports" for node compatibility.
26
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
- mod
28
- ));
29
19
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
20
  var head_exports = {};
31
21
  __export(head_exports, {
32
22
  default: () => head_default
33
23
  });
34
24
  module.exports = __toCommonJS(head_exports);
35
- var import_react_helmet = __toESM(require("react-helmet"));
36
- __reExport(head_exports, require("react-helmet"), module.exports);
37
- var head_default = import_react_helmet.default;
25
+ var import_react_helmet_async = require("react-helmet-async");
26
+ __reExport(head_exports, require("react-helmet-async"), module.exports);
27
+ var head_default = import_react_helmet_async.Helmet;
38
28
  // Annotate the CommonJS export names for ESM import in node:
39
29
  0 && (module.exports = {
40
- ...require("react-helmet")
30
+ ...require("react-helmet-async")
41
31
  });
@@ -1,6 +1,6 @@
1
1
  import { RuntimeReactContext, getInitialContext } from "./runtime";
2
2
  var globalContext = {};
3
- import { getServerPayload, setServerPayload } from "./serverPayload/index";
3
+ import { getServerPayload, setServerPayload } from "./serverPayload";
4
4
  function getGlobalIsRscClient() {
5
5
  return globalContext.isRscClient;
6
6
  }
@@ -1,9 +1,12 @@
1
1
  import React from "react";
2
+ import { HelmetProvider } from "react-helmet-async";
2
3
  import { RuntimeReactContext } from "../context";
3
- function wrapRuntimeContextProvider(App, contextValue) {
4
- return /* @__PURE__ */ React.createElement(RuntimeReactContext.Provider, {
4
+ function wrapRuntimeContextProvider(App, contextValue, helmetContext) {
5
+ return /* @__PURE__ */ React.createElement(HelmetProvider, {
6
+ context: helmetContext || {}
7
+ }, /* @__PURE__ */ React.createElement(RuntimeReactContext.Provider, {
5
8
  value: contextValue
6
- }, App);
9
+ }, App));
7
10
  }
8
11
  export {
9
12
  wrapRuntimeContextProvider
@@ -5,30 +5,30 @@ var RE_BODY_ATTR = /<body[^>]*>/;
5
5
  var RE_LAST_IN_HEAD = /<\/head>/;
6
6
  var RE_TITLE = /<title[^>]*>([\s\S\n\r]*?)<\/title>/;
7
7
  var TEST_TITLE_CONTENT = RegExp("(?<=<title[^>]*>)([\\s\\S\\n\\r]*?)([.|\\S])([\\s\\S\\n\\r]*?)(?=<\\/title>)");
8
- function createReplaceHelemt(helmetData) {
9
- return helmetData ? function(template) {
10
- return helmetReplace(template, helmetData);
8
+ function createReplaceHelemt(helmetServerState) {
9
+ return helmetServerState ? function(template) {
10
+ return helmetReplace(template, helmetServerState);
11
11
  } : function(tempalte) {
12
12
  return tempalte;
13
13
  };
14
14
  }
15
- function helmetReplace(content, helmetData) {
15
+ function helmetReplace(content, helmetServerState) {
16
16
  var result = content;
17
- var bodyAttributes = helmetData.bodyAttributes.toString();
17
+ var bodyAttributes = helmetServerState.bodyAttributes.toString();
18
18
  if (bodyAttributes) {
19
19
  result = safeReplace(result, RE_BODY_ATTR, "<body ".concat(bodyAttributes, ">"));
20
20
  }
21
- var htmlAttributes = helmetData.htmlAttributes.toString();
21
+ var htmlAttributes = helmetServerState.htmlAttributes.toString();
22
22
  if (htmlAttributes) {
23
23
  result = safeReplace(result, RE_HTML_ATTR, "<html ".concat(htmlAttributes, ">"));
24
24
  }
25
- var base = helmetData.base.toString();
26
- var link = helmetData.link.toString();
27
- var meta = helmetData.meta.toString();
28
- var noscript = helmetData.noscript.toString();
29
- var script = helmetData.script.toString();
30
- var style = helmetData.style.toString();
31
- var title = helmetData.title.toString();
25
+ var base = helmetServerState.base.toString();
26
+ var link = helmetServerState.link.toString();
27
+ var meta = helmetServerState.meta.toString();
28
+ var noscript = helmetServerState.noscript.toString();
29
+ var script = helmetServerState.script.toString();
30
+ var style = helmetServerState.style.toString();
31
+ var title = helmetServerState.title.toString();
32
32
  var existTitleTag = RE_TITLE.test(content);
33
33
  var shouldReplaceTitle = existTitleTag && TEST_TITLE_CONTENT.test(title.trim());
34
34
  if (shouldReplaceTitle) {
@@ -3,7 +3,6 @@ import { _ as _instanceof } from "@swc/helpers/_/_instanceof";
3
3
  import { _ as _to_consumable_array } from "@swc/helpers/_/_to_consumable_array";
4
4
  import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
5
5
  import { matchRoutes } from "@modern-js/runtime-utils/router";
6
- import ReactHelmet from "react-helmet";
7
6
  import { CHUNK_CSS_PLACEHOLDER } from "../constants";
8
7
  import { createReplaceHelemt } from "../helmet";
9
8
  import { buildHtml } from "../shared";
@@ -54,7 +53,7 @@ function buildShellBeforeTemplate(beforeAppTemplate, options) {
54
53
  }
55
54
  function _buildShellBeforeTemplate() {
56
55
  _buildShellBeforeTemplate = _async_to_generator(function(beforeAppTemplate, options) {
57
- var config, runtimeContext, styledComponentsStyleTags, entryName, helmetData, callbacks;
56
+ var config, runtimeContext, styledComponentsStyleTags, entryName, helmetContext, helmetServerState, callbacks;
58
57
  function injectCss(template, entryName2, styledComponentsStyleTags2) {
59
58
  return _injectCss.apply(this, arguments);
60
59
  }
@@ -166,10 +165,10 @@ function _buildShellBeforeTemplate() {
166
165
  return _injectCss.apply(this, arguments);
167
166
  }
168
167
  return _ts_generator(this, function(_state) {
169
- config = options.config, runtimeContext = options.runtimeContext, styledComponentsStyleTags = options.styledComponentsStyleTags, entryName = options.entryName;
170
- helmetData = ReactHelmet.renderStatic();
168
+ config = options.config, runtimeContext = options.runtimeContext, styledComponentsStyleTags = options.styledComponentsStyleTags, entryName = options.entryName, helmetContext = options.helmetContext;
169
+ helmetServerState = helmetContext ? helmetContext.helmet : void 0;
171
170
  callbacks = [
172
- createReplaceHelemt(helmetData),
171
+ createReplaceHelemt(helmetServerState),
173
172
  // @TODO: prefetch scripts of lazy component
174
173
  function(template) {
175
174
  return injectCss(template, entryName, styledComponentsStyleTags);
@@ -13,7 +13,7 @@ import { ShellChunkStatus, getReadableStreamFromString, resolveStreamingMode } f
13
13
  import { getTemplates } from "./template";
14
14
  var createReadableStreamFromElement = function() {
15
15
  var _ref = _async_to_generator(function(request, rootElement, options) {
16
- var renderToPipeableStream, runtimeContext, htmlTemplate, config, ssrConfig, entryName, shellChunkStatus, renderLevel, forceStream2String, onReady, sheet, chunkVec, root;
16
+ var renderToPipeableStream, runtimeContext, htmlTemplate, config, ssrConfig, entryName, helmetContext, shellChunkStatus, renderLevel, forceStream2String, onReady, sheet, chunkVec, root;
17
17
  return _ts_generator(this, function(_state) {
18
18
  switch (_state.label) {
19
19
  case 0:
@@ -23,7 +23,7 @@ var createReadableStreamFromElement = function() {
23
23
  ];
24
24
  case 1:
25
25
  renderToPipeableStream = _state.sent().renderToPipeableStream;
26
- runtimeContext = options.runtimeContext, htmlTemplate = options.htmlTemplate, config = options.config, ssrConfig = options.ssrConfig, entryName = options.entryName;
26
+ runtimeContext = options.runtimeContext, htmlTemplate = options.htmlTemplate, config = options.config, ssrConfig = options.ssrConfig, entryName = options.entryName, helmetContext = options.helmetContext;
27
27
  shellChunkStatus = ShellChunkStatus.START;
28
28
  renderLevel = RenderLevel.SERVER_RENDER;
29
29
  forceStream2String = Boolean(process.env.MODERN_JS_STREAM_TO_STRING);
@@ -48,7 +48,8 @@ var createReadableStreamFromElement = function() {
48
48
  runtimeContext,
49
49
  config,
50
50
  entryName,
51
- styledComponentsStyleTags
51
+ styledComponentsStyleTags,
52
+ helmetContext
52
53
  }).then(function(param) {
53
54
  var shellAfter = param.shellAfter, shellBefore = param.shellBefore;
54
55
  var pendingScripts = [];
@@ -135,7 +136,8 @@ var createReadableStreamFromElement = function() {
135
136
  renderLevel,
136
137
  runtimeContext,
137
138
  entryName,
138
- config
139
+ config,
140
+ helmetContext
139
141
  }).then(function(param) {
140
142
  var shellAfter = param.shellAfter, shellBefore = param.shellBefore;
141
143
  var _options_onShellError;
@@ -71,7 +71,7 @@ function getReadableStreamFromString(content) {
71
71
  function createRenderStreaming(createReadableStreamPromise) {
72
72
  return function() {
73
73
  var _ref = _async_to_generator(function(request, serverRoot, options) {
74
- var createReadableStreamFromElement, end, runtimeContext, config, resource, onError, onTiming, htmlTemplate, entryName, ssrConfig, StreamServerRootWrapper, rootElement, stream;
74
+ var createReadableStreamFromElement, end, runtimeContext, config, resource, onError, onTiming, htmlTemplate, entryName, ssrConfig, StreamServerRootWrapper, helmetContext, rootElement, stream;
75
75
  return _ts_generator(this, function(_state) {
76
76
  switch (_state.label) {
77
77
  case 0:
@@ -95,9 +95,10 @@ function createRenderStreaming(createReadableStreamPromise) {
95
95
  ]
96
96
  });
97
97
  };
98
+ helmetContext = {};
98
99
  rootElement = wrapRuntimeContextProvider(serverRoot, Object.assign(runtimeContext, {
99
100
  ssr: true
100
- }));
101
+ }), helmetContext);
101
102
  rootElement = /* @__PURE__ */ _jsx(StreamServerRootWrapper, {
102
103
  children: rootElement
103
104
  });
@@ -113,6 +114,7 @@ function createRenderStreaming(createReadableStreamPromise) {
113
114
  rscSSRManifest: options.rscSSRManifest,
114
115
  rscServerManifest: options.rscServerManifest,
115
116
  rscRoot: options.rscRoot,
117
+ helmetContext,
116
118
  onShellReady: function onShellReady() {
117
119
  var cost = end();
118
120
  onTiming(SSRTimings.RENDER_SHELL, cost);
@@ -3,7 +3,6 @@ import { _ as _to_consumable_array } from "@swc/helpers/_/_to_consumable_array";
3
3
  import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
4
4
  import { time } from "@modern-js/runtime-utils/time";
5
5
  import ReactDomServer from "react-dom/server";
6
- import ReactHelmet from "react-helmet";
7
6
  import { RenderLevel } from "../../constants";
8
7
  import { wrapRuntimeContextProvider } from "../../react/wrapper";
9
8
  import { CHUNK_CSS_PLACEHOLDER, CHUNK_JS_PLACEHOLDER, HTML_PLACEHOLDER, SSR_DATA_PLACEHOLDER } from "../constants";
@@ -17,7 +16,7 @@ import { SSRDataCollector } from "./ssrData";
17
16
  import { StyledCollector } from "./styledComponent";
18
17
  var renderString = function() {
19
18
  var _ref = _async_to_generator(function(request, serverRoot, options) {
20
- var _runtimeContext_ssrContext, resource, runtimeContext, config, onError, onTiming, tracer, routerContext, htmlTemplate, entryName, loadableStats, routeManifest, ssrConfig, chunkSet, prefetchData, e, collectors, rootElement, html;
19
+ var _runtimeContext_ssrContext, resource, runtimeContext, config, onError, onTiming, tracer, routerContext, htmlTemplate, entryName, loadableStats, routeManifest, ssrConfig, chunkSet, prefetchData, e, collectors, helmetContext, rootElement, html;
21
20
  return _ts_generator(this, function(_state) {
22
21
  switch (_state.label) {
23
22
  case 0:
@@ -86,12 +85,13 @@ var renderString = function() {
86
85
  useJsonScript: config.useJsonScript
87
86
  })
88
87
  ];
88
+ helmetContext = {};
89
89
  rootElement = wrapRuntimeContextProvider(serverRoot, Object.assign(runtimeContext, {
90
90
  ssr: true
91
- }));
91
+ }), helmetContext);
92
92
  return [
93
93
  4,
94
- generateHtml(rootElement, htmlTemplate, chunkSet, collectors, ((_runtimeContext_ssrContext = runtimeContext.ssrContext) === null || _runtimeContext_ssrContext === void 0 ? void 0 : _runtimeContext_ssrContext.htmlModifiers) || [], tracer)
94
+ generateHtml(rootElement, htmlTemplate, chunkSet, collectors, ((_runtimeContext_ssrContext = runtimeContext.ssrContext) === null || _runtimeContext_ssrContext === void 0 ? void 0 : _runtimeContext_ssrContext.htmlModifiers) || [], tracer, helmetContext)
95
95
  ];
96
96
  case 5:
97
97
  html = _state.sent();
@@ -106,12 +106,12 @@ var renderString = function() {
106
106
  return _ref.apply(this, arguments);
107
107
  };
108
108
  }();
109
- function generateHtml(App, htmlTemplate, chunkSet, collectors, htmlModifiers, _) {
109
+ function generateHtml(App, htmlTemplate, chunkSet, collectors, htmlModifiers, _, helmetContext) {
110
110
  return _generateHtml.apply(this, arguments);
111
111
  }
112
112
  function _generateHtml() {
113
- _generateHtml = _async_to_generator(function(App, htmlTemplate, chunkSet, collectors, htmlModifiers, param) {
114
- var onError, onTiming, html, helmetData, finalApp, end, cost, ssrScripts, cssChunk, jsChunk, finalHtml;
113
+ _generateHtml = _async_to_generator(function(App, htmlTemplate, chunkSet, collectors, htmlModifiers, param, helmetContext) {
114
+ var onError, onTiming, html, helmetServerState, finalApp, end, cost, ssrScripts, cssChunk, jsChunk, finalHtml;
115
115
  return _ts_generator(this, function(_state) {
116
116
  switch (_state.label) {
117
117
  case 0:
@@ -127,7 +127,7 @@ function _generateHtml() {
127
127
  html = ReactDomServer.renderToString(finalApp);
128
128
  chunkSet.renderLevel = RenderLevel.SERVER_RENDER;
129
129
  }
130
- helmetData = ReactHelmet.renderStatic();
130
+ helmetServerState = helmetContext.helmet;
131
131
  cost = end();
132
132
  onTiming(SSRTimings.RENDER_HTML, cost);
133
133
  } catch (e) {
@@ -150,7 +150,7 @@ function _generateHtml() {
150
150
  createReplaceChunkJs(jsChunk),
151
151
  createReplaceChunkCss(cssChunk),
152
152
  createReplaceSSRDataScript(ssrScripts),
153
- createReplaceHelemt(helmetData)
153
+ createReplaceHelemt(helmetServerState)
154
154
  ].concat(_to_consumable_array(htmlModifiers)))
155
155
  ];
156
156
  case 2:
@@ -1,6 +1,6 @@
1
- import head from "react-helmet";
2
- var head_default = head;
3
- export * from "react-helmet";
1
+ import { Helmet } from "react-helmet-async";
2
+ var head_default = Helmet;
3
+ export * from "react-helmet-async";
4
4
  export {
5
5
  head_default as default
6
6
  };
@@ -1,6 +1,6 @@
1
1
  import { RuntimeReactContext, getInitialContext } from "./runtime";
2
2
  const globalContext = {};
3
- import { getServerPayload, setServerPayload } from "./serverPayload/index";
3
+ import { getServerPayload, setServerPayload } from "./serverPayload";
4
4
  function getGlobalIsRscClient() {
5
5
  return globalContext.isRscClient;
6
6
  }
@@ -1,9 +1,12 @@
1
1
  import React from "react";
2
+ import { HelmetProvider } from "react-helmet-async";
2
3
  import { RuntimeReactContext } from "../context";
3
- function wrapRuntimeContextProvider(App, contextValue) {
4
- return /* @__PURE__ */ React.createElement(RuntimeReactContext.Provider, {
4
+ function wrapRuntimeContextProvider(App, contextValue, helmetContext) {
5
+ return /* @__PURE__ */ React.createElement(HelmetProvider, {
6
+ context: helmetContext || {}
7
+ }, /* @__PURE__ */ React.createElement(RuntimeReactContext.Provider, {
5
8
  value: contextValue
6
- }, App);
9
+ }, App));
7
10
  }
8
11
  export {
9
12
  wrapRuntimeContextProvider
@@ -5,26 +5,26 @@ const RE_BODY_ATTR = /<body[^>]*>/;
5
5
  const RE_LAST_IN_HEAD = /<\/head>/;
6
6
  const RE_TITLE = /<title[^>]*>([\s\S\n\r]*?)<\/title>/;
7
7
  const TEST_TITLE_CONTENT = RegExp("(?<=<title[^>]*>)([\\s\\S\\n\\r]*?)([.|\\S])([\\s\\S\\n\\r]*?)(?=<\\/title>)");
8
- function createReplaceHelemt(helmetData) {
9
- return helmetData ? (template) => helmetReplace(template, helmetData) : (tempalte) => tempalte;
8
+ function createReplaceHelemt(helmetServerState) {
9
+ return helmetServerState ? (template) => helmetReplace(template, helmetServerState) : (tempalte) => tempalte;
10
10
  }
11
- function helmetReplace(content, helmetData) {
11
+ function helmetReplace(content, helmetServerState) {
12
12
  let result = content;
13
- const bodyAttributes = helmetData.bodyAttributes.toString();
13
+ const bodyAttributes = helmetServerState.bodyAttributes.toString();
14
14
  if (bodyAttributes) {
15
15
  result = safeReplace(result, RE_BODY_ATTR, `<body ${bodyAttributes}>`);
16
16
  }
17
- const htmlAttributes = helmetData.htmlAttributes.toString();
17
+ const htmlAttributes = helmetServerState.htmlAttributes.toString();
18
18
  if (htmlAttributes) {
19
19
  result = safeReplace(result, RE_HTML_ATTR, `<html ${htmlAttributes}>`);
20
20
  }
21
- const base = helmetData.base.toString();
22
- const link = helmetData.link.toString();
23
- const meta = helmetData.meta.toString();
24
- const noscript = helmetData.noscript.toString();
25
- const script = helmetData.script.toString();
26
- const style = helmetData.style.toString();
27
- const title = helmetData.title.toString();
21
+ const base = helmetServerState.base.toString();
22
+ const link = helmetServerState.link.toString();
23
+ const meta = helmetServerState.meta.toString();
24
+ const noscript = helmetServerState.noscript.toString();
25
+ const script = helmetServerState.script.toString();
26
+ const style = helmetServerState.style.toString();
27
+ const title = helmetServerState.title.toString();
28
28
  const existTitleTag = RE_TITLE.test(content);
29
29
  const shouldReplaceTitle = existTitleTag && TEST_TITLE_CONTENT.test(title.trim());
30
30
  if (shouldReplaceTitle) {
@@ -1,5 +1,4 @@
1
1
  import { matchRoutes } from "@modern-js/runtime-utils/router";
2
- import ReactHelmet from "react-helmet";
3
2
  import { CHUNK_CSS_PLACEHOLDER } from "../constants";
4
3
  import { createReplaceHelemt } from "../helmet";
5
4
  import { buildHtml } from "../shared";
@@ -22,10 +21,10 @@ const checkIsInline = (chunk, enableInline) => {
22
21
  }
23
22
  };
24
23
  async function buildShellBeforeTemplate(beforeAppTemplate, options) {
25
- const { config, runtimeContext, styledComponentsStyleTags, entryName } = options;
26
- const helmetData = ReactHelmet.renderStatic();
24
+ const { config, runtimeContext, styledComponentsStyleTags, entryName, helmetContext } = options;
25
+ const helmetServerState = helmetContext ? helmetContext.helmet : void 0;
27
26
  const callbacks = [
28
- createReplaceHelemt(helmetData),
27
+ createReplaceHelemt(helmetServerState),
29
28
  // @TODO: prefetch scripts of lazy component
30
29
  (template) => injectCss(template, entryName, styledComponentsStyleTags)
31
30
  ];
@@ -9,7 +9,7 @@ import { ShellChunkStatus, getReadableStreamFromString, resolveStreamingMode } f
9
9
  import { getTemplates } from "./template";
10
10
  const createReadableStreamFromElement = async (request, rootElement, options) => {
11
11
  const { renderToPipeableStream } = await import("react-dom/server");
12
- const { runtimeContext, htmlTemplate, config, ssrConfig, entryName } = options;
12
+ const { runtimeContext, htmlTemplate, config, ssrConfig, entryName, helmetContext } = options;
13
13
  let shellChunkStatus = ShellChunkStatus.START;
14
14
  let renderLevel = RenderLevel.SERVER_RENDER;
15
15
  const forceStream2String = Boolean(process.env.MODERN_JS_STREAM_TO_STRING);
@@ -31,7 +31,8 @@ const createReadableStreamFromElement = async (request, rootElement, options) =>
31
31
  runtimeContext,
32
32
  config,
33
33
  entryName,
34
- styledComponentsStyleTags
34
+ styledComponentsStyleTags,
35
+ helmetContext
35
36
  }).then(({ shellAfter, shellBefore }) => {
36
37
  const pendingScripts = [];
37
38
  const body = new Transform({
@@ -99,7 +100,8 @@ const createReadableStreamFromElement = async (request, rootElement, options) =>
99
100
  renderLevel,
100
101
  runtimeContext,
101
102
  entryName,
102
- config
103
+ config,
104
+ helmetContext
103
105
  }).then(({ shellAfter, shellBefore }) => {
104
106
  var _options_onShellError;
105
107
  const fallbackHtml = `${shellBefore}${shellAfter}`;
@@ -82,9 +82,10 @@ function createRenderStreaming(createReadableStreamPromise) {
82
82
  ]
83
83
  });
84
84
  };
85
+ const helmetContext = {};
85
86
  let rootElement = wrapRuntimeContextProvider(serverRoot, Object.assign(runtimeContext, {
86
87
  ssr: true
87
- }));
88
+ }), helmetContext);
88
89
  rootElement = /* @__PURE__ */ _jsx(StreamServerRootWrapper, {
89
90
  children: rootElement
90
91
  });
@@ -98,6 +99,7 @@ function createRenderStreaming(createReadableStreamPromise) {
98
99
  rscSSRManifest: options.rscSSRManifest,
99
100
  rscServerManifest: options.rscServerManifest,
100
101
  rscRoot: options.rscRoot,
102
+ helmetContext,
101
103
  onShellReady() {
102
104
  const cost = end();
103
105
  onTiming(SSRTimings.RENDER_SHELL, cost);
@@ -1,6 +1,5 @@
1
1
  import { time } from "@modern-js/runtime-utils/time";
2
2
  import ReactDomServer from "react-dom/server";
3
- import ReactHelmet from "react-helmet";
4
3
  import { RenderLevel } from "../../constants";
5
4
  import { wrapRuntimeContextProvider } from "../../react/wrapper";
6
5
  import { CHUNK_CSS_PLACEHOLDER, CHUNK_JS_PLACEHOLDER, HTML_PLACEHOLDER, SSR_DATA_PLACEHOLDER } from "../constants";
@@ -58,15 +57,16 @@ const renderString = async (request, serverRoot, options) => {
58
57
  useJsonScript: config.useJsonScript
59
58
  })
60
59
  ];
60
+ const helmetContext = {};
61
61
  const rootElement = wrapRuntimeContextProvider(serverRoot, Object.assign(runtimeContext, {
62
62
  ssr: true
63
- }));
64
- const html = await generateHtml(rootElement, htmlTemplate, chunkSet, collectors, ((_runtimeContext_ssrContext = runtimeContext.ssrContext) === null || _runtimeContext_ssrContext === void 0 ? void 0 : _runtimeContext_ssrContext.htmlModifiers) || [], tracer);
63
+ }), helmetContext);
64
+ const html = await generateHtml(rootElement, htmlTemplate, chunkSet, collectors, ((_runtimeContext_ssrContext = runtimeContext.ssrContext) === null || _runtimeContext_ssrContext === void 0 ? void 0 : _runtimeContext_ssrContext.htmlModifiers) || [], tracer, helmetContext);
65
65
  return html;
66
66
  };
67
- async function generateHtml(App, htmlTemplate, chunkSet, collectors, htmlModifiers, { onError, onTiming }) {
67
+ async function generateHtml(App, htmlTemplate, chunkSet, collectors, htmlModifiers, { onError, onTiming }, helmetContext) {
68
68
  let html = "";
69
- let helmetData;
69
+ let helmetServerState;
70
70
  const finalApp = collectors.reduce((pre, creator) => {
71
71
  var _creator_collect;
72
72
  return ((_creator_collect = creator.collect) === null || _creator_collect === void 0 ? void 0 : _creator_collect.call(creator, pre)) || pre;
@@ -77,7 +77,7 @@ async function generateHtml(App, htmlTemplate, chunkSet, collectors, htmlModifie
77
77
  html = ReactDomServer.renderToString(finalApp);
78
78
  chunkSet.renderLevel = RenderLevel.SERVER_RENDER;
79
79
  }
80
- helmetData = ReactHelmet.renderStatic();
80
+ helmetServerState = helmetContext.helmet;
81
81
  const cost = end();
82
82
  onTiming(SSRTimings.RENDER_HTML, cost);
83
83
  } catch (e) {
@@ -91,7 +91,7 @@ async function generateHtml(App, htmlTemplate, chunkSet, collectors, htmlModifie
91
91
  createReplaceChunkJs(jsChunk),
92
92
  createReplaceChunkCss(cssChunk),
93
93
  createReplaceSSRDataScript(ssrScripts),
94
- createReplaceHelemt(helmetData),
94
+ createReplaceHelemt(helmetServerState),
95
95
  ...htmlModifiers
96
96
  ]);
97
97
  return finalHtml;
@@ -1,6 +1,6 @@
1
- import head from "react-helmet";
2
- var head_default = head;
3
- export * from "react-helmet";
1
+ import { Helmet } from "react-helmet-async";
2
+ var head_default = Helmet;
3
+ export * from "react-helmet-async";
4
4
  export {
5
5
  head_default as default
6
6
  };
@@ -3,9 +3,9 @@ import type { NestedRoute, PageRoute } from '@modern-js/types';
3
3
  import type React from 'react';
4
4
  import type { AppConfig } from '../../common';
5
5
  import type { RuntimeExtends } from '../plugin/types';
6
- import type { ServerPayload } from './serverPayload/index';
6
+ import type { ServerPayload } from './serverPayload';
7
7
  export { type RuntimeContext, RuntimeReactContext, getInitialContext, } from './runtime';
8
- export type { ServerPayload, PayloadRoute } from './serverPayload/index';
8
+ export type { ServerPayload, PayloadRoute } from './serverPayload';
9
9
  interface GlobalContext {
10
10
  entryName?: string;
11
11
  /**
@@ -37,7 +37,7 @@ interface GlobalContext {
37
37
  serverPayload?: ServerPayload;
38
38
  enableRsc?: boolean;
39
39
  }
40
- export { getServerPayload, setServerPayload, } from './serverPayload/index';
40
+ export { getServerPayload, setServerPayload, } from './serverPayload';
41
41
  export declare function getGlobalIsRscClient(): boolean | undefined;
42
42
  export declare function getGlobalEnableRsc(): boolean | undefined;
43
43
  export declare function setGlobalContext(context: Omit<GlobalContext, 'appConfig' | 'internalRuntimeContext'> & {
@@ -1,3 +1,6 @@
1
1
  import React from 'react';
2
+ import { type HelmetServerState } from 'react-helmet-async';
2
3
  import { type RuntimeContext } from '../context';
3
- export declare function wrapRuntimeContextProvider(App: React.ReactElement, contextValue: RuntimeContext): React.FunctionComponentElement<React.ProviderProps<RuntimeContext>>;
4
+ export declare function wrapRuntimeContextProvider(App: React.ReactElement, contextValue: RuntimeContext, helmetContext?: {
5
+ helmet?: HelmetServerState;
6
+ }): React.ReactElement;
@@ -1,3 +1,3 @@
1
- import type { HelmetData } from 'react-helmet';
2
- export declare function createReplaceHelemt(helmetData?: HelmetData): (template: string) => string;
3
- export declare function helmetReplace(content: string, helmetData: HelmetData): string;
1
+ import type { HelmetServerState } from 'react-helmet-async';
2
+ export declare function createReplaceHelemt(helmetServerState?: HelmetServerState): (template: string) => string;
3
+ export declare function helmetReplace(content: string, helmetServerState: HelmetServerState): string;
@@ -5,5 +5,6 @@ export interface BuildShellBeforeTemplateOptions {
5
5
  entryName: string;
6
6
  config: HandleRequestConfig;
7
7
  styledComponentsStyleTags?: string;
8
+ helmetContext?: Record<string, unknown>;
8
9
  }
9
10
  export declare function buildShellBeforeTemplate(beforeAppTemplate: string, options: BuildShellBeforeTemplateOptions): Promise<string>;
@@ -18,6 +18,7 @@ export type CreateReadableStreamFromElementOptions = {
18
18
  onShellError?: (error: unknown) => void;
19
19
  onAllReady?: () => void;
20
20
  onError: OnError;
21
+ helmetContext?: Record<string, unknown>;
21
22
  };
22
23
  export type CreateReadableStreamFromElement = (request: Request, rootElement: React.ReactElement, options: CreateReadableStreamFromElementOptions) => Promise<ReadableStream<Uint8Array>>;
23
24
  export declare enum ShellChunkStatus {
@@ -1,3 +1,3 @@
1
- import head from 'react-helmet';
2
- export default head;
3
- export * from 'react-helmet';
1
+ import { Helmet } from 'react-helmet-async';
2
+ export default Helmet;
3
+ export * from 'react-helmet-async';
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "modern",
16
16
  "modern.js"
17
17
  ],
18
- "version": "2.70.3",
18
+ "version": "2.70.4",
19
19
  "engines": {
20
20
  "node": ">=14.17.6"
21
21
  },
@@ -201,31 +201,30 @@
201
201
  }
202
202
  },
203
203
  "dependencies": {
204
- "@babel/core": "^7.26.0",
204
+ "@babel/core": "^7.28.6",
205
205
  "@babel/types": "^7.26.0",
206
206
  "@loadable/babel-plugin": "5.15.3",
207
207
  "@loadable/component": "5.15.3",
208
208
  "@loadable/server": "5.15.3",
209
209
  "@swc/helpers": "^0.5.17",
210
210
  "@types/loadable__component": "^5.13.4",
211
- "@types/react-helmet": "^6.1.2",
212
211
  "@types/styled-components": "^5.1.14",
213
212
  "cookie": "0.7.2",
214
213
  "es-module-lexer": "^1.1.0",
215
214
  "esbuild": "0.25.5",
216
215
  "invariant": "^2.2.4",
217
216
  "isbot": "3.7.1",
218
- "react-helmet": "^6.1.0",
217
+ "react-helmet-async": "2.0.5",
219
218
  "react-is": "^18",
220
219
  "react-side-effect": "^2.1.2",
221
220
  "styled-components": "^5.3.1",
222
- "@modern-js/plugin": "2.70.3",
223
- "@modern-js/plugin-data-loader": "2.70.3",
224
- "@modern-js/plugin-v2": "2.70.3",
225
- "@modern-js/render": "2.70.3",
226
- "@modern-js/runtime-utils": "2.70.3",
227
- "@modern-js/types": "2.70.3",
228
- "@modern-js/utils": "2.70.3"
221
+ "@modern-js/plugin": "2.70.4",
222
+ "@modern-js/plugin-data-loader": "2.70.4",
223
+ "@modern-js/plugin-v2": "2.70.4",
224
+ "@modern-js/render": "2.70.4",
225
+ "@modern-js/runtime-utils": "2.70.4",
226
+ "@modern-js/utils": "2.70.4",
227
+ "@modern-js/types": "2.70.4"
229
228
  },
230
229
  "peerDependencies": {
231
230
  "react": ">=17",
@@ -249,10 +248,10 @@
249
248
  "ts-node": "^10.9.1",
250
249
  "typescript": "^5",
251
250
  "webpack": "^5.103.0",
252
- "@modern-js/app-tools": "2.70.3",
253
- "@scripts/jest-config": "2.66.0",
251
+ "@modern-js/app-tools": "2.70.4",
254
252
  "@scripts/build": "2.66.0",
255
- "@modern-js/core": "2.70.3"
253
+ "@scripts/jest-config": "2.66.0",
254
+ "@modern-js/core": "2.70.4"
256
255
  },
257
256
  "sideEffects": false,
258
257
  "publishConfig": {