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} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
reactStrictMode: true,
|
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;
|
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'
|
type UtfdumpContextTy = {
|
||||||
import type { ReactNode } from 'react'
|
utfdump?: typeof import('utfdump_wasm'),
|
||||||
|
};
|
||||||
|
|
||||||
const initial: IWASMContext = {}
|
type UtfdumpContextProviderProps = {
|
||||||
|
children: ReactNode,
|
||||||
|
};
|
||||||
|
|
||||||
const useMountEffectOnce = (fn: () => void) => {
|
export const UtfdumpContext = createContext<UtfdumpContextTy>({});
|
||||||
const wasExecutedRef = useRef(false)
|
|
||||||
|
export function UtfdumpContextProvider(props: UtfdumpContextProviderProps) {
|
||||||
|
const hasLoaded = useRef(false);
|
||||||
|
const [contextValue, setContextValue] = useState<UtfdumpContextTy>({});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!wasExecutedRef.current) {
|
// Ensure the WASM module is only run once, as this effect callback is called twice when React
|
||||||
fn()
|
// 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 (
|
return (
|
||||||
<WASMContext.Provider value={state}>
|
<UtfdumpContext.Provider value={contextValue}>
|
||||||
{children}
|
{props.children}
|
||||||
</WASMContext.Provider>
|
</UtfdumpContext.Provider>
|
||||||
)
|
);
|
||||||
}
|
|
||||||
|
|
||||||
interface IWASMContext {
|
|
||||||
wasm?: typeof import('utfdump_wasm')
|
|
||||||
}
|
|
||||||
|
|
||||||
interface WASMContextProviderProps {
|
|
||||||
children: ReactNode
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue