From e095d7e9fea1acdb8d81717c0d3c79dab0d66052 Mon Sep 17 00:00:00 2001 From: kongjiacong Date: Mon, 9 Dec 2024 16:08:14 +0800 Subject: [PATCH 1/3] feat: use server.useJsonScript instead ssr.inlineScript --- .../plugin-runtime/src/core/react/index.tsx | 2 +- .../src/core/server/requestHandler.ts | 8 +-- .../src/core/server/stream/afterTemplate.ts | 18 +++--- .../src/core/server/string/index.ts | 1 + .../src/core/server/string/ssrData.ts | 24 +++----- .../plugin-runtime/src/core/server/utils.ts | 8 --- .../runtime/plugin-runtime/src/core/types.ts | 2 +- .../runtime/DeferredDataScripts.node.tsx | 16 ++--- .../src/router/runtime/plugin.node.tsx | 4 +- .../core/src/plugins/render/ssrRender.ts | 1 + .../server/core/src/types/config/server.ts | 7 ++- .../server/core/src/types/requestHandler.ts | 1 + pnpm-lock.yaml | 60 +++++++++++-------- .../server-json-script/modern.config.ts | 12 ++++ .../server-json-script/package.json | 31 ++++++++++ .../server-json-script/src/routes/layout.tsx | 9 +++ .../server-json-script/src/routes/page.tsx | 5 ++ .../server-json-script/tests/index.test.ts | 48 +++++++++++++++ .../server-json-script/tests/tsconfig.json | 12 ++++ .../server-json-script/tsconfig.json | 13 ++++ 20 files changed, 206 insertions(+), 76 deletions(-) create mode 100644 tests/integration/server-json-script/modern.config.ts create mode 100644 tests/integration/server-json-script/package.json create mode 100644 tests/integration/server-json-script/src/routes/layout.tsx create mode 100644 tests/integration/server-json-script/src/routes/page.tsx create mode 100644 tests/integration/server-json-script/tests/index.test.ts create mode 100644 tests/integration/server-json-script/tests/tsconfig.json create mode 100644 tests/integration/server-json-script/tsconfig.json diff --git a/packages/runtime/plugin-runtime/src/core/react/index.tsx b/packages/runtime/plugin-runtime/src/core/react/index.tsx index 0301f856813d..10bd2719fa78 100644 --- a/packages/runtime/plugin-runtime/src/core/react/index.tsx +++ b/packages/runtime/plugin-runtime/src/core/react/index.tsx @@ -9,7 +9,7 @@ export function createRoot(UserApp?: React.ComponentType | null) { const App = UserApp || getGlobalApp(); if (isBrowser()) { - // we should get data from HTMLElement when set ssr.inlineScript = false + // we should get data from HTMLElement when set server.useInline = false window._SSR_DATA = window._SSR_DATA || parsedJSONFromElement(SSR_DATA_JSON_ID); diff --git a/packages/runtime/plugin-runtime/src/core/server/requestHandler.ts b/packages/runtime/plugin-runtime/src/core/server/requestHandler.ts index 2de74c3cfc29..420df0bed819 100644 --- a/packages/runtime/plugin-runtime/src/core/server/requestHandler.ts +++ b/packages/runtime/plugin-runtime/src/core/server/requestHandler.ts @@ -16,7 +16,7 @@ import { getGlobalRunner } from '../plugin/runner'; import { createRoot } from '../react'; import type { SSRServerContext } from '../types'; import { CHUNK_CSS_PLACEHOLDER } from './constants'; -import { getSSRConfigByEntry, getSSRInlineScript, getSSRMode } from './utils'; +import { getSSRConfigByEntry, getSSRMode } from './utils'; export type { RequestHandlerConfig as HandleRequestConfig } from '@modern-js/app-tools'; @@ -62,7 +62,7 @@ function createSSRContext( reporter, } = options; - const { nonce } = config; + const { nonce, useJsonScript } = config; const { entryName, route } = resource; @@ -100,15 +100,14 @@ function createSSRContext( config.ssr, config.ssrByEntries, ); - const ssrMode = getSSRMode(ssrConfig); - const inlineScript = getSSRInlineScript(ssrConfig); const loaderFailureMode = typeof ssrConfig === 'object' ? ssrConfig.loaderFailureMode : undefined; return { nonce, + useJsonScript, loaderContext, redirection: {}, htmlModifiers: [], @@ -138,7 +137,6 @@ function createSSRContext( }, reporter, mode: ssrMode, - inlineScript, onError, onTiming, loaderFailureMode, diff --git a/packages/runtime/plugin-runtime/src/core/server/stream/afterTemplate.ts b/packages/runtime/plugin-runtime/src/core/server/stream/afterTemplate.ts index bf3ed2357647..b4a1618500ea 100644 --- a/packages/runtime/plugin-runtime/src/core/server/stream/afterTemplate.ts +++ b/packages/runtime/plugin-runtime/src/core/server/stream/afterTemplate.ts @@ -6,7 +6,7 @@ import type { SSRContainer } from '../../types'; import { SSR_DATA_PLACEHOLDER } from '../constants'; import type { HandleRequestConfig } from '../requestHandler'; import { type BuildHtmlCb, type SSRConfig, buildHtml } from '../shared'; -import { attributesToString, getSSRInlineScript, safeReplace } from '../utils'; +import { attributesToString, safeReplace } from '../utils'; export type BuildShellAfterTemplateOptions = { runtimeContext: RuntimeContext; @@ -29,6 +29,7 @@ export function buildShellAfterTemplate( request, ssrConfig, nonce: config.nonce, + useJsonScript: config.useJsonScript, runtimeContext, renderLevel, }), @@ -62,9 +63,11 @@ function createReplaceSSRData(options: { runtimeContext: RuntimeContext; ssrConfig: SSRConfig; nonce?: string; + useJsonScript?: boolean; renderLevel: RenderLevel; }) { - const { runtimeContext, nonce, renderLevel, ssrConfig } = options; + const { runtimeContext, nonce, renderLevel, useJsonScript, ssrConfig } = + options; const { request, reporter } = runtimeContext.ssrContext!; @@ -102,16 +105,11 @@ function createReplaceSSRData(options: { renderLevel, }; const attrsStr = attributesToString({ nonce }); - - const inlineScript = getSSRInlineScript(ssrConfig); - const useInlineScript = inlineScript !== false; const serializeSSRData = serializeJson(ssrData); - const ssrDataScript = useInlineScript - ? ` - window._SSR_DATA = ${serializeSSRData} - ` - : ``; + const ssrDataScript = useJsonScript + ? `` + : `window._SSR_DATA = ${serializeSSRData}`; return (template: string) => safeReplace(template, SSR_DATA_PLACEHOLDER, ssrDataScript); diff --git a/packages/runtime/plugin-runtime/src/core/server/string/index.ts b/packages/runtime/plugin-runtime/src/core/server/string/index.ts index efb53f702156..3dd7ca2afc06 100644 --- a/packages/runtime/plugin-runtime/src/core/server/string/index.ts +++ b/packages/runtime/plugin-runtime/src/core/server/string/index.ts @@ -96,6 +96,7 @@ export const renderString: RenderString = async ( chunkSet, routerContext, nonce: config.nonce, + useJsonScript: config.useJsonScript, }), ]; diff --git a/packages/runtime/plugin-runtime/src/core/server/string/ssrData.ts b/packages/runtime/plugin-runtime/src/core/server/string/ssrData.ts index d62b2e07dafa..03e5a09af24f 100644 --- a/packages/runtime/plugin-runtime/src/core/server/string/ssrData.ts +++ b/packages/runtime/plugin-runtime/src/core/server/string/ssrData.ts @@ -4,11 +4,7 @@ import type { HeadersData } from '@modern-js/runtime-utils/universal/request'; import { ROUTER_DATA_JSON_ID, SSR_DATA_JSON_ID } from '../../constants'; import type { SSRContainer, SSRServerContext } from '../../types'; import type { SSRConfig } from '../shared'; -import { - attributesToString, - getSSRInlineScript, - serializeErrors, -} from '../utils'; +import { attributesToString, serializeErrors } from '../utils'; import type { ChunkSet, Collector } from './types'; export interface SSRDataCreatorOptions { @@ -19,6 +15,7 @@ export interface SSRDataCreatorOptions { ssrConfig?: SSRConfig; routerContext?: StaticHandlerContext; nonce?: string; + useJsonScript?: boolean; } export class SSRDataCollector implements Collector { @@ -86,22 +83,19 @@ export class SSRDataCollector implements Collector { ssrData: Record, routerData?: Record, ) { - const { nonce, ssrConfig } = this.#options; - const inlineScript = getSSRInlineScript(ssrConfig); - - const useInlineScript = inlineScript !== false; + const { nonce, useJsonScript = false } = this.#options; const serializeSSRData = serializeJson(ssrData); const attrsStr = attributesToString({ nonce }); - let ssrDataScripts = useInlineScript - ? `window._SSR_DATA = ${serializeSSRData}` - : ``; + let ssrDataScripts = useJsonScript + ? `` + : `window._SSR_DATA = ${serializeSSRData}`; if (routerData) { const serializedRouterData = serializeJson(routerData); - ssrDataScripts += useInlineScript - ? `\nwindow._ROUTER_DATA = ${serializedRouterData}` - : `\n`; + ssrDataScripts += useJsonScript + ? `\n` + : `\nwindow._ROUTER_DATA = ${serializedRouterData}`; } return ssrDataScripts; } diff --git a/packages/runtime/plugin-runtime/src/core/server/utils.ts b/packages/runtime/plugin-runtime/src/core/server/utils.ts index 8556d0c241b8..a2f028aba921 100644 --- a/packages/runtime/plugin-runtime/src/core/server/utils.ts +++ b/packages/runtime/plugin-runtime/src/core/server/utils.ts @@ -79,11 +79,3 @@ export function getSSRMode(ssrConfig?: SSRConfig): 'string' | 'stream' | false { return ssrConfig?.mode === 'stream' ? 'stream' : 'string'; } - -export function getSSRInlineScript(ssrConfig?: SSRConfig): boolean { - if (typeof ssrConfig === 'object') { - return ssrConfig.inlineScript === undefined ? true : ssrConfig.inlineScript; - } - - return true; -} diff --git a/packages/runtime/plugin-runtime/src/core/types.ts b/packages/runtime/plugin-runtime/src/core/types.ts index 39047be86450..313343e7c794 100644 --- a/packages/runtime/plugin-runtime/src/core/types.ts +++ b/packages/runtime/plugin-runtime/src/core/types.ts @@ -70,7 +70,7 @@ export type SSRServerContext = Pick< loaderFailureMode?: 'clientRender' | 'errorBoundary'; onError?: (e: unknown) => void; onTiming?: (name: string, dur: number) => void; - inlineScript?: boolean; + useJsonScript?: boolean; }; /* 通过 useRuntimeContext 获取的 SSRContext */ diff --git a/packages/runtime/plugin-runtime/src/router/runtime/DeferredDataScripts.node.tsx b/packages/runtime/plugin-runtime/src/router/runtime/DeferredDataScripts.node.tsx index fa3f0c9fb3d9..d5092a74e1d3 100644 --- a/packages/runtime/plugin-runtime/src/router/runtime/DeferredDataScripts.node.tsx +++ b/packages/runtime/plugin-runtime/src/router/runtime/DeferredDataScripts.node.tsx @@ -15,11 +15,11 @@ import { serializeErrors } from './utils'; */ const DeferredDataScripts = (props?: { nonce?: string; - inlineScript?: boolean; + useJsonScript?: boolean; context: StaticHandlerContext; }) => { const staticContext = props?.context; - const inlineScript = props?.inlineScript; + const useJsonScript = props?.useJsonScript; const hydratedRef = useRef(false); useEffect(() => { @@ -52,12 +52,14 @@ const DeferredDataScripts = (props?: { errors: serializeErrors(staticContext.errors), }; - const initialScript0 = inlineScript ? '' : `${serializeJson(_ROUTER_DATA)}`; - const initialScript1 = inlineScript - ? [`_ROUTER_DATA = ${serializeJson(_ROUTER_DATA)};`, modernInline].join( + const initialScript0 = useJsonScript + ? `${serializeJson(_ROUTER_DATA)}` + : ''; + const initialScript1 = useJsonScript + ? modernInline + : [`_ROUTER_DATA = ${serializeJson(_ROUTER_DATA)};`, modernInline].join( '\n', - ) - : modernInline; + ); const deferredDataScripts: JSX.Element[] = []; const initialScripts = Object.entries(activeDeferreds).map( diff --git a/packages/runtime/plugin-runtime/src/router/runtime/plugin.node.tsx b/packages/runtime/plugin-runtime/src/router/runtime/plugin.node.tsx index b6cc35ffa0fe..73e100e40751 100644 --- a/packages/runtime/plugin-runtime/src/router/runtime/plugin.node.tsx +++ b/packages/runtime/plugin-runtime/src/router/runtime/plugin.node.tsx @@ -166,7 +166,7 @@ export const routerPlugin = ( const context = useContext(RuntimeReactContext); const { remixRouter, routerContext, ssrContext } = context; - const { nonce, mode, inlineScript } = ssrContext!; + const { nonce, mode, useJsonScript } = ssrContext!; const routerWrapper = ( <> @@ -182,7 +182,7 @@ export const routerPlugin = ( )} {mode === 'stream' && JSX_SHELL_STREAM_END_MARK} diff --git a/packages/server/core/src/plugins/render/ssrRender.ts b/packages/server/core/src/plugins/render/ssrRender.ts index 9d5ea8babca2..088920c1e764 100644 --- a/packages/server/core/src/plugins/render/ssrRender.ts +++ b/packages/server/core/src/plugins/render/ssrRender.ts @@ -160,5 +160,6 @@ function createRequestHandlerConfig( enableInlineStyles: output?.enableInlineStyles, crossorigin: html?.crossorigin, scriptLoading: html?.scriptLoading, + useJsonScript: server?.useJsonScript, }; } diff --git a/packages/server/core/src/types/config/server.ts b/packages/server/core/src/types/config/server.ts index 0ef5ede1efd7..d93db409c691 100644 --- a/packages/server/core/src/types/config/server.ts +++ b/packages/server/core/src/types/config/server.ts @@ -36,10 +36,13 @@ export interface ServerUserConfig { ssrByEntries?: SSRByEntries; baseUrl?: string | string[]; port?: number; - enableMicroFrontendDebug?: boolean; watchOptions?: WatchOptions; compiler?: 'babel' | 'typescript'; - enableFrameworkExt?: boolean; + /** + * @description use json script tag instead of inline script + * @default false + */ + useJsonScript?: boolean; } export type ServerNormalizedConfig = ServerUserConfig; diff --git a/packages/server/core/src/types/requestHandler.ts b/packages/server/core/src/types/requestHandler.ts index c6fee3631880..e50fec86a308 100644 --- a/packages/server/core/src/types/requestHandler.ts +++ b/packages/server/core/src/types/requestHandler.ts @@ -19,6 +19,7 @@ export type RequestHandlerConfig = { enableInlineScripts?: boolean | RegExp; ssr?: ServerUserConfig['ssr']; ssrByEntries?: ServerUserConfig['ssrByEntries']; + useJsonScript?: ServerUserConfig['useJsonScript']; }; export type LoaderContext = Map; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 97f71ee9f2fa..1fce53c156bd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6848,6 +6848,37 @@ importers: specifier: ^5 version: 5.3.3 + tests/integration/server-json-script: + dependencies: + '@modern-js/runtime': + specifier: workspace:* + version: link:../../../packages/runtime/plugin-runtime + axios: + specifier: ^1.7.4 + version: 1.7.8(debug@4.3.7) + express: + specifier: ^4.17.2 + version: 4.21.1 + react: + specifier: ^18.3.1 + version: 18.3.1 + react-dom: + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) + devDependencies: + '@modern-js/app-tools': + specifier: workspace:* + version: link:../../../packages/solutions/app-tools + '@types/jest': + specifier: ^29 + version: 29.5.14 + '@types/node': + specifier: ^14 + version: 14.18.35 + jest: + specifier: ^29 + version: 29.5.0(@types/node@14.18.35)(ts-node@10.9.2(@swc/core@1.3.42)(@types/node@14.18.35)(typescript@5.6.3)) + tests/integration/server-prod: dependencies: '@modern-js/runtime': @@ -15555,9 +15586,6 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} @@ -15590,9 +15618,6 @@ packages: get-func-name@2.0.0: resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} - get-intrinsic@1.2.0: - resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} - get-intrinsic@1.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} @@ -15792,9 +15817,6 @@ packages: resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} engines: {node: '>=8'} - has-property-descriptors@1.0.0: - resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} - has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -29747,8 +29769,8 @@ snapshots: call-bind@1.0.2: dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.2.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 call-bind@1.0.7: dependencies: @@ -30680,7 +30702,7 @@ snapshots: define-properties@1.1.4: dependencies: - has-property-descriptors: 1.0.0 + has-property-descriptors: 1.0.2 object-keys: 1.1.1 defined@1.0.0: {} @@ -31559,7 +31581,7 @@ snapshots: extract-zip@2.0.1: dependencies: - debug: 4.3.4 + debug: 4.3.7(supports-color@5.5.0) get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -31945,8 +31967,6 @@ snapshots: fsevents@2.3.3: optional: true - function-bind@1.1.1: {} - function-bind@1.1.2: {} function.prototype.name@1.1.5: @@ -31990,12 +32010,6 @@ snapshots: get-func-name@2.0.0: {} - get-intrinsic@1.2.0: - dependencies: - function-bind: 1.1.2 - has: 1.0.3 - has-symbols: 1.0.3 - get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 @@ -32246,10 +32260,6 @@ snapshots: has-own-prop@2.0.0: {} - has-property-descriptors@1.0.0: - dependencies: - get-intrinsic: 1.2.4 - has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.0 diff --git a/tests/integration/server-json-script/modern.config.ts b/tests/integration/server-json-script/modern.config.ts new file mode 100644 index 000000000000..77fb66c86f4d --- /dev/null +++ b/tests/integration/server-json-script/modern.config.ts @@ -0,0 +1,12 @@ +import { applyBaseConfig } from '../../utils/applyBaseConfig'; + +export default applyBaseConfig({ + runtime: { + router: true, + state: false, + }, + server: { + ssr: true, + useJsonScript: true, + }, +}); diff --git a/tests/integration/server-json-script/package.json b/tests/integration/server-json-script/package.json new file mode 100644 index 000000000000..ad9978cd58ee --- /dev/null +++ b/tests/integration/server-json-script/package.json @@ -0,0 +1,31 @@ +{ + "name": "server-json-script", + "version": "2.9.0", + "private": true, + "scripts": { + "new": "modern new", + "reset": "rm -rf node_modules", + "dev": "modern dev", + "build": "modern build", + "serve": "modern serve", + "test": "jest", + "preview": "modern deploy --mode preview", + "deploy": "modern deploy" + }, + "engines": { + "node": ">=14.17.6" + }, + "dependencies": { + "@modern-js/runtime": "workspace:*", + "axios": "^1.7.4", + "express": "^4.17.2", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@modern-js/app-tools": "workspace:*", + "@types/jest": "^29", + "@types/node": "^14", + "jest": "^29" + } +} diff --git a/tests/integration/server-json-script/src/routes/layout.tsx b/tests/integration/server-json-script/src/routes/layout.tsx new file mode 100644 index 000000000000..5bc3d7c33409 --- /dev/null +++ b/tests/integration/server-json-script/src/routes/layout.tsx @@ -0,0 +1,9 @@ +import { Link, Outlet, useLoaderData } from '@modern-js/runtime/router'; + +export default function Layout() { + return ( +
+ +
+ ); +} diff --git a/tests/integration/server-json-script/src/routes/page.tsx b/tests/integration/server-json-script/src/routes/page.tsx new file mode 100644 index 000000000000..0dd15f8aa5cb --- /dev/null +++ b/tests/integration/server-json-script/src/routes/page.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function App() { + return
Hello Modern.js
; +} diff --git a/tests/integration/server-json-script/tests/index.test.ts b/tests/integration/server-json-script/tests/index.test.ts new file mode 100644 index 000000000000..2ed023c19482 --- /dev/null +++ b/tests/integration/server-json-script/tests/index.test.ts @@ -0,0 +1,48 @@ +import path from 'path'; +import puppeteer, { type Browser, type Page } from 'puppeteer'; +import { + getPort, + killApp, + launchApp, + launchOptions, +} from '../../../utils/modernTestUtils'; + +const appDir = path.resolve(__dirname, '../'); +let app: any; +let appPort: number; + +beforeAll(async () => { + appPort = await getPort(); +}); + +afterAll(async () => { + if (app) { + await killApp(app); + } +}); + +describe('test basic usage', () => { + jest.setTimeout(25000); + + test(`should start successfully`, async () => { + app = await launchApp(appDir, appPort, {}, {}); + const browser = await puppeteer.launch(launchOptions as any); + const page = await browser.newPage(); + await page.goto(`http://localhost:${appPort}`, { + waitUntil: ['networkidle0'], + }); + + const scriptType1 = await page.$eval('#__MODERN_ROUTER_DATA__', el => { + return el.getAttribute('type'); + }); + const scriptType2 = await page.$eval('#__MODERN_ROUTER_DATA__', el => { + return el.getAttribute('type'); + }); + + expect(scriptType1).toBe('application/json'); + expect(scriptType2).toBe('application/json'); + + await page.close(); + await browser.close(); + }); +}); diff --git a/tests/integration/server-json-script/tests/tsconfig.json b/tests/integration/server-json-script/tests/tsconfig.json new file mode 100644 index 000000000000..10f49432232c --- /dev/null +++ b/tests/integration/server-json-script/tests/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "@modern-js/tsconfig/base", + "compilerOptions": { + "declaration": true, + "jsx": "preserve", + "baseUrl": "./", + "emitDeclarationOnly": true, + "isolatedModules": true, + "paths": {}, + "types": ["node", "jest"] + } +} diff --git a/tests/integration/server-json-script/tsconfig.json b/tests/integration/server-json-script/tsconfig.json new file mode 100644 index 000000000000..6e9938432374 --- /dev/null +++ b/tests/integration/server-json-script/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@modern-js/tsconfig/base", + "compilerOptions": { + "declaration": false, + "types": ["jest", "node"], + "jsx": "preserve", + "baseUrl": "./", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src", "server", "modern.config.ts"] +} From 3d7f39f1c3f19b96c1c3de4d9bb16282e27db568 Mon Sep 17 00:00:00 2001 From: kongjiacong Date: Tue, 10 Dec 2024 14:18:10 +0800 Subject: [PATCH 2/3] docs: add changeset --- .changeset/eleven-otters-cry.md | 7 +++++++ .../document/main-doc/docs/en/configure/app/server/ssr.mdx | 2 -- .../document/main-doc/docs/zh/configure/app/server/ssr.mdx | 2 -- 3 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 .changeset/eleven-otters-cry.md diff --git a/.changeset/eleven-otters-cry.md b/.changeset/eleven-otters-cry.md new file mode 100644 index 000000000000..dc0db5b93744 --- /dev/null +++ b/.changeset/eleven-otters-cry.md @@ -0,0 +1,7 @@ +--- +'@modern-js/runtime': patch +'@modern-js/server-core': patch +--- + +feat: add server.useJsonScript , for instead ssr.inlineScript +feat: 添加 server.useJsonScript 配置,代替 ssr.inlineScript diff --git a/packages/document/main-doc/docs/en/configure/app/server/ssr.mdx b/packages/document/main-doc/docs/en/configure/app/server/ssr.mdx index 0e80b84b492a..d476d107cd09 100644 --- a/packages/document/main-doc/docs/en/configure/app/server/ssr.mdx +++ b/packages/document/main-doc/docs/en/configure/app/server/ssr.mdx @@ -29,7 +29,6 @@ When the value type is `Object`, the following properties can be configured: | ---------------- | ------------------------------------------------------------- | -------------------------------------- | ---------------------------------------------------------------------------- | | mode | `string` | `string` | which defaults to using `renderToString` for rendering. Configure `stream` to enable streaming rendering | | forceCSR | `boolean` | `false` | which is off by default for forcing CSR rendering. Configure `true` to force CSR by adding `?csr=true` or adding `x-modern-ssr-fallback` header when accessing the page | -| inlineScript | `boolean` | `true` | By default, SSR data is injected into HTML as inline scripts and assigned directly to global variables. Configure `false` to distribute JSON instead of assigning to global variables, this configuration doesn't work in Streaming SSR | | disablePrerender | `boolean` | `fasle` | To ensure compatibility with the old data request method (`useLoader`), by default, Modern.js performs pre-rendering of components.However, if developers want to reduce one rendering when there is no use of the useLoader API in your project, you can set the configuration `disablePrerender=true` | | unsafeHeaders | `string[]` | `[]` | For safety reasons, Modern.js does not add excessive content to SSR_DATA. Developers can use this configuration to specify the headers that need to be injected | | scriptLoading | `defer \| blocking \| module \| async` | `defer` | The configuration is the same as [html.scriptLoading](/configure/app/html/script-loading), supporting SSR injected script set to `async` loading. The priority is `ssr.scriptLoading` > `html.scriptLoading` | @@ -42,7 +41,6 @@ export default defineConfig({ ssr: { forceCSR: true, mode: 'stream', - inlineScript: false, unsafeHeaders: ['User-Agent'], scriptLoading: 'async', }, diff --git a/packages/document/main-doc/docs/zh/configure/app/server/ssr.mdx b/packages/document/main-doc/docs/zh/configure/app/server/ssr.mdx index f6214c70a2c5..bbb007e9a410 100644 --- a/packages/document/main-doc/docs/zh/configure/app/server/ssr.mdx +++ b/packages/document/main-doc/docs/zh/configure/app/server/ssr.mdx @@ -30,7 +30,6 @@ export default defineConfig({ | mode | `string` | `string` | 默认为使用 `renderToString` 渲染。配置为 `stream` 开启流式渲染 | | forceCSR | `boolean` | `false` | 默认关闭强制 CSR 渲染。配置为 `true` 后,在页面访问时添加 `?csr=true` 或添加请求头 `x-modern-ssr-fallback` 即可强制 CSR | | inlineScript | `boolean` | `true` | 默认情况下,SSR 的数据会以内联脚本的方式注入到 HTML 中,并且直接赋值给全局变量。配置为 `false` 后,会下发 JSON,而不是赋值给全局变量,Streaming SSR 下,该配置不会生效 | -| disablePrerender | `boolean` | `fasle` | 为了兼容旧数据请求方式 - `useLoader`, 默认情况下 Modern.js 会对组件进行一次预渲染即有两次渲染 | | unsafeHeaders | `string[]` | `[]` | 为了安全考虑,Modern.js 不会往 SSR_DATA 添加过多的内容。开发者可以通过该配置,对需要注入的 headers 进行配置 | | scriptLoading | `defer \| blocking \| module \| async` | `defer` | 配置同 [html.scriptLoading](/configure/app/html/script-loading),支持 ssr 注入的 script 设置为 async 加载方式。优先级为 `ssr.scriptLoading` > `html.scriptLoading` | | loaderFailureMode| `clientRender \| errorBoundary` | `errorBoundary` | 当 [data loader](/guides/basic-features/data/data-fetch.html#data-loader推荐) 中出错时,默认会渲染路由 [`Error`](/guides/basic-features/routes.html#错误处理) 组件,配置为 `'clientRender'` 时,有一个 data loader 抛错,就降级到客户端渲染,可以与 [Client Loader](/guides/basic-features/data/data-fetch.html#client-loader) 配合使用 | @@ -43,7 +42,6 @@ export default defineConfig({ forceCSR: true, mode: 'stream', inlineScript: false, - disablePrerender: true, unsafeHeaders: ['User-Agent'], scriptLoading: 'async', }, From de9145289e42fba9a5a8cde270d76e05bf1f9ff2 Mon Sep 17 00:00:00 2001 From: kongjiacong Date: Tue, 10 Dec 2024 16:46:17 +0800 Subject: [PATCH 3/3] chore: cr --- .../document/main-doc/docs/zh/configure/app/server/ssr.mdx | 4 ++-- packages/runtime/plugin-runtime/src/core/react/index.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/document/main-doc/docs/zh/configure/app/server/ssr.mdx b/packages/document/main-doc/docs/zh/configure/app/server/ssr.mdx index bbb007e9a410..d37d7e899a3d 100644 --- a/packages/document/main-doc/docs/zh/configure/app/server/ssr.mdx +++ b/packages/document/main-doc/docs/zh/configure/app/server/ssr.mdx @@ -29,7 +29,7 @@ export default defineConfig({ | ---------------- | ------------------------------------------------------------- | -------------------------------------- | ---------------------------------------------------------------------------- | | mode | `string` | `string` | 默认为使用 `renderToString` 渲染。配置为 `stream` 开启流式渲染 | | forceCSR | `boolean` | `false` | 默认关闭强制 CSR 渲染。配置为 `true` 后,在页面访问时添加 `?csr=true` 或添加请求头 `x-modern-ssr-fallback` 即可强制 CSR | -| inlineScript | `boolean` | `true` | 默认情况下,SSR 的数据会以内联脚本的方式注入到 HTML 中,并且直接赋值给全局变量。配置为 `false` 后,会下发 JSON,而不是赋值给全局变量,Streaming SSR 下,该配置不会生效 | +| disablePrerender | `boolean` | `fasle` | 为了兼容旧数据请求方式 - `useLoader`, 默认情况下 Modern.js 会对组件进行一次预渲染即有两次渲染 | | unsafeHeaders | `string[]` | `[]` | 为了安全考虑,Modern.js 不会往 SSR_DATA 添加过多的内容。开发者可以通过该配置,对需要注入的 headers 进行配置 | | scriptLoading | `defer \| blocking \| module \| async` | `defer` | 配置同 [html.scriptLoading](/configure/app/html/script-loading),支持 ssr 注入的 script 设置为 async 加载方式。优先级为 `ssr.scriptLoading` > `html.scriptLoading` | | loaderFailureMode| `clientRender \| errorBoundary` | `errorBoundary` | 当 [data loader](/guides/basic-features/data/data-fetch.html#data-loader推荐) 中出错时,默认会渲染路由 [`Error`](/guides/basic-features/routes.html#错误处理) 组件,配置为 `'clientRender'` 时,有一个 data loader 抛错,就降级到客户端渲染,可以与 [Client Loader](/guides/basic-features/data/data-fetch.html#client-loader) 配合使用 | @@ -41,7 +41,7 @@ export default defineConfig({ ssr: { forceCSR: true, mode: 'stream', - inlineScript: false, + disablePrerender: true, unsafeHeaders: ['User-Agent'], scriptLoading: 'async', }, diff --git a/packages/runtime/plugin-runtime/src/core/react/index.tsx b/packages/runtime/plugin-runtime/src/core/react/index.tsx index 10bd2719fa78..a25fcb317f65 100644 --- a/packages/runtime/plugin-runtime/src/core/react/index.tsx +++ b/packages/runtime/plugin-runtime/src/core/react/index.tsx @@ -9,7 +9,7 @@ export function createRoot(UserApp?: React.ComponentType | null) { const App = UserApp || getGlobalApp(); if (isBrowser()) { - // we should get data from HTMLElement when set server.useInline = false + // we should get data from HTMLElement when set server.useJsonScript = true window._SSR_DATA = window._SSR_DATA || parsedJSONFromElement(SSR_DATA_JSON_ID);