【ASP.NET Core】在node.js上託管Blazor WebAssembly應用

2023-03-22 06:10:36

由於 Blazor-WebAssembly 是在瀏覽器中執行的,通常不需要執行伺服器程式碼,只要有個「窩」能託管並提供相關檔案的下載即可。所以,當你有一個現成的 Blazor wasm 專案,沒必要用其他語言重寫,或者你不想用 ASP.NET Core 來託管(有些大材小用了),就可以試試用 node.js 來託管。

要實現這個不需要掌握什麼新的知識,所以咱們直接開工幹活。

首先,咱們做好 Blazor wasm 應用的開發。

dotnet new blazorwasm-empty -n Demo -o .

blazorwasm-empty 模板建立的專案只帶一些基本程式碼和 Hello World,沒有演示程式碼——無Counter無假天氣預報。

然後,Program.cs 檔案也可以精簡一下。

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");

await builder.Build().RunAsync();

#app 是CSS篩選器,即選擇 id 為 app 的元素來呈現 Razor 元件。這個相信各位都懂。

為了更好地演示,咱們把 Index 元件改一下,加一點互動功能,以便後面可以驗證 Blazor 是否正常啟動。

@page "/"

<h1>Hello, world!</h1>
<button @onclick="ClickMe">點這裡中大獎</button>
<div>@Message</div>

@code{
    private string? Message{get;set;}

    void ClickMe()
    {
        int xx = Random.Shared.Next(100, 700);
        Message = $"恭喜你獲得{xx}萬假鈔!";
    }
}

這個不復雜,就是點選一下按鈕,然後生成個隨機整數,並修改 Message 屬性。處理 click 事件要注意加上 @,如果是 onclick 你只能用 js 去寫,要想用 C# 來寫程式碼,就得用 @onclick。

接著,試執行一下,保證沒有錯誤,能正常執行。

 

現在,你開啟 \bin\Debug\net7.0\wwwroot 目錄,裡面你看到有個 _framework 目錄,這個目錄就是我們要的。不過,這個體積太大,不適合。咱們將專案發布一下,這樣體積會變小很多。

我們不需要 wwwroot 目錄下的東東,把整個目錄「咔嚓」掉(這裡指的是專案中的 wwwroot 目錄,不是輸出目錄的)。為了防止重新生成時有檔案錯誤(一般不會),可以把 obj 和 bin 目錄也刪除。

執行釋出命令。

dotnet publish -c PublishRelease

-c 引數也可以用 Release,差別不大。

另外新建一個目錄,路徑隨便,不要有非英文字元(防止出錯),比如這裡我命名為 Server。把剛才釋出的整個 _framework 目錄複製到 Server 目錄中。現在你可以關閉 Blazor 專案了,沒它什麼事了。

在 Server 目錄下新建一個檔案,叫 index.html。

<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8"/>
        <title>高階範例</title>
    </head>
    <body>
        <div id="app">正在載入……</div>
        <script src="_framework/blazor.webassembly.js"></script>
    </body>
</html>

這裡注意兩處:

1、要有一個 id 為 app 的元素,它用來呈現元件。

2、<script> 要參照 blazor.webassembly.js 檔案。

 

在 Server 目錄下再新建一個檔案,名為 app.js。這個用來寫伺服器主程式(js 程式碼)。

const url = require("node:url");
const path = require("node:path");
const http = require("node:http");
const fs = require("node:fs");

// 主機
const host = 'localhost';
//
const port = 6748;
// MIME 對映
function getFileMap(fileExt)
{
    switch(fileExt)
    {
        case ".js":
        case ".mjs":
            return "text/javascript";
        case ".json":
            return "application/json";
        case ".htm":
        case ".html":
            return "text/html";
        case ".css":
            return "text/css";
        case ".jpg":
        case ".jpeg":
            return "image/jpeg";
        // 其他的自己看情況新增
        default:
            // 其餘的如.dll、.gz等,就是二進位制檔案
            return "application/octet-stream";
    }
}

http.createServer((request, response)=>
{
    // 獲取請求路徑
    let reqPath = url.parse(request.url).pathname;
    // 去掉路徑開頭的「/」
    let fileName = reqPath.substring(1);
    // 如果空白,預設檔名 index.html
    if(fileName.length === 0)
    {
        fileName = "index.html";
    }
    // 讀取檔案內容
    fs.readFile(fileName, (err, data)=>{
        // 如果出錯
        if(err)
        {
            // 直接回個404
            response.writeHead(404, {"Content-Type": "text/html"});
        }
        else
        {
            // 獲取副檔名,以決定MIME型別
            let ext = path.extname(fileName);
            let mimeType = getFileMap(ext.toLowerCase());
            // 傳送HTTP頭
            response.writeHead(200, {"Content-Type": mimeType});
            // 傳送正文
            response.write(data);
        }
        // 這一行必須,結束響應訊息
        response.end();
    });
})
.listen(port, host);

console.log(`伺服器:${host}:${port}`);

執行它,執行:node app.js。接著在瀏覽器中輸入地址:http://localhost:6748。再驗證 Blazor 應用程式是否成功啟動。

 

如果看到亂數能正確生成,說明執行成功了。