diff --git a/examples/with-webassembly/README.md b/examples/with-webassembly/README.md index b2f9822c7fd2e0c..e846c711927e056 100644 --- a/examples/with-webassembly/README.md +++ b/examples/with-webassembly/README.md @@ -32,4 +32,6 @@ To compile `src/add.rs` to `add.wasm` run: npm run build-rust # or yarn build-rust +# or +pnpm build-rust ``` diff --git a/examples/with-webassembly/components/RustComponent.tsx b/examples/with-webassembly/components/RustComponent.tsx new file mode 100644 index 000000000000000..6acf05307bf666f --- /dev/null +++ b/examples/with-webassembly/components/RustComponent.tsx @@ -0,0 +1,24 @@ +import type { AddModuleExports } from '../wasm' +import dynamic from 'next/dynamic' + +interface RustComponentProps { + number: Number +} + +const RustComponent = dynamic({ + loader: async () => { + // Import the wasm module + // @ts-ignore + const exports = (await import('../add.wasm')) as AddModuleExports + const { add_one: addOne } = exports + + // Return a React component that calls the add_one method on the wasm module + return ({ number }: RustComponentProps) => ( +
+ <>{addOne(number)} +
+ ) + }, +}) + +export default RustComponent diff --git a/examples/with-webassembly/next.config.js b/examples/with-webassembly/next.config.js index 4d5f3d98c8b8c9d..42ea82bf4049fce 100644 --- a/examples/with-webassembly/next.config.js +++ b/examples/with-webassembly/next.config.js @@ -1,7 +1,12 @@ /** @type {import('next').NextConfig} */ -module.exports = { - webpack(config) { - config.output.webassemblyModuleFilename = 'static/wasm/[modulehash].wasm' +const nextConfig = { + webpack(config, { isServer, dev }) { + // Use the client static directory in the server bundle and prod mode + // Fixes `Error occurred prerendering page "/"` + config.output.webassemblyModuleFilename = + isServer && !dev + ? '../static/wasm/[modulehash].wasm' + : 'static/wasm/[modulehash].wasm' // Since Webpack 5 doesn't enable WebAssembly by default, we should do it manually config.experiments = { ...config.experiments, asyncWebAssembly: true } @@ -9,3 +14,5 @@ module.exports = { return config }, } + +module.exports = nextConfig diff --git a/examples/with-webassembly/package.json b/examples/with-webassembly/package.json index fe8da1928db97d3..aeee0eac806674a 100644 --- a/examples/with-webassembly/package.json +++ b/examples/with-webassembly/package.json @@ -1,14 +1,20 @@ { "private": true, - "dependencies": { - "next": "latest", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, "scripts": { "dev": "next", "build": "next build", "build-rust": "rustc --target wasm32-unknown-unknown -O --crate-type=cdylib src/add.rs -o add.wasm", "start": "next start" + }, + "dependencies": { + "next": "latest", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/node": "^18.11.10", + "@types/react": "^18.0.26", + "@types/react-dom": "^18.0.9", + "typescript": "^4.9.3" } } diff --git a/examples/with-webassembly/pages/api/edge.js b/examples/with-webassembly/pages/api/edge.js deleted file mode 100644 index f724fd32280f5e1..000000000000000 --- a/examples/with-webassembly/pages/api/edge.js +++ /dev/null @@ -1,11 +0,0 @@ -import add_module from '../../add.wasm?module' - -const instance$ = WebAssembly.instantiate(add_module) - -export default async function edgeExample() { - const { exports } = await instance$ - const number = exports.add_one(10) - return new Response(`got: ${number}`) -} - -export const config = { runtime: 'experimental-edge' } diff --git a/examples/with-webassembly/pages/api/edge.ts b/examples/with-webassembly/pages/api/edge.ts new file mode 100644 index 000000000000000..0e9a30908ae409a --- /dev/null +++ b/examples/with-webassembly/pages/api/edge.ts @@ -0,0 +1,16 @@ +import type { AddModuleExports } from '../../wasm' +// @ts-ignore +import addWasm from '../../add.wasm?module' + +const module$ = WebAssembly.instantiate(addWasm) + +export default async function handler() { + const instance = (await module$) as any + const exports = instance.exports as AddModuleExports + const { add_one: addOne } = exports + const number = addOne(10) + + return new Response(`got: ${number}`) +} + +export const config = { runtime: 'experimental-edge' } diff --git a/examples/with-webassembly/pages/index.js b/examples/with-webassembly/pages/index.js deleted file mode 100644 index ba2b622f49f1d4c..000000000000000 --- a/examples/with-webassembly/pages/index.js +++ /dev/null @@ -1,24 +0,0 @@ -import { withRouter } from 'next/router' -import dynamic from 'next/dynamic' -import Link from 'next/link' - -const RustComponent = dynamic({ - loader: async () => { - // Import the wasm module - const rustModule = await import('../add.wasm') - // Return a React component that calls the add_one method on the wasm module - return (props) =>
{rustModule.add_one(props.number)}
- }, -}) - -const Page = ({ router: { query } }) => { - const number = parseInt(query.number || 30) - return ( -
- - + -
- ) -} - -export default withRouter(Page) diff --git a/examples/with-webassembly/pages/index.tsx b/examples/with-webassembly/pages/index.tsx new file mode 100644 index 000000000000000..6d6aba712f39194 --- /dev/null +++ b/examples/with-webassembly/pages/index.tsx @@ -0,0 +1,15 @@ +import { useRouter } from 'next/router' +import Link from 'next/link' +import RustComponent from '../components/RustComponent' + +export default function Page() { + const { query } = useRouter() + const number = parseInt(query.number as string) || 30 + + return ( +
+ + + +
+ ) +} diff --git a/examples/with-webassembly/tsconfig.json b/examples/with-webassembly/tsconfig.json new file mode 100644 index 000000000000000..5b3c8783e426628 --- /dev/null +++ b/examples/with-webassembly/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "wasm.d.ts"], + "exclude": ["node_modules"] +} diff --git a/examples/with-webassembly/wasm.d.ts b/examples/with-webassembly/wasm.d.ts new file mode 100644 index 000000000000000..db4e6b84e3ea33b --- /dev/null +++ b/examples/with-webassembly/wasm.d.ts @@ -0,0 +1,3 @@ +export interface AddModuleExports { + add_one(number: Number): Number +}