Skip to content

Commit

Permalink
Merge branch 'main' into chore/renovate
Browse files Browse the repository at this point in the history
  • Loading branch information
caohuilin authored Sep 24, 2024
2 parents 015f632 + 0a31d31 commit f844ac5
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 3 deletions.
8 changes: 8 additions & 0 deletions .changeset/violet-islands-sniff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@modern-js/runtime': minor
'@modern-js/server-core': minor
---

feat: support <NoSSRCache> Component, only use ssr.mode='string'

feat: 支持 <NoSSRCache> 组件, 仅在 ssr.mode 为 'string'的时候生效
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
title: NoSSRCache
---
# NoSSRCache

With the NoSSRCache component, Modern.js does not cache the server-side rendering (SSR) results of the current page.

:::note
This component is currently only available if `ssr.mode` is `string`.
:::

## Usage

```tsx
import { NoSSRCache } from '@modern-js/runtime/ssr';

export default () => {
return (
<div>
<NoSSRCache />
...
</div>
);
}
```

## Example

In the following code, after using `useLoaderData` to fetch data, the current page is cached or not based on the data fetched. For this case, use `NoSSRCache`:

```tsx
import { useLoaderData } from '@modern-js/runtim/router';
import { NoSSRCache } from '@modern-js/runtime/ssr';

function User() {
const { data } = useLoaderData();
return (
<div>
{ !data ? <NoSSRCache /> : null }
...
</div>
);
}
```

## Scene

This can be used if you need to decide whether the current page needs to cache the server-side rendering (SSR) results based on the current page fetching the data (e.g., whether the request was successful or whether a field exists in the returned result).
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
title: NoSSRCache
---
# NoSSRCache

使用了 NoSSRCache 组件后,Modern.js 不会将当前页面的服务器端渲染(SSR)结果进行缓存。

:::note
该组件目前仅在 `ssr.mode``string` 的情况可以使用。
:::

## 使用姿势

```tsx
import { NoSSRCache } from '@modern-js/runtime/ssr';

export default () => {
return (
<div>
<NoSSRCache />
...
</div>
);
}
```

## 示例

下列代码中,使用 `useLoaderData` 获取数据后,根据请求数据的结果决定是否缓存当前页面的服务端渲染结果。针对这种情况可以使用 `NoSSRCache` 组件:

```tsx
import { useLoaderData } from '@modern-js/runtim/router';
import { NoSSRCache } from '@modern-js/runtime/ssr';

function User() {
const { data } = useLoaderData();
return (
<div>
{ !data ? <NoSSRCache /> : null }
...
</div>
);
}
```

## 使用场景

如果需要根据当前页面获取数据的情况(比如是否请求成功或者返回结果中是否存在某个字段),决定是否需要将当前页面的服务端渲染(SSR)结果进行缓存,则可以使用这种方式来解决。
2 changes: 1 addition & 1 deletion packages/runtime/plugin-runtime/src/core/server/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Plugin } from '../plugin';

// react component
export { PreRender, NoSSR } from './react';
export { PreRender, NoSSR, NoSSRCache } from './react';

export const ssr = (_config: any): Plugin => ({
name: '@modern-js/plugin-ssr',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { PreRender } from './prerender';
export { NoSSR } from './nossr';
export { NoSSRCache } from './no-ssr-cache';
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import { Helmet } from '../../../../exports/head';

export const NoSSRCache = () => {
return (
<Helmet>
<meta name="no-ssr-cache" />
</Helmet>
);
};
6 changes: 4 additions & 2 deletions packages/server/core/src/plugins/render/ssrCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface CacheStruct {
}

const ZERO_RENDER_LEVEL = /"renderLevel":0/;
const NO_SSR_CACHE = /<meta\s+[^>]*name=["']no-ssr-cache["'][^>]*>/i;

export type CacheStatus = 'hit' | 'stale' | 'expired' | 'miss';

Expand Down Expand Up @@ -53,8 +54,9 @@ async function processCache({
const push = () =>
reader.read().then(({ done, value }) => {
if (done) {
const match = ZERO_RENDER_LEVEL.test(html);
// We should not cache the html, if we can match the html is downgrading.
const match = ZERO_RENDER_LEVEL.test(html) || NO_SSR_CACHE.test(html);
// case 1: We should not cache the html, if we can match the html is downgrading.
// case 2: We should not cache the html, if the user's code contains <NoSSRCache>.
if (match) {
writer.close();
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Outlet } from '@modern-js/runtime/router';
import { NoSSRCache } from '@modern-js/runtime/ssr';

export default function Layout() {
return (
<div>
No SSR Cache layout
<NoSSRCache />
{<Outlet />}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Outlet } from '@modern-js/runtime/router';

export default function Page() {
return (
<div>
No SSR Cache
<Outlet />
</div>
);
}
15 changes: 15 additions & 0 deletions tests/integration/ssr/tests/base.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,19 @@ describe('Traditional SSR', () => {
const { headers } = response;
expect(Boolean(headers['x-render-cache'])).toBeTruthy();
});

test('no ssr cache', async () => {
await page.goto(`http://localhost:${appPort}/no-ssr-cache`, {
waitUntil: ['networkidle0'],
});
const content = await page.content();
const result = content.match(/count:(\d+)/)![0];

// twice visit, because the no-ssr-cache, the count is different.
await page.goto(`http://localhost:${appPort}/no-ssr-cache`, {
waitUntil: ['networkidle0'],
});
const content1 = await page.content();
expect(content1).not.toMatch(result);
});
});

0 comments on commit f844ac5

Please sign in to comment.