使用 C# 编译成wasm给前端使用

wasm 是什么在此就不多做介绍了,我们直接开始写个 helloworld。

项目准备

首先需要安装依赖,默认是用当前 LTS 的.net 8。执行命令:

dotnet workload install wasm-tools
dotnet new install Microsoft.NET.Runtime.WebAssembly.Templates
#如果想要开启 AOT 功能,还需要安装下面这个依赖
dotnet workload install wasm-tools-net8

AOT 好处在于运行时会快一些,但是代价是dotnet.native.wasm这个文件会从 2408kb 变成5434kb 。所以除非计算压力特别大,否则不推荐开启这个功能。开启方法为:在项目文件(XXX.csproj)中的PropertyGroup里面添加下列两行:

    <RunAOTCompilation>true</RunAOTCompilation>
    <WasmStripILAfterAOT>true</WasmStripILAfterAOT>

依赖安装好了,我们开始新建项目。在新建项目里面选择WebAssembly Browser App即可。这个模板项目其实就是一个完整的 hello world 程序了。但是为了学习,我们对它稍作修改。

了解项目文件

html 文件是一个简单的入口文件,我们可以不管它。main.js 是加载核心,Program.cs则对应 wasm 文件。

// main.js
import { dotnet } from './_framework/dotnet.js'

const { setModuleImports, getAssemblyExports, getConfig } = await dotnet
    .create();
//注入 c# 中
setModuleImports('main.js', {
    bridge: {
        location: {
            href: () => window.location.href
        }
    }
});

const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);
const text = exports.MyClass.Greeting();
document.getElementById('out').innerHTML = text;
if (exports.MyClass.CheckAuth()) {
    console.log("错误!")
}
if (exports.MyClass.Auth("不好")) {
    console.log("错误!")
}
if (!exports.MyClass.Auth("你好")) {
    console.log("错误!")
}
if (!exports.MyClass.CheckAuth()) {
    console.log("错误!")
}
//以上的运行结果是:
//Hello, World! Greetings from http://127.0.0.1/
//不好 验证失败

// 下面这行注释了就不会显示 Hello, Browser!
//await dotnet.run();
using System;
using System.Runtime.InteropServices.JavaScript;

Console.WriteLine("Hello, Browser!");

public partial class MyClass
{
    private static bool auth = false;
    [JSExport]
    internal static string Greeting()
    {
        var text = $"Hello, World! Greetings from {GetHRef()}";
        Console.WriteLine(text);
        return text;
    }

    [JSExport]
    internal static bool CheckAuth()
    {
        return auth;
    }

    [JSExport]
    internal static bool Auth(string code)
    {
        if (code == "你好")
        {
            auth = true;
        }
        else
        {
            auth = false;
            Log(code + " 验证失败");
        }
        return auth;
    }

    [JSImport("bridge.location.href", "main.js")]
    internal static partial string GetHRef();
//globalThis就是window,可以直接引用
    [JSImport("globalThis.console.log")]
    internal static partial void Log(string message);
}

运行

编译成wasm不能直接点击VS的编译按钮,必须使用命令行才行。在命令行里面执行dotnet publish -c Release,然后就会编译好,路径在项目路径+bin\Release\net8.0\publish\wwwroot。使用 nginx 配置好路径后访问,可以在控制台看到以下内容:

Hello, World! Greetings from http://127.0.0.1/
不好 验证失败

首次访问需要下载 5.2M 内容(压缩前),再次访问因为会缓存 wasm 文件,所以只需要400kb。缓存文件会记录文件 hash,重新编译导致 hash 变化后会自动重新下载,这个功能还是相当好用的。

总结

用 C# 编译成 wasm 整体还是很简单的,工作流很完整。但是由于它相当于是引入了一个 C# 的解释器,所以效率会差一点,而且大小也不算小(gz 压缩也有差不多 4M)。除非对安全要求较高,否则没必要用这个功能。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容