ASP.NET Core 極簡風 - 嵌入 .html/.css/.js 靜態檔案徹底實現單檔部署
7 |
ASP.NET Core 極簡風 - Minimal API 提到只需加一行 UseFileServer(),ASP.NET Core 空白網站就可以像 ASP.NET MVC 一樣,將 .html/.css/.js/圖檔放在 wwwroot 資料夾,支援靜態檔案存取。若要實測,用 dotnet new web 開一個 Minimal API 空白網站,在專案新增 wwwroot 資料夾,放入 ui.html 及 .png [1],Program.cs 則加入一行 UseFileServer() [2],按下 F5 偵測程式,瀏覽器網址輸入 /ui.html [3],網頁順利顯示,是不是超簡單?
適逢農曆新年,順便藉這個 ASP.NET Core 範例跟大家拜年,祝大家健康平安,萬事順心。
如果要用靜態檔案 HTML 當首頁,將其名命為 index.html 放在 wwwroot 下,並移除 app.Get("/", ...) 即可。
使用 dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true --no-self-contained 產生部署檔(參考:使用 dotnet 命令列工具發行 .NET 6 專案),除了 .exe 外,wwwroot 也會一併輸出:
除了 exe 檔外還需要複製 wwwroot 資料夾減損簡潔性,在我心目中,像 Gitea、Hugo 靠單一執行檔搞定才稱得上是王者風範。所幸,ASP.NET Core 已有內建方法能讓我們實現夢想。(隨著了解愈深,我愈覺得 ASP.NET Core 已成熟到可普遍商用的程度)
ASP.NET Core 有個 Manifest Embedded File Provider,可將 .html/.css/.js/圖檔等靜態檔以內嵌資源(Embedded Resource)形式包進 .exe 或 .dll 檔使用,步驟不多:
- 使用 dotnet add package Microsoft.Extensions.FileProviders.Embedded 參照 NuGet 套件
- 修改 .csproj,加上
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
並以<EmbeddedResource Include="..." />
宣告要轉為內嵌資源的目錄或檔案。例如:我將 wwwroot 更名為 ui 資料夾,其下的 index.html 與 happy-new-year.png 用 EmbeddedResource 宣告為內嵌資源,完整名稱為 minApiStFiles.ui.index.html 及 minApiStFiles.ui.happy-new-year.png。csproj 修改如下:<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> </PropertyGroup> <ItemGroup> <EmbeddedResource Include="ui\**" /> </ItemGroup> <ItemGroup> <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="6.0.1" /> </ItemGroup> </Project>
- 修改 Program.cs,UseFileServer() 時傳入 FileServerOptions,宣告 ManifestEmbeddedFileProvider 並提示命名空間以 ui 起首:
註:如果改用 ManifestEmbeddedFileProvider 前曾用過 wwwroot 實體檔案,bin 目錄會殘留 .staticwebasets.runtim.json,請手動刪除或用 dotnet clean 清除,否則會出現找不到 wwwroot 錯誤。我在這上面卡了二十分鐘... orzvar builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseFileServer(new FileServerOptions { RequestPath = "", FileProvider = new Microsoft.Extensions.FileProviders .ManifestEmbeddedFileProvider( typeof(Program).Assembly, "ui" ) }); //app.MapGet("/", () => "Hello World!"); app.Run();
就醬,只靠一個 exe 檔,ASP.NET Core 憑空生出 index.html 與 happy-new-year.png,這才是我理想中的極簡風。
ASP.NET Core 好威,.NET 6 真棒!
Tutorial of how to embed wwwroot files into ASP.NET Core executable file to simplify deployment.
Comments
# by 小黑
真的不錯~
# by 螢火蟲
我朋友有一個網站 從舊主機到新主機之後,部署到IIS之後wwwroot底下的img,css,js都不能正常載入,請問您知道可能是什麼原因嗎
# by 螢火蟲
我朋友有一個.netcore網站,從舊主機搬到新主機,wwwroot下的js,css,img都不能正常載入,您知道大概是什麼原因嗎,之前明明可以的。
# by Jeffrey
to 螢火蟲,光由這些描述不太能斷定原因,新主機有安裝 ASP.NET Core Hosting Bundle 嗎? https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-aspnetcore-6.0.4-windows-hosting-bundle-installer 只有這個 ASP.NET Core 網站出問題?若隨便開個空白 ASP.NET Core MVC 專案部署上去可以運作嗎?
# by matt
想請問使用這個方法後,我的靜態檔案是angular build出來的, route不是根目錄時覽器上執行重新整理後出現404,必須要在跟目錄下才能正常運作,目前有解法嗎?
# by Jeffrey
to matt, 對 Anuglar Route 外行,不太懂問題關鍵,如果問題出在 .js 要放在根目錄,我以為放在 /wwwroot 第一層就可以了。
# by matt
謝謝,找到方法了,原本重新導到index.html,改成導到 空字串 就行了。