Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: keep server assets on server build #1258

Merged
merged 4 commits into from
Feb 22, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions e2e/fixtures/rsc-asset/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "rsc-basic",
"version": "0.1.0",
"type": "module",
"private": true,
"scripts": {
"dev": "waku dev",
"build": "waku build",
"start": "waku start"
},
"dependencies": {
"react": "19.0.0",
"react-dom": "19.0.0",
"react-server-dom-webpack": "19.0.0",
"waku": "workspace:*"
},
"devDependencies": {
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"typescript": "^5.7.3",
"vite": "6.1.0"
}
}
31 changes: 31 additions & 0 deletions e2e/fixtures/rsc-asset/src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import fs from 'node:fs';
import testClientTxtUrl from './test-client.txt?no-inline';

Check failure on line 2 in e2e/fixtures/rsc-asset/src/components/App.tsx

View workflow job for this annotation

GitHub Actions / Test on (Node 20.8.0)

Cannot find module './test-client.txt?no-inline' or its corresponding type declarations.

Check failure on line 2 in e2e/fixtures/rsc-asset/src/components/App.tsx

View workflow job for this annotation

GitHub Actions / Test on (Node 18.17.0)

Cannot find module './test-client.txt?no-inline' or its corresponding type declarations.

Check failure on line 2 in e2e/fixtures/rsc-asset/src/components/App.tsx

View workflow job for this annotation

GitHub Actions / Test on (Node 22.7.0)

Cannot find module './test-client.txt?no-inline' or its corresponding type declarations.

const App = (_: { name: string }) => {
// vite doesn't handle `new URL` for ssr,
// so this is handled by a custom plugin in waku.config.ts
const testServerTxtUrl = new URL('./test-server.txt', import.meta.url);

return (
<html>
<head>
<title>e2e-rsc-asset</title>
</head>
<body>
<main>
<div>
client asset:{' '}
<a href={testClientTxtUrl} data-testid="client-link">
{testClientTxtUrl}
</a>
</div>
<div data-testid="server-file">
server asset: {fs.readFileSync(testServerTxtUrl, 'utf-8')}
</div>
</main>
</body>
</html>
);
};

export default App;
1 change: 1 addition & 0 deletions e2e/fixtures/rsc-asset/src/components/test-client.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test-client-ok
1 change: 1 addition & 0 deletions e2e/fixtures/rsc-asset/src/components/test-server.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test-server-ok
18 changes: 18 additions & 0 deletions e2e/fixtures/rsc-asset/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { unstable_defineEntries as defineEntries } from 'waku/minimal/server';

Check failure on line 1 in e2e/fixtures/rsc-asset/src/entries.tsx

View workflow job for this annotation

GitHub Actions / Test on (Node 20.8.0)

File '/home/runner/work/waku/waku/packages/waku/src/minimal/server.ts' is not listed within the file list of project '/home/runner/work/waku/waku/tsconfig.e2e.json'. Projects must list all files or use an 'include' pattern.

Check failure on line 1 in e2e/fixtures/rsc-asset/src/entries.tsx

View workflow job for this annotation

GitHub Actions / Test on (Node 18.17.0)

File '/home/runner/work/waku/waku/packages/waku/src/minimal/server.ts' is not listed within the file list of project '/home/runner/work/waku/waku/tsconfig.e2e.json'. Projects must list all files or use an 'include' pattern.

Check failure on line 1 in e2e/fixtures/rsc-asset/src/entries.tsx

View workflow job for this annotation

GitHub Actions / Test on (Node 22.7.0)

File '/home/runner/work/waku/waku/packages/waku/src/minimal/server.ts' is not listed within the file list of project '/home/runner/work/waku/waku/tsconfig.e2e.json'. Projects must list all files or use an 'include' pattern.

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

const entries: ReturnType<typeof defineEntries> = defineEntries({
handleRequest: async (input, { renderRsc }) => {
if (input.type === 'component') {
return renderRsc({ App: <App name={input.rscPath || 'Waku'} /> });
}
if (input.type === 'function') {
const value = await input.fn(...input.args);
return renderRsc({ _value: value });
}
},
handleBuild: () => null,
});

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

Check failure on line 3 in e2e/fixtures/rsc-asset/src/main.tsx

View workflow job for this annotation

GitHub Actions / Test on (Node 20.8.0)

File '/home/runner/work/waku/waku/packages/waku/src/minimal/client.ts' is not listed within the file list of project '/home/runner/work/waku/waku/tsconfig.e2e.json'. Projects must list all files or use an 'include' pattern.

Check failure on line 3 in e2e/fixtures/rsc-asset/src/main.tsx

View workflow job for this annotation

GitHub Actions / Test on (Node 18.17.0)

File '/home/runner/work/waku/waku/packages/waku/src/minimal/client.ts' is not listed within the file list of project '/home/runner/work/waku/waku/tsconfig.e2e.json'. Projects must list all files or use an 'include' pattern.

Check failure on line 3 in e2e/fixtures/rsc-asset/src/main.tsx

View workflow job for this annotation

GitHub Actions / Test on (Node 22.7.0)

File '/home/runner/work/waku/waku/packages/waku/src/minimal/client.ts' is not listed within the file list of project '/home/runner/work/waku/waku/tsconfig.e2e.json'. Projects must list all files or use an 'include' pattern.

const rootElement = (
<StrictMode>
<Root>
<Slot id="App" />
</Root>
</StrictMode>
);

createRoot(document as any).render(rootElement);
17 changes: 17 additions & 0 deletions e2e/fixtures/rsc-asset/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"strict": true,
"target": "esnext",
"downlevelIteration": true,
"esModuleInterop": true,
"module": "nodenext",
"skipLibCheck": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"types": ["react/experimental", "vite/client"],
"jsx": "react-jsx",
"outDir": "./dist",
"composite": true
},
"include": ["./src", "./waku.config.ts"]
}
37 changes: 37 additions & 0 deletions e2e/fixtures/rsc-asset/waku.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { defineConfig } from 'waku/config';

Check failure on line 1 in e2e/fixtures/rsc-asset/waku.config.ts

View workflow job for this annotation

GitHub Actions / Test on (Node 20.8.0)

File '/home/runner/work/waku/waku/packages/waku/src/config.ts' is not listed within the file list of project '/home/runner/work/waku/waku/tsconfig.e2e.json'. Projects must list all files or use an 'include' pattern.

Check failure on line 1 in e2e/fixtures/rsc-asset/waku.config.ts

View workflow job for this annotation

GitHub Actions / Test on (Node 18.17.0)

File '/home/runner/work/waku/waku/packages/waku/src/config.ts' is not listed within the file list of project '/home/runner/work/waku/waku/tsconfig.e2e.json'. Projects must list all files or use an 'include' pattern.

Check failure on line 1 in e2e/fixtures/rsc-asset/waku.config.ts

View workflow job for this annotation

GitHub Actions / Test on (Node 22.7.0)

File '/home/runner/work/waku/waku/packages/waku/src/config.ts' is not listed within the file list of project '/home/runner/work/waku/waku/tsconfig.e2e.json'. Projects must list all files or use an 'include' pattern.
import type { Plugin } from 'vite';
import path from 'node:path';
import fs from 'node:fs';

export default defineConfig({
unstable_viteConfigs: {
'build-server': () => ({
plugins: [importMetaUrlServerPlugin()],
}),
},
});

// emit asset and rewrite `new URL("./xxx", import.meta.url)` syntax for build.
function importMetaUrlServerPlugin(): Plugin {
// https://github.com/vitejs/vite/blob/0f56e1724162df76fffd5508148db118767ebe32/packages/vite/src/node/plugins/assetImportMetaUrl.ts#L51-L52
const assetImportMetaUrlRE =
/\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*(?:,\s*)?\)/dg;

return {
name: 'test-server-asset',
transform(code, id) {
return code.replace(assetImportMetaUrlRE, (s, match) => {
const absPath = path.resolve(path.dirname(id), match.slice(1, -1));
if (fs.existsSync(absPath)) {
const referenceId = this.emitFile({
type: 'asset',
name: path.basename(absPath),
source: new Uint8Array(fs.readFileSync(absPath)),
});
return `new URL(import.meta.ROLLUP_FILE_URL_${referenceId})`;
}
return s;
});
},
};
}
31 changes: 31 additions & 0 deletions e2e/rsc-asset.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { expect } from '@playwright/test';

import { test, prepareNormalSetup } from './utils.js';

const startApp = prepareNormalSetup('rsc-asset');

for (const mode of ['DEV', 'PRD'] as const) {
test.describe(`rsc-asset: ${mode}`, () => {
let port: number;
let stopApp: () => Promise<void>;
test.beforeAll(async () => {
({ port, stopApp } = await startApp(mode));
});
test.afterAll(async () => {
await stopApp();
});

test('basic', async ({ page }) => {
await page.goto(`http://localhost:${port}/`);

// server asset
await expect(page.getByTestId('server-file')).toContainText(
'server asset: test-server-ok',
);

// client asset
await page.getByTestId('client-link').click();
await page.getByText('test-client-ok').click();
});
});
}
4 changes: 2 additions & 2 deletions packages/waku/src/lib/builder/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ import {
import { extendViteConfig } from '../utils/vite-config.js';
import {
appendFile,
copyFile,
createWriteStream,
existsSync,
mkdir,
readdir,
readFile,
rename,
unlink,
writeFile,
} from '../utils/node-fs.js';
Expand Down Expand Up @@ -441,7 +441,7 @@ const buildClientBundle = async (
for (const nonJsAsset of nonJsAssets) {
const from = joinPath(rootDir, config.distDir, nonJsAsset);
const to = joinPath(rootDir, config.distDir, DIST_PUBLIC, nonJsAsset);
await rename(from, to);
await copyFile(from, to);
}
return clientBuildOutput;
};
Expand Down
28 changes: 28 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading