4

讓 ASP.NET Core 也能改完 cshtml 立即看結果

 2 years ago
source link: https://blog.darkthread.net/blog/razor-runtime-compilation/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
讓 ASP.NET Core 也能改完 cshtml 立即看結果-黑暗執行緒

這是改寫 ASP.NET Core 後的一大困擾,ASP.NET Core 預設會將 .cshtml 編譯成 YourApp.Views.dll,不再像以前可以直接修改 Views 資料夾下的 .cshtml,重新整理瀏覽器就看修改後的結果。必須停止偵錯,重新編譯執行才會更新。

這項調整讓我的前端程式開發過程變得很痛苦,我採用「輕前端」的開發策略,cshtml 是主體,JavaScript 部分只用 Vue.js 處理 MVVM 及用 AJAX 方式呼叫 WebAPI,因此常要反覆調整 HTML 元素的 v-model、v-bind、v-on 標籤及 CSS 樣式等,每動一個地方想看結果就得停止偵錯、重新編譯,再重新偵錯,看瀏覽器關了又開、開了又開,火都上來了。過去 MVC5 那種改 cshtml 後存檔 + 瀏覽器重整看結果的開發程序才是正常人能忍受的開發方式吧!

研究找到解決方案。在 MS 文件查到,ASP.NET Core 3.1 起支援所謂的 Razor Runtime Compilation,允許 Razor Pages 或 MVC 啟用 cshtml 動態編譯,恢復 MVC5 時代存檔重整即更新的模式。而從 VS2019 16.5.4 起(依文件釋出日期 4/14 推測),新增 ASP.NET Core 專案時會多一個「Enable Razor runtime compilation」選項:(實測要 ASP.NET Core 3.1 以後才會有這個選項)

勾選後,專案會多參照一個 Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation Package:

而 Properties/launchSettings.json 則有一個 ASPNETCORE_HOSTINGSTARTUPASSEMBLIES 變數啟用 cshtml 執行期編譯:

  //... 略
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
      }
    }
    //... 略

如果是已經建立好的 ASP.NET Core 3.1 專案,可以手動安裝 Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation NuGet Package,比照上述方式加入 ASPNETCORE_HOSTINGSTARTUPASSEMBLIES 參數。MS 文件提到 Startup.ConfigureServices() 加上 services.AddRazorPages().AddRazorRuntimeCompilation() 的做法,不如 用 ASPNETCORE_HOSTINGSTARTUPASSEMBLIES 變數動態切換來方便。

註:Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation 需要 .NET Core 3.1 以上版本,不適用 ASP.NET Core 2.x。

一般來說,cshtml 動態編譯在開發階段比較有用,在線上環境會因為動態編譯及啟用 .NET Core File Watcher 損失一些效能,而部署 .cshtml 檔案還會增加原始碼外洩及被惡意竄改的風險,較不建議使用。故預設 Publish 時,.cshtml 預設還是會編譯成 AppName.Views.dll,輸出結果也不會包含 Views 或 Pages 資料夾,若你有很好的理由要在正式環境啟用,可在 .csproj 加入 RazorCompileOnPublish 屬性設成 false (預設為 true):

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
    <RazorCompileOnPublish>false</RazorCompileOnPublish>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.3" />
  </ItemGroup>

</Project>

如此,輸出時將不會產生 AppName.Views.dll,MVC5 時代熟悉的 Views/Pages 資料夾也會回來囉。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK