feat(asset): support for WebAssembly in the main process

This commit is contained in:
alex8088 2023-01-10 21:53:38 +08:00
parent 4989595464
commit b3208d3dae
2 changed files with 43 additions and 1 deletions

6
node.d.ts vendored
View file

@ -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<WebAssembly.Instance>
export default loadWasm
}

View file

@ -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<string, string> | 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<string | void> {
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