Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
Aslemammad committed Dec 9, 2023
1 parent 096e02f commit 09a2707
Show file tree
Hide file tree
Showing 17 changed files with 1,221 additions and 88 deletions.
37 changes: 37 additions & 0 deletions examples/12_css/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Waku example</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
@keyframes spinner {
to {
transform: rotate(360deg);
}
}
.spinner {
width: 36px;
height: 36px;
margin: auto;
border: 2px solid #ddd;
border-top-color: #222;
border-radius: 50%;
animation: spinner 1s linear infinite;
}
#root > .spinner {
margin-top: calc(50% - 18px);
}
</style>
</head>
<body>
<!--placeholder1-->
<div id="root">
<div class="spinner"></div>
</div>
<!--/placeholder1-->
<script src="/src/main.tsx" async type="module"></script>
<!--placeholder2-->
<!--/placeholder2-->
</body>
</html>
29 changes: 29 additions & 0 deletions examples/12_css/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "waku-example",
"version": "0.1.0",
"type": "module",
"private": true,
"scripts": {
"dev": "waku dev --with-ssr",
"build": "waku build --with-ssr",
"start": "waku start --with-ssr"
},
"dependencies": {
"@hono/node-server": "^1.2.2",
"hono": "^3.10.0",
"react": "18.3.0-canary-6c7b41da3-20231123",
"react-dom": "18.3.0-canary-6c7b41da3-20231123",
"react-server-dom-webpack": "18.3.0-canary-6c7b41da3-20231123",
"waku": "0.17.1"
},
"devDependencies": {
"@swc/core": "1.3.96",
"@types/react": "^18.2.37",
"@types/react-dom": "^18.2.15",
"@vanilla-extract/css": "^1.14.0",
"@vanilla-extract/vite-plugin": "^3.9.2",
"@vitejs/plugin-react": "4.2.0",
"typescript": "^5.2.2",
"vite": "5.0.4"
}
}
3 changes: 3 additions & 0 deletions examples/12_css/src/components/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
h1 {
color: red;
}
3 changes: 3 additions & 0 deletions examples/12_css/src/components/App.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.title {
background-color: pink;
}
18 changes: 18 additions & 0 deletions examples/12_css/src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// @ts-expect-error no types
import styles from './App.module.css';
import './App.css';
import { container } from './styles.css.js';
import { Counter } from './Counter.js';

const App = ({ name }: { name: string }) => {
return (
<div style={{ border: '3px red dashed', margin: '1em', padding: '1em' }}>
<h1>Hello {name}!!</h1>
<h1 className={styles.title}>Hello {name}!!</h1>
<h3 className={container}>This is a server component.</h3>
<Counter />
</div>
);
};

export default App;
14 changes: 14 additions & 0 deletions examples/12_css/src/components/Counter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use client';

import { useState } from 'react';

export const Counter = () => {
const [count, setCount] = useState(0);
return (
<div style={{ border: '3px blue dashed', margin: '1em', padding: '1em' }}>
<p>Count: {count}</p>
<button onClick={() => setCount((c) => c + 1)}>Increment</button>
<h3>This is a client component.</h3>
</div>
);
};
7 changes: 7 additions & 0 deletions examples/12_css/src/components/styles.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { style } from '@vanilla-extract/css';

export const container = style({
border: '3px green dashed',
margin: '1em',
padding: '1em',
});
34 changes: 34 additions & 0 deletions examples/12_css/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { lazy } from 'react';
import { defineEntries } from 'waku/server';

const App = lazy(() => import('./components/App.js'));

export default defineEntries(
// renderEntries
async (input) => {
return {
App: <App name={input || 'Waku'} />,
};
},
// getBuildConfig
async () => {
return {
'/': {
entries: [['']],
},
};
},
// getSsrConfig
async (pathStr) => {
switch (pathStr) {
case '/':
return {
input: '',
unstable_render: ({ createElement, Slot }) =>
createElement(Slot, { id: 'App' }),
};
default:
return null;
}
},
);
17 changes: 17 additions & 0 deletions examples/12_css/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { StrictMode } from 'react';
import { createRoot, hydrateRoot } from 'react-dom/client';
import { Root, Slot } from 'waku/client';

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

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
hydrateRoot(document.getElementById('root')!, rootElement);
} else {
createRoot(document.getElementById('root')!).render(rootElement);
}
15 changes: 15 additions & 0 deletions examples/12_css/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"strict": true,
"target": "esnext",
"downlevelIteration": true,
"esModuleInterop": true,
"module": "nodenext",
"skipLibCheck": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"jsx": "react-jsx",
"rootDir": "./src",
"outDir": "./dist"
}
}
10 changes: 10 additions & 0 deletions examples/12_css/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import url from 'node:url';
import path from 'node:path';
// import { defineConfig } from 'waku/config'
import { defineConfig } from 'vite';
import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';

export default defineConfig({
root: path.dirname(url.fileURLToPath(import.meta.url)),
plugins: [vanillaExtractPlugin({ emitCssInSsr: true })],
});
25 changes: 18 additions & 7 deletions packages/waku/src/lib/plugins/vite-plugin-rsc-delegate.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from 'node:path';
import type { Plugin } from 'vite';
import type { Plugin, TransformResult, ViteDevServer } from 'vite';
import * as swc from '@swc/core';

import { encodeFilePathToAbsolute } from '../utils/path.js';
Expand All @@ -9,17 +9,21 @@ const CSS_LANGS_RE =
/\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/;

export function rscDelegatePlugin(
importCallback: (source: string) => void,
importCallback: (source: string | TransformResult) => void,
): Plugin {
let mode = 'development';
let base = '/';
let server: ViteDevServer;
return {
name: 'rsc-delegate-plugin',
configResolved(config) {
mode = config.mode;
base = config.base;
},
transform(code, id) {
configureServer(_server) {
server = _server;
},
async transform(code, id) {
const ext = path.extname(id);
if (
mode === 'development' &&
Expand All @@ -36,10 +40,17 @@ export function rscDelegatePlugin(
const source = base + '@id/__x00__' + item.source.value;
importCallback(source);
} else if (CSS_LANGS_RE.test(item.source.value)) {
const filePath = path.join(path.dirname(id), item.source.value);
// HACK this relies on Vite's internal implementation detail.
const source = base + '@fs' + encodeFilePathToAbsolute(filePath);
importCallback(source);
const resolvedSource = await server.pluginContainer.resolveId(
item.source.value,
id,
{ ssr: true },
);
if (resolvedSource?.id) {
const transformedResult = await server.transformRequest(
resolvedSource.id,
);
transformedResult && importCallback(transformedResult);
}
}
}
}
Expand Down
45 changes: 38 additions & 7 deletions packages/waku/src/lib/plugins/vite-plugin-rsc-hmr.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
import path from 'node:path';
import type { Plugin, ViteDevServer } from 'vite';
import type { Plugin, TransformResult, ViteDevServer } from 'vite';

const customCode = `
import { createHotContext as __vite__createHotContext } from "/@vite/client"
import.meta.hot = __vite__createHotContext(import.meta.url);
if (import.meta.hot && !globalThis.__WAKU_HMR_CONFIGURED__) {
globalThis.__WAKU_HMR_CONFIGURED__ = true;
import.meta.hot.on('hot-import', (data) => import(/* @vite-ignore */ data));
import.meta.hot.on('module', (data) => {
const code = data.code
const script = document.createElement('script')
script.type = 'module'
script.text = code
document.head.appendChild(script)
});
}
`;

export function rscHmrPlugin(): Plugin {
return {
name: 'rsc-hmr-plugin',
async transform(code, id) {
const ext = path.extname(id);
if (['.ts', '.tsx', '.js', '.jsx'].includes(ext)) {
return code + customCode;
}
return code;
enforce: 'post',
transformIndexHtml(html) {
return html.replace(
'</body>',
`<script type="module">${customCode}</script></body>`,
);
},
};
}
Expand All @@ -37,3 +49,22 @@ export function hotImport(vite: ViteDevServer, source: string) {
sourceSet.add(source);
vite.ws.send({ type: 'custom', event: 'hot-import', data: source });
}

const modulePendingMap = new WeakMap<ViteDevServer, Set<TransformResult>>();
export function moduleImport(
viteServer: ViteDevServer,
result: TransformResult,
) {
let sourceSet = modulePendingMap.get(viteServer);
if (!sourceSet) {
sourceSet = new Set();
modulePendingMap.set(viteServer, sourceSet);
viteServer.ws.on('connection', () => {
for (const result of sourceSet!) {
viteServer.ws.send({ type: 'custom', event: 'module', data: result });
}
});
}
sourceSet.add(result);
viteServer.ws.send({ type: 'custom', event: 'module', data: result });
}
Loading

0 comments on commit 09a2707

Please sign in to comment.