Skip to content

Commit

Permalink
feat: ssr add more context (#5032)
Browse files Browse the repository at this point in the history
  • Loading branch information
GiveMe-A-Name authored Dec 20, 2023
1 parent 5e9a6a9 commit ae22b74
Show file tree
Hide file tree
Showing 12 changed files with 56 additions and 25 deletions.
7 changes: 7 additions & 0 deletions .changeset/tender-cups-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@modern-js/runtime': patch
'@modern-js/server-core': patch
---

feat: support ssr pass more context
feat: 支持传递更多的 ssr context
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ When the value type is `Object`, the following properties can be configured:
- `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.
- `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.

```ts title="modern.config.ts"
export default defineConfig({
Expand All @@ -38,6 +39,7 @@ export default defineConfig({
forceCSR: true,
mode: 'stream',
inlineScript: false,
unsafeHeaders: ['User-Agent'],
},
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default defineConfig({
- `inlineScript``boolean = true`,默认情况下,SSR 的数据会以内联脚本的方式注入到 HTML 中,并且直接赋值给全局变量。配置为 `false` 后,会下发 JSON,而不是赋值给全局变量。
- `disablePrerender`: `boolean = fasle`, 为了兼容旧数据请求方式 - `useLoader`, 默认情况下 Modern.js 会对组件进行一次预渲染即有两次渲染。
开发者在保证项目中没有使用 useLoader Api 情况下, 可通过配置 `disablePrerender=true`来减少一次渲染。
- `unsafeHeaders`: `string[] = []`, 为了安全考虑,Modern.js 不会往 SSR_DATA 添加过多的内容。开发者可以通过该配置,对需要注入的 headers 进行配置。

```ts title="modern.config.ts"
export default defineConfig({
Expand All @@ -39,6 +40,7 @@ export default defineConfig({
mode: 'stream',
inlineScript: false,
disablePrerender: true,
unsafeHeaders: ['User-Agent'],
},
},
});
Expand Down
5 changes: 5 additions & 0 deletions packages/runtime/plugin-runtime/src/ssr/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ export const ssrPlugin = (): CliPlugin<AppTools> => ({
typeof config.server?.ssr === 'object'
? Boolean(config.server.ssr.disablePrerender)
: false;
const unsafeHeaders =
typeof config.server?.ssr === 'object'
? config.server.ssr.unsafeHeaders
: undefined;

plugins.push({
name: PLUGIN_IDENTIFIER,
Expand All @@ -224,6 +228,7 @@ export const ssrPlugin = (): CliPlugin<AppTools> => ({
typeof enableInlineStyles === 'function'
? undefined
: enableInlineStyles,
unsafeHeaders,
}),
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
ModernSSRReactComponent,
SSRPluginConfig,
SSRServerContext,
RenderResult,
} from '../types';
import prefetch from '../../prefetch';
import { ROUTER_DATA_JSON_ID, SSR_DATA_JSON_ID } from '../constants';
Expand All @@ -26,7 +27,6 @@ import {
createReplaceHtml,
createReplaceSSRDataScript,
} from './buildHtml';
import { RenderResult } from './type';

type EntryOptions = {
ctx: SSRServerContext;
Expand All @@ -39,11 +39,20 @@ const buildTemplateData = (
data: Record<string, any>,
renderLevel: RenderLevel,
tracker: SSRTracker,
config: SSRPluginConfig,
) => {
const { request, enableUnsafeCtx } = context;
const unsafeContext = {
headers: request.headers,
};
const { request } = context;
const { unsafeHeaders } = config;

const headers = unsafeHeaders
? Object.fromEntries(
Object.entries(request.headers).filter(([key, _]) => {
return unsafeHeaders
?.map(header => header.toLowerCase())
?.includes(key.toLowerCase());
}),
)
: undefined;

return {
data,
Expand All @@ -54,7 +63,7 @@ const buildTemplateData = (
pathname: request.pathname,
host: request.host,
url: request.url,
...(enableUnsafeCtx ? unsafeContext : {}),
headers,
},
reporter: {
sessionId: tracker.sessionId,
Expand Down Expand Up @@ -142,6 +151,7 @@ export default class Entry {
prefetchData,
this.result.renderLevel,
this.tracker,
this.pluginConfig,
);
const ssrDataScripts = this.getSSRDataScript(templateData, routerData);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { type ChunkAsset, ChunkExtractor } from '@loadable/server';
import { ReactElement } from 'react';
import { attributesToString } from '../utils';
import { SSRPluginConfig } from '../types';
import { RenderResult } from './type';
import { SSRPluginConfig, RenderResult } from '../types';
import type { Collector } from './render';

const extname = (uri: string): string => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ServerStyleSheet } from 'styled-components';
import { ReactElement } from 'react';
import type { RenderResult } from './type';
import type { RenderResult } from '../types';
import type { Collector } from './render';

class StyledCollector implements Collector {
Expand Down

This file was deleted.

19 changes: 17 additions & 2 deletions packages/runtime/plugin-runtime/src/ssr/serverRender/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
import { ServerUserConfig } from '@modern-js/app-tools';
import type { BaseSSRServerContext } from '@modern-js/types';
import type { RuntimeContext } from '../../core';
import { RenderLevel } from './renderToString/type';
import type { BuildHtmlCb } from './renderToString/buildHtml';
import type { SSRTracker } from './tracker';

export enum RenderLevel {
CLIENT_RENDER,
SERVER_PREFETCH,
SERVER_RENDER,
}

export type RenderResult = {
renderLevel: RenderLevel;
html?: string;
chunksMap: {
js: string;
css: string;
};
};

export type SSRServerContext = BaseSSRServerContext & {
request: BaseSSRServerContext['request'] & {
userAgent: string;
Expand All @@ -15,7 +29,7 @@ export type SSRServerContext = BaseSSRServerContext & {
tracker: SSRTracker;
};
export type ModernSSRReactComponent = React.ComponentType<any>;
export { RuntimeContext, RenderLevel };
export { RuntimeContext };

export type SSRPluginConfig = {
crossorigin?: boolean | 'anonymous' | 'use-credentials';
Expand All @@ -24,6 +38,7 @@ export type SSRPluginConfig = {
enableInlineScripts?: boolean | RegExp;
disablePrerender?: boolean;
chunkLoadingGlobal?: string;
unsafeHeaders?: string[];
} & Exclude<ServerUserConfig['ssr'], boolean>;

export type ServerRenderOptions = {
Expand Down
1 change: 1 addition & 0 deletions packages/server/core/src/types/config/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export type SSR =
preload?: boolean | SSRPreload;
inlineScript?: boolean;
disablePrerender?: boolean;
unsafeHeaders?: string[];
};

export type SSRByEntries = Record<string, SSR>;
Expand Down
1 change: 1 addition & 0 deletions tests/integration/ssr/fixtures/base/modern.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default applyBaseConfig({
server: {
ssr: {
disablePrerender: true,
unsafeHeaders: ['Host'],
},
},
tools: {
Expand Down
3 changes: 3 additions & 0 deletions tests/integration/ssr/tests/base.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ async function basicUsage(page: Page, appPort: number) {
waitUntil: ['networkidle0'],
});
await (expect(page) as any).toMatchTextContent('user1-18');

const content = await page.content();
await (expect(content) as any).toMatch('"headers":{"host":');
}

async function errorThrown(page: Page, appPort: number) {
Expand Down

0 comments on commit ae22b74

Please sign in to comment.