auto wasm compilation
parent
78796489ca
commit
586e1d9e2c
@ -1,6 +1,26 @@
|
||||
const WasmPackPlugin = require('@wasm-tool/wasm-pack-plugin');
|
||||
const path = require('path');
|
||||
|
||||
let loadedWasm = false;
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
webpack(nextConfig) {
|
||||
if (!loadedWasm) {
|
||||
loadedWasm = true;
|
||||
nextConfig.plugins.push(
|
||||
new WasmPackPlugin({
|
||||
crateDirectory: path.resolve(__dirname, '..', 'utfdump', 'wasm'),
|
||||
outDir: path.resolve(__dirname, 'wasm', 'utfdump'),
|
||||
forceMode: 'production',
|
||||
extraArgs: '--target web',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return nextConfig;
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
|
||||
@ -1,49 +1,38 @@
|
||||
// using solution from https://github.com/satelllte/nextjs-wasm for now
|
||||
import { useState, createContext, useEffect, useRef } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
import { useState, createContext, useEffect, useRef } from 'react'
|
||||
import type { ReactNode } from 'react'
|
||||
type UtfdumpContextTy = {
|
||||
utfdump?: typeof import('utfdump_wasm'),
|
||||
};
|
||||
|
||||
const initial: IWASMContext = {}
|
||||
type UtfdumpContextProviderProps = {
|
||||
children: ReactNode,
|
||||
};
|
||||
|
||||
const useMountEffectOnce = (fn: () => void) => {
|
||||
const wasExecutedRef = useRef(false)
|
||||
export const UtfdumpContext = createContext<UtfdumpContextTy>({});
|
||||
|
||||
export function UtfdumpContextProvider(props: UtfdumpContextProviderProps) {
|
||||
const hasLoaded = useRef(false);
|
||||
const [contextValue, setContextValue] = useState<UtfdumpContextTy>({});
|
||||
|
||||
useEffect(() => {
|
||||
if (!wasExecutedRef.current) {
|
||||
fn()
|
||||
// Ensure the WASM module is only run once, as this effect callback is called twice when React
|
||||
// is in strict mode.
|
||||
// FIXME: is atomic compare-and-swap necessary? Does React run this in a multithreaded context?
|
||||
if (!hasLoaded.current) {
|
||||
hasLoaded.current = true;
|
||||
|
||||
(async() => {
|
||||
const utfdumpWasmModule = await import('utfdump_wasm');
|
||||
await utfdumpWasmModule.default();
|
||||
setContextValue({ utfdump: utfdumpWasmModule });
|
||||
})();
|
||||
}
|
||||
wasExecutedRef.current = true
|
||||
}, [fn])
|
||||
}
|
||||
|
||||
export const WASMContext = createContext(initial)
|
||||
|
||||
export const WASMContextProvider: React.FC<WASMContextProviderProps> = ({
|
||||
children
|
||||
}) => {
|
||||
const [state, setState] = useState<IWASMContext>(initial)
|
||||
|
||||
// This has to run only once: https://github.com/rustwasm/wasm-bindgen/issues/3153
|
||||
// Though, in development React renders twice when Strict Mode is enabled: https://reactjs.org/docs/strict-mode.html
|
||||
// That's why it must be limited to a single mount run
|
||||
useMountEffectOnce(() => {
|
||||
(async() => {
|
||||
const wasm = await import("utfdump_wasm");
|
||||
await wasm.default();
|
||||
setState({ wasm });
|
||||
})()
|
||||
})
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<WASMContext.Provider value={state}>
|
||||
{children}
|
||||
</WASMContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
interface IWASMContext {
|
||||
wasm?: typeof import('utfdump_wasm')
|
||||
}
|
||||
|
||||
interface WASMContextProviderProps {
|
||||
children: ReactNode
|
||||
<UtfdumpContext.Provider value={contextValue}>
|
||||
{props.children}
|
||||
</UtfdumpContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue