I am building an client-side application (using html/javascript) and would like to use a web assembly in it, compiled with .net 7.
https://learn.microsoft.com/en-us/aspnet/core/client-side/dotnet-interop
https://www.meziantou.net/using-dotnet-code-from-javascript-using-webassembly.htm
The application is NOT using blazor, it is a normal React vite-based application. So from the dotent, I get this dotnet.js file and a bunch of other files (the AppBundle folder), and now I would like to use that from some React component in my Vite application. So how do I do that?
If I try to go directly like this:
import { dotnet } = from '../../wasm/bin/Release/net7.0/browser-wasm/AppBundle/dotnet.js';
// then use use dotent
Then it even works in debug, but when bundling, vite cries about dynamic imports, and cannot pack the AppBundle properly, leaving the .dlls and other stuff behind. Also, dotent.js
does not like being renamed to something like dotnet.123ak.js
, and just breaks. Also, vite renames dotnet.wasm
to dotnet.123ak.wasm
, maybe this is what the dotnet part does not like.
Anyway. It would be enough to have sort of a "virtual" (unprocessed) import which I can somehow specify to resolve to the "dotent.js" file forcefully to some fixed path (external). How can I achieve this with vite? I.e. basically, I want
If I import like this:
import { dotnet } from 'some-file'
Then on build I do not get any errors, and after build I get the some-file
replaced with /MyAppBundle/dotnet.js
(a fixed value in config)
How can I achive this (for example, with webpack, there is "resolve" option in config, maybe there is something similar to help in vite?)
Figured it out. You can use await import(...)
to make it work. Have written a post regarding this:
https://medium.com/@nbelyh/using-net-as-a-webassembly-from-javascript-react-16fd9373c411
usage
const { dotnet, loading } =
useDotNet('/path/to/your/AppBundle/dotnet.js')
definition
import { useEffect, useRef, useState } from 'react';
export const useDotNet = (url: string) => {
const dotnetUrl = useRef('');
const [dotnet, setDotNet] = useState<any>(null);
const [loading, setLoading] = useState(true);
const load = async (currentUrl: string): Promise<any> => {
const module = await import(/* @vite-ignore */ currentUrl);
const { getAssemblyExports, getConfig } = await module
.dotnet
.withDiagnosticTracing(false)
.create();
const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);
return exports;
}
useEffect(() => {
if (dotnetUrl.current !== url) { // safeguard to prevent double-loading
setLoading(true);
dotnetUrl.current = url;
load(url)
.then(exports => setDotNet(exports))
.finally(() => setLoading(false))
}
}, [url]);
return { dotnet, loading };
}