diff --git a/node.d.ts b/node.d.ts index 040579f..cfc7ca0 100644 --- a/node.d.ts +++ b/node.d.ts @@ -21,3 +21,9 @@ declare module '*.node' { const node: any export default node } + +// node wasm +declare module '*.wasm?loader' { + const loadWasm: (options?: WebAssembly.Imports) => Promise + export default loadWasm +} diff --git a/src/plugins/asset.ts b/src/plugins/asset.ts index 3297aec..da2dda3 100644 --- a/src/plugins/asset.ts +++ b/src/plugins/asset.ts @@ -6,7 +6,7 @@ import MagicString from 'magic-string' import { cleanUrl, parseRequest, getHash, toRelativePath } from '../utils' interface AssetResolved { - type: 'asset' | 'native' + type: 'asset' | 'native' | 'wasm' file: string query: Record | null } @@ -31,12 +31,33 @@ function resolveAsset(id: string): AssetResolved | null { } } + if (file.endsWith('.wasm')) { + return { + type: 'wasm', + file, + query + } + } + return null } const nodeAssetRE = /__VITE_NODE_ASSET__([a-z\d]{8})__/g const nodePublicAssetRE = /__VITE_NODE_PUBLIC_ASSET__([a-z\d]{8})__/g +const wasmHelperId = '\0__electron-vite-wasm-helper' + +const wasmHelperCode = ` +import { join } from 'path' +import { readFile } from 'fs/promises' + +export default async function loadWasm(file, importObject = {}) { + const wasmBuffer = await readFile(join(__dirname, file)) + const result = await WebAssembly.instantiate(wasmBuffer, importObject) + return result.instance +} +` + export default function assetPlugin(): Plugin { let sourcemap: boolean | 'inline' | 'hidden' = false let publicDir = '' @@ -52,7 +73,16 @@ export default function assetPlugin(): Plugin { publicDir = normalizePath(config.publicDir) outDir = normalizePath(config.build.outDir) }, + resolveId(id): string | void { + if (id === wasmHelperId) { + return id + } + }, async load(id): Promise { + if (id === wasmHelperId) { + return wasmHelperCode + } + const assetResolved = resolveAsset(id) if (!assetResolved) { return @@ -97,6 +127,12 @@ export default function assetPlugin(): Plugin { if (assetResolved.type === 'native') { return `export default require(${referenceId})` } + + if (assetResolved.type === 'wasm') { + return ` + import loadWasm from ${JSON.stringify(wasmHelperId)} + export default importObject => loadWasm(${referenceId}, importObject)` + } }, renderChunk(code, chunk): { code: string; map: SourceMapInput } | null { let match: RegExpExecArray | null