2025 年,解決 ASP.NET Core 專案無法 Minify 現代 JavaScript 的問題
| | 0 | | 954 |
對於在 ASP.NET MVC 中壓縮及打包 JavaScript/CSS,我的觀念還停留在 10 年前的 ASP.NET MVC ScriptBundle,或是部落格用到的第三方程式庫 LigerShark.WebOptimizer。
時間來到 2025 年,前端 CSS/JavaScript 規格跟工具已不知翻過幾輪,是該時候評估學習新工具及新做法了。
我先查了 ASP.NET Core 官方文件,看看官方是否有推出現代化武器。很不幸地,ASP.NET Core 並未內建打包壓縮(Bundling and Minification)工具,只建議了兩種做法:
- LigerShar.WebOptimizer 開源程式庫,文章開頭有提到我部落格在用的那個
- 借用 Gulp / Webpack 等前端工作流程
ASP.NET Core 在這部分支援薄弱倒也不難理解,這些年前端框架 React、Vue、Angular 都有一套成熟的編譯壓縮打包機制,像我還在寫 JavaScript 從 HTML <script src="">
載入的輕前端玩家畢竟是少數,市場太小不值得投入資源開發工具,資源與支援自然就少,選了非主流就得自立自強,缺了什麼要自己補上。
除非萬不得已我不想扯上 Gulp/WebPack 讓專案維護複雜化,還是想堅守 WebOptimizer 的簡單輕巧解法。WebOptimizer 為執行階段動態壓縮打包,JS/CSS 是靜態檔,壓縮打包動作其實在編譯或部署時做一次就夠,沒必要每次啟動重跑,我找到 WebOptimizer 作者 Mads Kristensen 的另一個作品 - BuildBundlerMinifier,是 WebOptimizer 的靜態編譯版。
使用方法很簡單,專案 dotnet add package BuildBundlerMinifier
加入參照,在專案根目錄加入 bundleconfig.json 設定壓縮打包對象:
[
{
"outputFileName": "wwwroot/js/bundle.min.js",
"inputFiles": [
"wwwroot/lib/vue/vue.global.prod.min.js",
"wwwroot/lib/sweetalert2/sweetalert2.all.min.js",
"wwwroot/js/app.js"
],
"minify": {
"enabled": true,
"renameLocals": true
},
"sourceMap": false
}
]
執行 dotnet build
,「順利的話」便會生出壓縮打包後的 bundle.min.js。
沒錯,「順利的話」代表事情沒那麼單純。實測發現,不管 WebOptimizer 或 BuildBundlerMinifier 都存在版本偏舊不支援現代 JavaScript 語法的問題。以上的設定在 minify enabled: true 時會出錯,改為 false 只合併檔案則沒什麼問題。
舉例來說,以下這段常見的 JavaScript 寫法:
const app = Vue.createApp({
data() {
return {
message: 'Hello Vue!'
}
},
methods: {
showAlert() {
Swal.fire({
title: 'SweetAlert Example',
text: this.message,
icon: 'success',
confirmButtonText: 'OK',
animation: false
});
}
}
});
const vm = app.mount('#app');
WebOptimizer 進行 Minify 壓縮時會出現以下錯誤:
細究原因,BundlerMinifier 底層靠 NUglify 程式庫壓縮 JavaScript、CSS 及 HTML 檔案,而這個有點年紀的開源專案源自更古老的 Microsoft Ajax Minifier,其 JS 語法標準只支援到 ES2021,距今已快四年(註 ECMAScript 最新標準 ES2024 已於 2024 六月發佈),故 2022 之後的新版程式庫一旦用到 ES2022、ES2023 甚至 ES2024 的新語法,轟!
由於 JavaScript 語法規格更新飛快,IE 死後 Chrome 幾已一統江湖(Edge 也是 Chromium 核心),且主流瀏覽器都會持續自動更新到最新版,前端開發界採納新規格少了很多顧忌,引起新語法沒在客氣的,想跟上腳步只能回歸主流前端工具,於是我想到了 UglifyJS。
我目前找到的 Workaround 是寫一支 PowerShell 程式 Minify.ps1,讀取 Minify.csv 設定要壓縮的 .js。專案目錄要先用 npm install uglify-js
裝好 UglifyJS,編譯過程 Minify.ps1 會讀取 Minify.csv 一一呼叫 UglifyJS 進行壓後存成 min.js,之後再交給 BundlerMinifier 打包。
PowerShell 程式如下:
$ErrorActionPreference = "Stop"
$uglifyJsPath = "$PSScriptRoot\node_modules\.bin\uglifyjs.ps1"
if (-not (Test-Path $uglifyJsPath)) {
Write-Host "uglifyjs.ps1 not found. Please run npm install uglify-js" -ForegroundColor Red
exit 1
}
Get-Content $PSScriptRoot\minify.csv | ForEach-Object {
$file = $_
$ext = [System.IO.Path]::GetExtension($file)
if (Test-Path $file) {
& "$uglifyJsPath" $file -o ([System.IO.Path]::ChangeExtension($file, ".min" + $ext))
}
}
最後,在 csproj 設定每次編譯前執行 Minify.ps1:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>js_bundle</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BuildBundlerMinifier" Version="3.2.449" />
<PackageReference Include="LigerShark.WebOptimizer.Core" Version="3.0.433" />
</ItemGroup>
<Target Name="Minify JavaScript" BeforeTargets="BeforeCompile">
<Exec Command="pwsh "$(ProjectDir)Minify.ps1""></Exec>
</Target>
</Project>
實測設定成 BeforeTargets="BeforeCompile" Minify.ps1 會固定在 BundleMinifier 之前執行,產生好 min.js 給 BundleMinifier 打包,bundleconfig.json 要設定成 minify enabled: false 只打包不壓縮,如此便可克服 BundleMinifier 不支援新 JavaScript 語法的問題。如果要改完 .js 立即看結果,可以刪除打包輸出的 min.js,BundleMinifier 會自動觸發連帶先跑 Minify.ps1,達成即改即看的效果。
就醬,搬開輕前端之路上的小石頭繼續前進,分享給也在這條路上的伙伴。
後記,這回有復習用 libman 下載安裝 cdnjs 上的 JavaScript 程式庫,筆記一下指令:
libman install vue --provider cdnjs --files vue.global.prod.min.js --destination wwwroot/lib/vue
libman install sweetalert2 --provider cdnjs --files sweetalert2.all.min.js --destination wwwroot/lib/sweetalert2
libman install highlight.js --provider cdnjs --files styles/vs2015.min.css --files highlight.min.js --destination wwwroot/lib/highlight.js
In 2025, front-end development tools have evolved, and traditional ASP.NET MVC bundling methods are outdated. ASP.NET Core lacks built-in bundling/minification tools, but options include LigerShark.WebOptimizer and front-end tools like Gulp/Webpack. For modern JavaScript syntax, use UglifyJS with a PowerShell script for reliable minification, integrated into your build process.
Comments
Be the first to post a comment