Bundle và minify js, css trong ASP.NET MVC
Các kỹ thuật bundle (gói các tập tin) và minify (rút gọn tập tin) đã được giới thiệu trong ASP.NET MVC 4 để cải thiện thời gian tải trang.
Bundle trong ASP.NET MVC
Bundle cho phép chúng ta tải một loạt các tập tin tĩnh từ máy chủ trong một yêu cầu HTTP duy nhất.
Hình sau minh họa kỹ thuật bundle:
Trong hình trên, trình duyệt gửi hai yêu cầu riêng biệt để tải hai tệp JavaScript khác nhau MyJavaScriptFile-1.js
và MyJavaScriptFile-2.js
.
Kỹ thuật bundle trong ASP.NET MVC cho phép chúng ta tải nhiều hơn một tệp JavaScript MyJavaScriptFile-1.js
và MyJavaScriptFile-2.js
trong một yêu cầu, như được hiển thị bên dưới.
Các loại bundle trong ASP.NET MVC
MVC 5 bao gồm các lớp bundle sau trong namespace System.web.Optimization
:
- ScriptBundle: ScriptBundle chịu trách nhiệm gộp một hoặc nhiều tập tin JavaScript.
- StyleBundle: StyleBundle chịu trách nhiệm gộp một hoặc nhiều tập tin CSS.
- DynamicFolderBundle: Đại diện cho một đối tượng Bundle mà ASP.NET tạo từ một thư mục chứa các tập tin cùng loại.
Minify trong ASP.NET MVC
Kỹ thuật minify (rút gọn tập tin) tối ưu hóa kích thước tập tin JavaScript hoặc CSS bằng cách loại bỏ khoảng trắng và chú thích không cần thiết, đồng thời rút ngắn tên biến thành một ký tự.
Ví dụ: hãy xem hàm JavaScript sau.
sayHello = function(name){
//this is comment
var msg = "Hello" + name;
alert(msg);
}
Minify sẽ loại bỏ các khoảng trắng không cần thiết, chú thích và rút ngắn tên biến để giảm ký tự, điều này sẽ làm giảm kích thước của tập tin JavaScript. JavaScript trên sẽ được thu nhỏ thành dạng sau.
sayHello=function(n){var t="Hello"+n;alert(t)}
Bundle và minify giúp giảm thời gian tải của trang, từ đó nâng cao trải nghiệm của người dùng.
Bundle các tập tin JavaScript bằng ScriptBundle trong ASP.NET MVC
Ở phần này, bạn sẽ học cách gói nhiều tập tin JavaScript và trả về trong một yêu cầu HTTP duy nhất trong ASP.NET MVC.
Lớp ScriptBundle được sử dụng để gói và rút gọn các tập tin JavaScript. Bạn có thể gói và rút gọn các tập tin JavaScript và CSS trong lớp BundleConfig
nằm trong thư mục App_Start
trong một project ASP.NET MVC. (bạn có thể tạo lớp tùy chỉnh của riêng mình thay vì sử dụng lớp BundleConfig, nhưng bạn nên làm theo thông lệ tiêu chuẩn.)
Ví dụ sau minh họa cách tạo bundle cho các tập tin JavaScript.
using System.Web;
using System.Web.Optimization;
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/bs-jq-bundle").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/jquery-3.3.1.js"));
//the following creates bundles in debug mode;
//BundleTable.EnableOptimizations = true;
}
}
Trong ví dụ trên, chúng ta đã tạo một bundle mới bằng cách tạo một thể hiện của lớp ScriptBundle
và chỉ định đường dẫn ảo và tên bundle trong phương thức khởi tạo.
~/bundles/
là một đường dẫn ảo và bs-jq-bundle
là tên của gói. Sau đó, chúng ta đã thêm hai tập tin bootstrap.js
và jquery-3.3.1.js
vào gói này.
Phương thức bundles.Add()
được sử dụng để thêm các gói mới vào BundleCollection
. Theo mặc định, gói bs-jq-bundle
trên sẽ được tạo ở chế độ phát hành (release). Sử dụng BundleTable.EnableOptimizations = true
nếu bạn muốn xem các gói trong chế độ debug.
Bây giờ, để đưa bs-jq-bundle
trên vào trang web của bạn, hãy sử dụng phương thức Scripts.Render()
trong layout view, như được trình bày bên dưới.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title</title>
@Scripts.Render("~/bundles/bootstrap")
</head>
<body>
@*html code removed for clarity *@
</body>
</html>
Bây giờ, khi bạn chạy ứng dụng ở chế độ phát hành (release), bạn sẽ thấy gói được tạo và tải trong một yêu cầu duy nhất.
Thêm một thư mục vào bundle
Sử dụng phương thức IncludeDirectory
để thêm tất cả các tập tin trong một thư mục cụ thể trong một gói, như được hiển thị bên dưới.
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/scripts")
.IncludeDirectory("~/Scripts/","*.js", true));
}
Sử dụng ký tự đại diện (Wildcard)
Hầu hết các tập tin JavaScript của bên thứ ba kèm theo phiên bản trong tên của tập tin JavaScript. Ví dụ: jQuery bao gồm phiên bản trong tên tệp. Ký tự đại diện {version}
sẽ tự động chọn một phiên bản tập tin có sẵn.
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery")
.Include( "~/Scripts/jquery-{version}.js"));
}
}
Sử dụng CDN
Bạn cũng có thể tạo một nhóm các tệp từ Mạng phân phối nội dung (CDN – Content Delivery Network), như được hiển thị bên dưới.
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
var cdnPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js";
bundles.Add(new ScriptBundle("~/bundles/jquery", cdnPath)
.Include( "~/Scripts/jquery-{version}.js"));
}
}
Ghi chú: ASP.NET MVC gọi
BundleConfig.RegisterBundle()
từ sự kiệnApplication_Start
trong tập tinGlobal.asax.cs
. Vì vậy, tất cả các gói được thêm vàoBundleCollection
khi bắt đầu một ứng dụng.
Bundle các tập tin CSS bằng StyleBundle trong ASP.NET MVC
Ở phần này, bạn sẽ học cách kết hợp nhiều tập tin CSS (Cascading Style Sheet) để trả lại nó trong một yêu cầu HTTP duy nhất.
ASP.NET MVC sử dụng lớp StyleBundle để thực hiện việc gói và rút gọn các tập tin CSS. Tương tự như ScriptBundle, tất cả các gói CSS phải được tạo trong lớp BundleConfig
trong thư mục App_Start
.
Ví dụ sau đây cho thấy cách kết hợp nhiều tập tin CSS thành một gói.
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new StyleBundle("~/bundles/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"
));
// add ScriptBundle here..
}
}
Trong ví dụ trên, chúng ta đã tạo một gói CSS mới bằng cách tạo một thể hiện của lớp StyleBundle
và chỉ định đường dẫn ảo và tên gói trong phương thức khởi tạo.
~/bundles/
là một đường dẫn ảo và css
là tên gói. Sau đó, chúng ta đã thêm hai tập tin bootstrap.css
và site.css
vào gói này.
Phương thức bundles.Add()
được sử dụng để thêm các gói mới vào BundleCollection
. Theo mặc định, gói CSS trên sẽ được tạo ở chế độ phát hành (release). Sử dụng BundleTable.EnableOptimizations = true
nếu bạn muốn xem các gói trong chế độ debug.
Bây giờ, để đưa gói CSS ở trên vào trang web của bạn, hãy sử dụng phương thức Styles.Render()
trong layout view, như được hiển thị bên dưới.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/bundles/css")
</head>
<body>
@*html code removed for clarity *@
</body>
</html>
Bây giờ, khi bạn chạy ứng dụng ở chế độ phát hành, bạn sẽ thấy gói được tạo và tải trong một yêu cầu duy nhất.
Bạn có thể sử dụng phương thức IncludeDirectory()
, ký tự đại diện phiên bản {version}
và đường dẫn CDN giống như ScriptBundle.
Cách thiết lập đường dẫn hình ảnh trong StyleBundle
Chúng ta đã biết phương thức Include()
của lớp Bundle chấp nhận một tên tệp với một đường dẫn ảo.
Nếu bạn mở trình gỡ lỗi của trình duyệt, bạn có thể thấy rằng tập tin css đã được tải với mã trạng thái 200.
Tuy nhiên, nếu tập tin site.css chứa hình ảnh với đường dẫn tuyệt đối, thì hình ảnh sẽ không tải được. Ví dụ: tập tin site.css sau đây của chúng tôi có một kiểu footer được hiển thị bên dưới.
footer
{
background:url(../images/border_btm.png) top repeat-x;
padding:15px;
color:#618eac;
margin-top:15px;
}
Kiểu footer ở trên có sử dụng hình nền, nằm trong thư mục images riêng biệt.
Tuy nhiên, trình duyệt sẽ báo lỗi 404 vì nó không thể tìm thấy hình ảnh.
Trình duyệt sẽ xem xét đường dẫn ảo cho bất kỳ đường dẫn nào được đưa ra trong tập tin css. Nó sẽ cố gắng tải hình ảnh từ máy chủ lưu trữ.
Giải pháp:
Nếu bạn sử dụng một đường dẫn tuyệt đối trong css của mình cho hình ảnh thì bạn có thể chỉ định lớp chuyển đổi CssRewriteUrlTransform.
Lớp CssRewriteUrlTransform
viết lại url cho đường dẫn tuyệt đối.
bundles.Add(new StyleBundle("~/bundles/css").Include(
"~/Content/css/site.css",
new CssRewriteUrlTransform()
));
Bây giờ, đường dẫn hình ảnh trong tập tin css sẽ được chuyển thành đường dẫn tuyệt đối.
Như bạn có thể thấy trong hình trên, hình ảnh được tải bằng đường dẫn tuyệt đối từ thư mục gốc.