Skip to content

Commit

Permalink
Merge branch 'main' into canary-ci-2-fix-2
Browse files Browse the repository at this point in the history
  • Loading branch information
dai-shi committed Dec 14, 2024
2 parents 4ddfa5e + 4eb1bae commit 6a56265
Show file tree
Hide file tree
Showing 83 changed files with 533 additions and 1,931 deletions.
4 changes: 2 additions & 2 deletions docs/guides/stream-intercept.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ import streamInterceptor from './src/middleware/stream-interceptor';
export default {
// ...
middleware: () => [
import('waku/middleware/context'),
import('./src/middleware/themePreload.js'), // + this is the one we just added
import('waku/middleware/dev-server'),
import('waku/middleware/rsc'),
import('waku/middleware/ssr'),
import('waku/middleware/handler'),
],
};
```
Expand Down
58 changes: 21 additions & 37 deletions docs/minimal-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,29 @@ description: The minimal Waku API for library authors.

### Server API

To use React Server Components in Waku, you need to create an `entries.tsx` file in the project root directory with a `renderEntries` function that returns a server component module.
To use React Server Components in Waku, you need to create an `entries.tsx` file in the project root directory and `defineEntries` to handle server requests.

```tsx
import { defineEntries } from 'waku/server';
import { unstable_defineEntries as defineEntries } from 'waku/minimal/server';
import App from './components/App.js';

export default defineEntries(
// renderEntries
async (rscPath) => {
return {
App: <App name={rscPath || 'Waku'} />,
};
export default defineEntries({
handleRequest: async (input, { renderRsc, renderHtml }) => {
if (input.type === 'component') {
return renderRsc({ App: <App name={input.rscPath || 'Waku'} /> });
}
if (input.type === 'custom' && input.pathname === '/') {
return renderHtml({ App: <App name="Waku" /> }, <Slot id="App" />, '');
}
},
);
getBuildConfig: async () => [{ pathSpec: [], entries: [{ rscPath: '' }] }],
});
```

The `id` parameter is the ID of the React Server Component that you want to load on the server. You specify the RSC ID from the client.
Tips for experimenting:

- `input.type === 'custom'` condition can be omitted if you don't need SSR.
- `getBuildConfig` can return `[]` if you don't need to build anything.

### Client API

Expand All @@ -34,7 +40,7 @@ This file should be `./src/main.tsx`.

```tsx
import { createRoot } from 'react-dom/client';
import { Root, Slot } from 'waku/client';
import { Root, Slot } from 'waku/minimal/client';

const rootElement = (
<StrictMode>
Expand All @@ -61,30 +67,8 @@ const Component = () => {
};
```

### Additional Server API

In addition to the `renderEntries` function, you can also optionally specify `getBuildConfig` function in
`entries.tsx`.

```tsx
import { defineEntries } from 'waku/server';

export default defineEntries(
// renderEntries
async (rscPath) => {
return {
App: <App name={rscPath || 'Waku'} />,
};
},
// getBuildConfig
async () => {
return {
'/': {
entries: [['']],
},
};
},
);
```
### Examples

The `getBuildConfig` function is used for build-time optimization. It renders React Server Components during the build process to produce the output that will be sent to the client. Note that rendering here means to produce RSC payload not HTML content.
- [../examples/31_minimal](Minimal example)
- [../examples/34_functions](With server functions)
- [../examples/39_api](With custom API endpoints)
3 changes: 1 addition & 2 deletions docs/redirects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ export default {
import('waku/middleware/context'),
import('./src/middleware/redirects.js'),
import('waku/middleware/dev-server'),
import('waku/middleware/rsc'),
import('waku/middleware/ssr'),
import('waku/middleware/handler'),
],
} satisfies Config;
```
Expand Down
5 changes: 5 additions & 0 deletions e2e/21_create-pages_standalone.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ async function testRouterExample(page: Page, port: number) {
await page.goto(`http://localhost:${port}/foo`);
await expect(page.getByRole('heading', { name: 'Foo' })).toBeVisible();

await page.goto(`http://localhost:${port}/nested/baz`);
await expect(
page.getByRole('heading', { name: 'Nested Layout' }),
).toBeVisible();

const backgroundColor = await page.evaluate(() =>
window.getComputedStyle(document.body).getPropertyValue('background-color'),
);
Expand Down
3 changes: 1 addition & 2 deletions e2e/fixtures/broken-links/waku.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ export default {
import('waku/middleware/context'),
import('./src/redirects.js'),
import('waku/middleware/dev-server'),
import('waku/middleware/rsc'),
import('waku/middleware/ssr'),
import('waku/middleware/handler'),
],
};
10 changes: 4 additions & 6 deletions e2e/fixtures/rsc-basic/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { new_defineEntries } from 'waku/minimal/server';
import { unstable_defineEntries as defineEntries } from 'waku/minimal/server';

import App from './components/App.js';

const entries: ReturnType<typeof new_defineEntries> = new_defineEntries({
unstable_handleRequest: async (input, { renderRsc }) => {
const entries: ReturnType<typeof defineEntries> = defineEntries({
handleRequest: async (input, { renderRsc }) => {
if (input.type === 'component') {
return renderRsc({ App: <App name={input.rscPath || 'Waku'} /> });
}
Expand All @@ -12,9 +12,7 @@ const entries: ReturnType<typeof new_defineEntries> = new_defineEntries({
return renderRsc({ _value: value });
}
},
unstable_getBuildConfig: async () => [
{ pathSpec: [], entries: [{ rscPath: '' }] },
],
getBuildConfig: async () => [{ pathSpec: [], entries: [{ rscPath: '' }] }],
});

export default entries;
2 changes: 1 addition & 1 deletion e2e/fixtures/rsc-basic/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { Root, Slot } from 'waku/client';
import { Root, Slot } from 'waku/minimal/client';

const rootElement = (
<StrictMode>
Expand Down
10 changes: 4 additions & 6 deletions e2e/fixtures/rsc-css-modules/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { new_defineEntries } from 'waku/minimal/server';
import { unstable_defineEntries as defineEntries } from 'waku/minimal/server';

import App from './components/App.js';

const entries: ReturnType<typeof new_defineEntries> = new_defineEntries({
unstable_handleRequest: async (input, { renderRsc }) => {
const entries: ReturnType<typeof defineEntries> = defineEntries({
handleRequest: async (input, { renderRsc }) => {
if (input.type === 'component') {
return renderRsc({ App: <App name={input.rscPath || 'Waku'} /> });
}
Expand All @@ -12,9 +12,7 @@ const entries: ReturnType<typeof new_defineEntries> = new_defineEntries({
return renderRsc({ _value: value });
}
},
unstable_getBuildConfig: async () => [
{ pathSpec: [], entries: [{ rscPath: '' }] },
],
getBuildConfig: async () => [{ pathSpec: [], entries: [{ rscPath: '' }] }],
});

export default entries;
2 changes: 1 addition & 1 deletion e2e/fixtures/rsc-css-modules/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { Root, Slot } from 'waku/client';
import { Root, Slot } from 'waku/minimal/client';

const rootElement = (
<StrictMode>
Expand Down
19 changes: 17 additions & 2 deletions e2e/fixtures/rsc-router/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ReactNode } from 'react';
import { unstable_defineRouter } from 'waku/router/server';
import { unstable_defineRouter as defineRouter } from 'waku/router/server';
import { Slot, Children } from 'waku/minimal/client';
import { unstable_defineEntries as defineEntries } from 'waku/minimal/server';

import Layout from './routes/layout.js';
import Page from './routes/page.js';
Expand All @@ -12,7 +13,7 @@ const PATH_PAGE: Record<string, ReactNode> = {
'/foo': <FooPage />,
};

export default unstable_defineRouter({
const router: ReturnType<typeof defineRouter> = defineRouter({
getPathConfig: async () =>
STATIC_PATHS.map((path) => ({
pattern: `^${path}$`,
Expand Down Expand Up @@ -60,3 +61,17 @@ export default unstable_defineRouter({
};
},
});

const entries: ReturnType<typeof defineEntries> = defineEntries({
handleRequest: async (input, utils) => {
if (input.type === 'custom') {
return null; // no ssr
}
return router.handleRequest(input, utils);
},
getBuildConfig: (utils) => {
return router.getBuildConfig(utils);
},
});

export default entries;
8 changes: 0 additions & 8 deletions e2e/fixtures/rsc-router/waku.config.ts

This file was deleted.

10 changes: 4 additions & 6 deletions e2e/fixtures/ssr-basic/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { new_defineEntries } from 'waku/minimal/server';
import { unstable_defineEntries as defineEntries } from 'waku/minimal/server';
import { Slot } from 'waku/minimal/client';

import App from './components/App.js';

const entries: ReturnType<typeof new_defineEntries> = new_defineEntries({
unstable_handleRequest: async (input, { renderRsc, renderHtml }) => {
const entries: ReturnType<typeof defineEntries> = defineEntries({
handleRequest: async (input, { renderRsc, renderHtml }) => {
if (input.type === 'component') {
return renderRsc({ App: <App name={input.rscPath || 'Waku'} /> });
}
Expand All @@ -16,9 +16,7 @@ const entries: ReturnType<typeof new_defineEntries> = new_defineEntries({
return renderHtml({ App: <App name="Waku" /> }, <Slot id="App" />, '');
}
},
unstable_getBuildConfig: async () => [
{ pathSpec: [], entries: [{ rscPath: '' }] },
],
getBuildConfig: async () => [{ pathSpec: [], entries: [{ rscPath: '' }] }],
});

export default entries;
2 changes: 1 addition & 1 deletion e2e/fixtures/ssr-basic/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StrictMode } from 'react';
import { createRoot, hydrateRoot } from 'react-dom/client';
import { Root, Slot } from 'waku/client';
import { Root, Slot } from 'waku/minimal/client';

const rootElement = (
<StrictMode>
Expand Down
11 changes: 0 additions & 11 deletions e2e/fixtures/ssr-basic/waku.config.ts

This file was deleted.

3 changes: 1 addition & 2 deletions e2e/fixtures/ssr-catch-error/waku.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ export default {
import('waku/middleware/context'),
import('waku/middleware/dev-server'),
import('./src/middleware/validator.js'),
import('waku/middleware/rsc'),
import('waku/middleware/ssr'),
import('waku/middleware/handler'),
],
/**
* Base path for HTTP requests to indicate RSC requests.
Expand Down
10 changes: 4 additions & 6 deletions e2e/fixtures/ssr-context-provider/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { new_defineEntries } from 'waku/minimal/server';
import { unstable_defineEntries as defineEntries } from 'waku/minimal/server';
import { Slot } from 'waku/minimal/client';

import App from './components/app.js';

const entries: ReturnType<typeof new_defineEntries> = new_defineEntries({
unstable_handleRequest: async (input, { renderRsc, renderHtml }) => {
const entries: ReturnType<typeof defineEntries> = defineEntries({
handleRequest: async (input, { renderRsc, renderHtml }) => {
if (input.type === 'component') {
return renderRsc({ App: <App /> });
}
Expand All @@ -16,9 +16,7 @@ const entries: ReturnType<typeof new_defineEntries> = new_defineEntries({
return renderHtml({ App: <App /> }, <Slot id="App" />, '');
}
},
unstable_getBuildConfig: async () => [
{ pathSpec: [], entries: [{ rscPath: '' }] },
],
getBuildConfig: async () => [{ pathSpec: [], entries: [{ rscPath: '' }] }],
});

export default entries;
2 changes: 1 addition & 1 deletion e2e/fixtures/ssr-context-provider/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StrictMode } from 'react';
import { createRoot, hydrateRoot } from 'react-dom/client';
import { Root, Slot } from 'waku/client';
import { Root, Slot } from 'waku/minimal/client';

const rootElement = (
<StrictMode>
Expand Down
11 changes: 0 additions & 11 deletions e2e/fixtures/ssr-context-provider/waku.config.ts

This file was deleted.

10 changes: 4 additions & 6 deletions e2e/fixtures/ssr-swr/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { new_defineEntries } from 'waku/minimal/server';
import { unstable_defineEntries as defineEntries } from 'waku/minimal/server';
import { Slot } from 'waku/minimal/client';

import App from './components/App.js';

const entries: ReturnType<typeof new_defineEntries> = new_defineEntries({
unstable_handleRequest: async (input, { renderRsc, renderHtml }) => {
const entries: ReturnType<typeof defineEntries> = defineEntries({
handleRequest: async (input, { renderRsc, renderHtml }) => {
if (input.type === 'component') {
return renderRsc({ App: <App name={input.rscPath || 'Waku'} /> });
}
Expand All @@ -16,9 +16,7 @@ const entries: ReturnType<typeof new_defineEntries> = new_defineEntries({
return renderHtml({ App: <App name="Waku" /> }, <Slot id="App" />, '');
}
},
unstable_getBuildConfig: async () => [
{ pathSpec: [], entries: [{ rscPath: '' }] },
],
getBuildConfig: async () => [{ pathSpec: [], entries: [{ rscPath: '' }] }],
});

export default entries;
2 changes: 1 addition & 1 deletion e2e/fixtures/ssr-swr/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StrictMode } from 'react';
import { createRoot, hydrateRoot } from 'react-dom/client';
import { Root, Slot } from 'waku/client';
import { Root, Slot } from 'waku/minimal/client';

const rootElement = (
<StrictMode>
Expand Down
11 changes: 0 additions & 11 deletions e2e/fixtures/ssr-swr/waku.config.ts

This file was deleted.

Loading

0 comments on commit 6a56265

Please sign in to comment.