ASP.NET Core 中的捆綁和縮小靜態(tài)資產(chǎn)

最近在B站上看到楊旭老師的ASP.NET Core 3.x 入門視頻(完結(jié))的第三節(jié)的ASP.NET視頻教程,里面提到到ASP.NET Core 中的捆綁和縮小靜態(tài)資產(chǎn),可以在微軟官方文檔ASP.NET Core 中的捆綁和縮小靜態(tài)資產(chǎn)拆撼,特此記錄一下映之,感興趣的可以直接查看官方文檔穴豫。

ASP.NET Core 中的捆綁和縮小靜態(tài)資產(chǎn)

2020/09/02
作者:Scott AddieDavid Pine
本文介紹應(yīng)用捆綁和縮小的好處皮钠,包括如何在 ASP.NET Core Web 應(yīng)用中使用這些功能晚岭。

什么是捆綁和縮小

捆綁和縮小是可以在 Web 應(yīng)用中應(yīng)用的兩個不同的性能優(yōu)化迂烁。 捆綁和縮小一起使用州袒,可減少服務(wù)器的請求數(shù)并減小請求的靜態(tài)資產(chǎn)的大小揭绑,從而提高性能。
捆綁和縮小主要縮短第一個頁面請求加載時間郎哭。 請求網(wǎng)頁后他匪,瀏覽器會緩存靜態(tài)資產(chǎn)(JavaScript、CSS 和圖像)夸研。 因此邦蜜,在請求相同資產(chǎn)的同一站點上請求相同的一個或多個頁面時,捆綁和縮小不會提高性能陈惰。 如果未在資產(chǎn)上正確設(shè)置 expires 標(biāo)頭畦徘,且未使用捆綁和縮小,則瀏覽器的新鮮度啟發(fā)會在幾天后將資產(chǎn)標(biāo)記為過期抬闯。 此外井辆,瀏覽器還需要對每個資產(chǎn)進(jìn)行驗證請求。 在這種情況下溶握,即使在第一個頁面請求后杯缺,捆綁和縮小仍能提高性能。

捆綁

捆綁將多個文件合并到單個文件中睡榆。 捆綁可減少呈現(xiàn) Web 資產(chǎn)(如網(wǎng)頁)所需的服務(wù)器請求數(shù)萍肆。 可以專門為 CSS、JavaScript 等創(chuàng)建任意數(shù)量的單個捆綁胀屿。文件越少塘揣,從瀏覽器到服務(wù)器或從提供應(yīng)用程序的服務(wù)的 HTTP 請求就越少。 這會提高第一頁加載性能宿崭。

縮小

縮小在不更改功能的情況下從代碼中刪除不必要的字符亲铡。 因此,請求的資產(chǎn)(如 CSS葡兑、圖像和 JavaScript 文件)的大小大幅減小奖蔓。 縮小的常見副作用包括將變量名稱縮短為一個字符、刪除注釋和不必要的空格讹堤。
考慮以下 JavaScript 函數(shù):

AddAltToImg = function (imageTagAndImageID, imageContext) {
    ///<signature>
    ///<summary> Adds an alt tab to the image
    // </summary>
    //<param name="imgElement" type="String">The image selector.</param>
    //<param name="ContextForImage" type="String">The image context.</param>
    ///</signature>
    var imageElement = $(imageTagAndImageID, imageContext);
    imageElement.attr('alt', imageElement.attr('id').replace(/ID/, ''));
}

縮小將函數(shù)縮減為以下內(nèi)容:

AddAltToImg=function(t,a){var r=$(t,a);r.attr("alt",r.attr("id").replace(/ID/,""))};

除了刪除注釋和不必要的空格外吆鹤,還進(jìn)行了以下參數(shù)和變量名稱重命名:

原始 重命名
imageTagAndImageID t
imageContext a
imageElement r

捆綁和縮小的影響

操作 使用捆綁/縮小 不使用捆綁/縮小 更改
文件請求 7 18 157%
傳輸?shù)?KB 156 264.68 70%
加載時間(毫秒) 885 2360 167%

對于 HTTP 請求標(biāo)頭,瀏覽器非常詳細(xì)洲守。 捆綁時疑务,已發(fā)送的總字節(jié)數(shù)指標(biāo)明顯減少沾凄。 加載時間顯示了顯著改進(jìn),但本示例在本地運行知允。 將捆綁和縮小與通過網(wǎng)絡(luò)傳輸?shù)馁Y產(chǎn)結(jié)合使用時搭独,可實現(xiàn)更高的性能提升。

選擇捆綁和縮小策略

MVC 和 Razor Pages 項目模板提供了一種用于捆綁和縮小的解決方案廊镜,它們構(gòu)成 JSON 配置文件。 第三方工具(如 Grunt 任務(wù)運行程序)以更復(fù)雜的方式完成相同的任務(wù)唉俗。 開發(fā)工作流需要捆綁和縮小之外的其他處理(如 linting 和圖像優(yōu)化)時嗤朴,第三方工具非常適用。 通過使用設(shè)計時捆綁和縮小虫溜,在應(yīng)用部署之前創(chuàng)建縮小文件雹姊。 在部署之前進(jìn)行捆綁和縮小具有減少服務(wù)器負(fù)載的優(yōu)點。 但是衡楞,必須認(rèn)識到吱雏,設(shè)計時捆綁和縮小會增加生成的復(fù)雜性,并且僅適用于靜態(tài)文件瘾境。

配置捆綁和縮小

備注

需要將 BuildBundlerMinifier NuGet 包添加到項目中使其正常工作歧杏。
在 ASP.NET Core 2.1 或更高版本中,將名為 bundleconfig.json 的新 JSON 文件添加到 MVC 或 Razor Pages 項目根目錄迷守。 在該文件中包含以下 JSON 作為起點:

[
  {
    "outputFileName": "wwwroot/css/site.min.css",
    "inputFiles": [
      "wwwroot/css/site.css"
    ]
  },
  {
    "outputFileName": "wwwroot/js/site.min.js",
    "inputFiles": [
      "wwwroot/js/site.js"
    ],
    "minify": {
      "enabled": true,
      "renameLocals": true
    },
    "sourceMap": false
  }
]

bundleconfig.json 文件定義每個捆綁的選項犬绒。 在前面的示例中,為自定義 JavaScript (wwwroot/js/site.js) 和樣式表 (wwwroot/css/site.css) 文件定義了單一捆綁配置 兑凿。

配置選項包括:

  • outputFileName:要輸出的捆綁文件的名稱凯力。 可包含 bundleconfig.json 文件中的相對路徑。 (必需)
  • inputFiles:要捆綁在一起的文件數(shù)組礼华。 這些是配置文件的相對路徑咐鹤。 可以選擇使用空值,*這將導(dǎo)致輸出文件為空圣絮。 支持 glob 模式祈惶。 - minify:輸出類型的縮小選項。 可選晨雳,默認(rèn)值 - minify: { enabled: true }
  • sourceMap:指示是否為捆綁的文件生成源映射的標(biāo)記血久。 可選,默認(rèn)值 - false
  • sourceMapRootPath:用于存儲所生成的源映射文件的根路徑帮非。

向工作流添加文件

假設(shè)添加了額外的 custom.css 文件氧吐,類似于以下內(nèi)容:

.about, [role=main], [role=complementary] {
    margin-top: 60px;
}

footer {
    margin-top: 10px;
}

若要縮小 custom.css 并將其與 site.css 捆綁到 site.min.css 文件中讹蘑,請將相對路徑添加到 bundleconfig.json :

[
  {
    "outputFileName": "wwwroot/css/site.min.css",
    "inputFiles": [
      "wwwroot/css/site.css",
      "wwwroot/css/custom.css"
    ]
  },
  {
    "outputFileName": "wwwroot/js/site.min.js",
    "inputFiles": [
      "wwwroot/js/site.js"
    ],
    "minify": {
      "enabled": true,
      "renameLocals": true
    },
    "sourceMap": false
  }
]

備注

或者,可以使用以下通配模式:

"inputFiles": ["wwwroot/**/!(*.min).css" ]

此通配模式匹配所有 CSS 文件筑舅,并排除縮小的文件模式座慰。

生成應(yīng)用程序。 打開 site.min.css 并注意 custom.css 的內(nèi)容將追加到文件末尾 翠拣。

基于環(huán)境的捆綁和縮小

最佳做法是版仔,應(yīng)在生產(chǎn)環(huán)境中使用應(yīng)用的捆綁文件和縮小文件。 在開發(fā)過程中误墓,原始文件可簡化應(yīng)用的調(diào)試蛮粮。
使用視圖中的環(huán)境標(biāo)記幫助程序指定要包含在頁面中的文件。 環(huán)境標(biāo)記幫助程序僅在特定環(huán)境中運行時呈現(xiàn)其內(nèi)容谜慌。
以下 environment 標(biāo)記將在 Development環(huán)境中運行時呈現(xiàn)未處理的 CSS 文件:

<environment include="Development">
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</environment>

以下 environment標(biāo)記將在非 Development 環(huán)境中運行時呈現(xiàn)捆綁的和縮小的 CSS 文件然想。 例如,在 ProductionStaging 中運行將觸發(fā)這些樣式表的呈現(xiàn):

<environment exclude="Development">
    <link rel="stylesheet" 
          asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
          asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
    <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>

從 Gulp 使用 bundleconfig.json

在某些情況下欣范,應(yīng)用的捆綁和縮小工作流需要額外處理变泄。 示例包括圖像優(yōu)化、緩存清除和 CDN 資產(chǎn)處理恼琼。 為了滿足這些要求妨蛹,可以將捆綁和縮小工作流轉(zhuǎn)換為使用 Gulp。

手動轉(zhuǎn)換捆綁和縮小工作流以使用 Gulp

將 package.json 文件(包含以下 devDependencies)添加到項目根:
警告

gulp-uglify 模塊不支持 ECMAScript (ES) 2015/ES6 和更高版本驳癌。 安裝 gulp-terser 而不是 gulp-uglify 來使用 ES2015/ES6 或更高版本滑燃。

"devDependencies": {
  "del": "^3.0.0",
  "gulp": "^4.0.0",
  "gulp-concat": "^2.6.1",
  "gulp-cssmin": "^0.2.0",
  "gulp-htmlmin": "^3.0.0",
  "gulp-uglify": "^3.0.0",
  "merge-stream": "^1.0.1"
}

通過在與 package.json 相同的級別運行以下命令來安裝依賴項:

npm i

安裝 Gulp CLI 作為全局依賴項:

npm i -g gulp-cli

將以下 gulpfile.js 文件復(fù)制到項目根:

'use strict';

var gulp = require('gulp'),
    concat = require('gulp-concat'),
    cssmin = require('gulp-cssmin'),
    htmlmin = require('gulp-htmlmin'),
    uglify = require('gulp-uglify'),
    merge = require('merge-stream'),
    del = require('del'),
    bundleconfig = require('./bundleconfig.json');

const regex = {
    css: /\.css$/,
    html: /\.(html|htm)$/,
    js: /\.js$/
};

gulp.task('min:js', async function () {
    merge(getBundles(regex.js).map(bundle => {
        return gulp.src(bundle.inputFiles, { base: '.' })
            .pipe(concat(bundle.outputFileName))
            .pipe(uglify())
            .pipe(gulp.dest('.'));
    }))
});

gulp.task('min:css', async function () {
    merge(getBundles(regex.css).map(bundle => {
        return gulp.src(bundle.inputFiles, { base: '.' })
            .pipe(concat(bundle.outputFileName))
            .pipe(cssmin())
            .pipe(gulp.dest('.'));
    }))
});

gulp.task('min:html', async function () {
    merge(getBundles(regex.html).map(bundle => {
        return gulp.src(bundle.inputFiles, { base: '.' })
            .pipe(concat(bundle.outputFileName))
            .pipe(htmlmin({ collapseWhitespace: true, minifyCSS: true, minifyJS: true }))
            .pipe(gulp.dest('.'));
    }))
});

gulp.task('min', gulp.series(['min:js', 'min:css', 'min:html']));

gulp.task('clean', () => {
    return del(bundleconfig.map(bundle => bundle.outputFileName));
});

gulp.task('watch', () => {
    getBundles(regex.js).forEach(
        bundle => gulp.watch(bundle.inputFiles, gulp.series(["min:js"])));

    getBundles(regex.css).forEach(
        bundle => gulp.watch(bundle.inputFiles, gulp.series(["min:css"])));

    getBundles(regex.html).forEach(
        bundle => gulp.watch(bundle.inputFiles, gulp.series(['min:html'])));
});

const getBundles = (regexPattern) => {
    return bundleconfig.filter(bundle => {
        return regexPattern.test(bundle.outputFileName);
    });
};

gulp.task('default', gulp.series("min"));

運行 Gulp 任務(wù)

若要在 Visual Studio 中生成項目之前觸發(fā) Gulp 縮小任務(wù):

  1. 安裝 BuildBundlerMinifier NuGet 包。
  2. 將以下 MSBuild 目標(biāo)添加到項目文件:
<Target Name="MyPreCompileTarget" BeforeTargets="Build">
  <Exec Command="gulp min" />
</Target>

在此示例中颓鲜,MyPreCompileTarget 目標(biāo)內(nèi)定義的所有任務(wù)在預(yù)定義的 Build 目標(biāo)之前運行表窘。 Visual Studio 的輸出窗口中顯示類似于以下內(nèi)容的輸出:

1>------ Build started: Project: BuildBundlerMinifierApp, Configuration: Debug Any CPU ------
1>BuildBundlerMinifierApp -> C:\BuildBundlerMinifierApp\bin\Debug\netcoreapp2.0\BuildBundlerMinifierApp.dll
1>[14:17:49] Using gulpfile C:\BuildBundlerMinifierApp\gulpfile.js
1>[14:17:49] Starting 'min:js'...
1>[14:17:49] Starting 'min:css'...
1>[14:17:49] Starting 'min:html'...
1>[14:17:49] Finished 'min:js' after 83 ms
1>[14:17:49] Finished 'min:css' after 88 ms
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

其他資源

參考資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市甜滨,隨后出現(xiàn)的幾起案子乐严,更是在濱河造成了極大的恐慌,老刑警劉巖衣摩,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昂验,死亡現(xiàn)場離奇詭異,居然都是意外死亡艾扮,警方通過查閱死者的電腦和手機(jī)既琴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泡嘴,“玉大人甫恩,你說我怎么就攤上這事∽糜瑁” “怎么了磺箕?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵奖慌,是天一觀的道長。 經(jīng)常有香客問我松靡,道長简僧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任雕欺,我火速辦了婚禮岛马,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘屠列。我一直安慰自己蛛枚,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布脸哀。 她就那樣靜靜地躺著,像睡著了一般扭吁。 火紅的嫁衣襯著肌膚如雪撞蜂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天侥袜,我揣著相機(jī)與錄音蝌诡,去河邊找鬼。 笑死枫吧,一個胖子當(dāng)著我的面吹牛浦旱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播九杂,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼颁湖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了例隆?” 一聲冷哼從身側(cè)響起甥捺,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎镀层,沒想到半個月后镰禾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡唱逢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年吴侦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坞古。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡备韧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绸贡,到底是詐尸還是另有隱情盯蝴,我是刑警寧澤毅哗,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站捧挺,受9級特大地震影響虑绵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜闽烙,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一翅睛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧黑竞,春花似錦捕发、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至遏匆,卻和暖如春法挨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背幅聘。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工凡纳, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人帝蒿。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓荐糜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親葛超。 傳聞我的和親對象是個殘疾皇子暴氏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容