前言
我的伺服器頻寬比較高,部落格部署在上面訪問的時候幾乎沒感覺有載入延遲,就沒做圖片這塊的最佳化,不過最近有小夥伴說部落格的圖片載入比較慢,那就來把圖片最佳化完善一下吧~
目前有兩個地方需要完善
- 圖片瀑布流
- 圖片縮圖
圖片瀑布流
關於瀑布流之前的文章有介紹: 基於.NetCore開發部落格專案 StarBlog - (10) 圖片瀑布流
不過當時直接套用的 Bootstrap5 例子程式碼,有偶爾顯示錯位的bug
我又去看了一下 masonry-layout 的官網,找到這個bug的原因:瀑布流在圖片還沒載入完成就渲染好了,而圖片的大小不一,造成了最終顯示錯位。
解決方法也很簡單,用 imagesLoaded 這個庫,它有個事件,在全部圖片載入完成後觸發,在事件響應裡面再渲染一次瀑布流,就搞定了~
masonry-layout 這個庫裡面不附帶 imagesLoaded ,要用必須自己安裝。
我用的版本是 5.0.0
yarn add imagesloaded
在 StarBlog.Web
的 gulpfile.js
裡配置一下路徑
// 使用 npm 下載的前端元件,自定義存放位置
const customLibs = [
// ...
{name: 'imagesloaded', dist: './node_modules/imagesloaded/*.js'},
]
然後執行 gulp move
接著,修改一下圖片頁面 StarBlog.Web/Views/Photography/Index.cshtml
引入 js 依賴,我這裡還用了 environment tag helper,可以根據不同的環境引入不同的檔案。在開發環境引入完整 js 檔案,生產環境引入 ``*.min` 檔案。
@section bottom {
<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/masonry-layout/dist/masonry.pkgd.js"></script>
<script src="~/lib/imagesloaded/imagesloaded.pkgd.js"></script>
</environment>
<environment exclude="Development">
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/masonry-layout/dist/masonry.pkgd.min.js"></script>
<script src="~/lib/imagesloaded/imagesloaded.pkgd.min.js"></script>
</environment>
<script src="~/js/photo.js"></script>
}
把圖片列表部分的程式碼改一下
<div id="photo-grid" class="row">
@foreach (var photo in Model.Photos) {
<div class="col-sm-6 col-lg-4 mb-4 grid-item">
<partial name="Widgets/PhotoCard" model="photo"/>
</div>
}
</div>
然後是 js/photo.js
裡的 js 程式碼
// init Masonry
let $grid = $('#photo-grid').masonry({
itemSelector: '.grid-item',
percentPosition: true,
})
// layout Masonry after each image loads
$grid.imagesLoaded().progress( function() {
$grid.masonry('layout');
});
搞定~
圖片縮圖
一開始我用的是 SixLabors.ImageSharp.Web 這個庫
挺方便的,以中介軟體的形式使用
透過 Nuget 安裝之後,在 program.cs
裡配置一下
// 註冊服務
builder.Services.AddImageSharp();
// 新增中介軟體
app.UseImageSharp();
之後就可以在任意圖片檔案的地址後面加上 width=xxx&format=xxx
這樣的引數來實現調整大小和轉換格式了~
圖片列表的每個圖片我做成了一個 partial view 元件,在 StarBlog.Web/Views/Shared/Widgets/PhotoCard.cshtml
這個檔案
要把這個改成縮圖,只需要修改一下 img
元素
現在每個圖片縮圖寬度300(寬度自適應),格式轉換成 webp
<img class="bd-placeholder-img card-img-top" src="/media/@Model.FilePath?width=300&format=webp" alt="">
這個中介軟體還有很多其他引數可以設定,我只用到兩個,詳情可以看文件: https://docs.sixlabors.com/articles/imagesharp.web/processingcommands.html
Progressive JPEG
本來用 ImageSharp.Web 中介軟體已經夠好了
但還有一點美中不足,就是它不支援生成 progressive JPEG 圖片,這樣就沒辦法在載入圖片的時候先顯示一個模糊的輪廓,再逐漸變清晰,而是從上到下一行一行載入,不好看~
所以,我用了 Magick.NET 這個庫來實現生成 progressive JPEG 格式的圖片。
這個庫有三種版本:Q8, Q16, Q16-HDRI
根據官網文件,我選擇了它推薦的 Q8 版本,效能最好 (圖片質量無所謂了)
使用 nuget 安裝 Magick.NET-Q8-AnyCPU
這個庫
修改 StarBlog.Web/Services/PhotoService.cs
現在我要來寫一個生成縮圖的方法
/// <summary>
/// 生成Progressive JPEG縮圖 (使用 MagickImage)
/// </summary>
public async Task<byte[]> GetThumb(string id, int width=300) {
var photo = await _photoRepo.Where(a => a.Id == id).FirstAsync();
using (var image = new MagickImage(GetPhotoFilePath(photo))) {
image.Format = MagickFormat.Pjpeg;
image.Resize(width,0);
return image.ToByteArray();
}
}
接著再寫個介面
編輯 StarBlog.Web/Apis/PhotoController.cs
[HttpGet("{id}/Thumb")]
public async Task<IActionResult> GetThumb(string id, [FromQuery] int width = 300) {
var data = await _photoService.GetThumb(id, width);
return new FileContentResult(data, "image/jpeg");
}
搞定。
現在只需要訪問 /Api/Photo/{圖片ID}/Thumb?width=300
這個地址,就可以生成 progressive JPEG 格式的縮圖了~
最後再來改造一下 StarBlog.Web/Views/Shared/Widgets/PhotoCard.cshtml
元件
<img class="bd-placeholder-img card-img-top" alt=""
src="@Url.Action("GetThumb", "Photo", new {id = Model.Id, width = 300})">
okk~
小結
相比起 ImageSharp.Web 中介軟體自帶快取的特性,我這個自己寫的縮圖方法是比較粗糙的,而且每次請求都是動態生成,會給伺服器帶來一定壓力。
不過它沒有 Progressive JPEG 呀,這個功能缺失真的太難受了,只能期待它早日實現這個功能吧~
不然就只能我自己來實現快取功能提高效能了~
系列文章
- 基於.NetCore開發部落格專案 StarBlog - (1) 為什麼需要自己寫一個部落格?
- 基於.NetCore開發部落格專案 StarBlog - (2) 環境準備和建立專案
- 基於.NetCore開發部落格專案 StarBlog - (3) 模型設計
- 基於.NetCore開發部落格專案 StarBlog - (4) markdown部落格批次匯入
- 基於.NetCore開發部落格專案 StarBlog - (5) 開始搭建Web專案
- 基於.NetCore開發部落格專案 StarBlog - (6) 頁面開發之部落格文章列表
- 基於.NetCore開發部落格專案 StarBlog - (7) 頁面開發之文章詳情頁面
- 基於.NetCore開發部落格專案 StarBlog - (8) 分類層級結構展示
- 基於.NetCore開發部落格專案 StarBlog - (9) 圖片批次匯入
- 基於.NetCore開發部落格專案 StarBlog - (10) 圖片瀑布流
- 基於.NetCore開發部落格專案 StarBlog - (11) 實現訪問統計
- 基於.NetCore開發部落格專案 StarBlog - (12) Razor頁面動態編譯
- 基於.NetCore開發部落格專案 StarBlog - (13) 加入友情連結功能
- 基於.NetCore開發部落格專案 StarBlog - (14) 實現主題切換功能
- 基於.NetCore開發部落格專案 StarBlog - (15) 生成隨機尺寸圖片
- 基於.NetCore開發部落格專案 StarBlog - (16) 一些新功能 (監控/統計/配置/初始化)
- 基於.NetCore開發部落格專案 StarBlog - (17) 自動下載文章裡的外部圖片
- 基於.NetCore開發部落格專案 StarBlog - (18) 實現本地Typora文章打包上傳
- 基於.NetCore開發部落格專案 StarBlog - (19) Markdown渲染方案探索
- 基於.NetCore開發部落格專案 StarBlog - (20) 圖片顯示最佳化