ABP Blazor 的 Bundling 和 Minification
Bundling(打包)指将多个JavaScript文件、CSS文件合并成一个或几个文件的过程。
Bundling的主要目的:
- 减少HTTP请求:通过合并文件,可以减少浏览器需要发起的HTTP请求数量,从而加快首页加载速度。
- 依赖管理:自动处理模块之间的依赖关系,确保代码正确执行。
- 代码分割:支持将代码分割成多个块(chunks),按需加载,进一步优化性能。
Minification(压缩)指在不更改功能的情况下从代码中删除不必要的字符,例如将变量名称缩短为一个字符、删除注释和不必要的空格。
Minification的主要目的:
- 减少文件体积:通过去除不必要的字符,可以显著减少文件的大小,从而减少传输的时间和带宽消耗。
- 提高加载速度:较小的文件可以更快的加载,加快页面的加载速度。
有许多方法可以打包(bundling)和压缩(minification)客户端资源(JavaScript和CSS文件)。最常见的方法是:
- 使用Bundler & Minifier Visual Studio扩展或NuGet包。
- 使用Gulp/Grunt任务管理器及其插件。
ABP是模块化的,各个模块使用的脚本和样式需要在index.html文件中引用。ABP提供了一种内置的方式,简单、动态、模块化地执行Bundling和Minification。
ABP的App.razor文件如下:
<!DOCTYPE html>
<html lang="@CultureInfo.CurrentCulture.Name" dir="@rtl">
<head>
...
<AbpStyles BundleName="@BlazorLeptonXLiteThemeBundles.Styles.Global" WebAssemblyStyleFiles="GlobalStyles" @rendermode="InteractiveAuto" />
...
</head>
<body class="abp-application-layout @rtl">
...
<AbpScripts BundleName="@BlazorLeptonXLiteThemeBundles.Scripts.Global" WebAssemblyScriptFiles="GlobalScripts" @rendermode="InteractiveAuto" />
<script src="_framework/blazor.web.js"></script>
</body>
</html>
@code{
private List<string> GlobalStyles =>
[
"global.css",
];
private List<string> GlobalScripts =>
[
"global.js"
];
}
<AbpStyles>
标签将输出为:
<link rel="stylesheet" href=“...” />
<AbpScripts>
标签将输出为:
<script src="..." />
对于Blazor Server和Blazor WebAssembly,执行Bundling和Minification的原理有所不同。
Blazor Server 中
Blazor Server中的 Bundling 和 Minification 是动态执行的,它与ABP MVC的Bundling过程很相似(使用的标签不同)。通过在模块类中ConfigureServices
方法中配置AbpBundlingOptions
选项,添加js和css bundle。
需要添加Volo.Abp.AspNetCore.Mvc.UI.Bundling
NuGet包,默认情况下,这个包已经安装在启动模板中。因此,大多数时候,您不需要手动安装它。如果没有使用启动模板,可以使用ABP CLI将其安装到项目中。在项目文件夹(包含.csproj
文件的文件夹)中执行以下命令:
abp add-package Volo.Abp.AspNetCore.Mvc.UI.Bundling
创建一个新的Bundle
Configure<AbpBundlingOptions>(options =>
{
options.ScriptBundles
.Add("MyGlobalBundle", bundle => {
bundle.AddFiles(
"/libs/jquery/jquery.js",
"/libs/bootstrap/js/bootstrap.js",
"/libs/toastr/toastr.min.js",
"/scripts/my-global-scripts.js"
);
});
});
配置现有的Bundle
Configure<AbpBundlingOptions>(options =>
{
options.StyleBundles.Configure(
BlazorLeptonXLiteThemeBundles.Styles.Global,
bundle =>
{
bundle.AddFiles("/blazor-global-styles.css");
//You can remove the following line if you don't use Blazor CSS isolation for components
bundle.AddFiles(new BundleFile("/Avalon.Blazor.styles.css", true));
bundle.AddFiles(new BundleFile("/Avalon.Blazor.Client.styles.css", true));
}
);
});
Bundle Contributor
可以创建一个BundleContributor
的派生类,更清晰的管理js和css文件。
public class BlazorLeptonXLiteThemeScriptContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/_content/Avalon.Abp.AspNetCore.Components.Web.LeptonXLiteTheme/side-menu/libs/bootstrap/js/bootstrap.bundle.js");
context.Files.AddIfNotContains("/_content/Avalon.Abp.AspNetCore.Components.Web.LeptonXLiteTheme/side-menu/libs/jquery/jquery.min.js");
context.Files.AddIfNotContains("/_content/Avalon.Abp.AspNetCore.Components.Web.LeptonXLiteTheme/side-menu/libs/bootstrap-datepicker/js/bootstrap-datepicker.min.js");
}
}
public class BlazorLeptonXLiteThemeStyleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/_content/Avalon.Abp.AspNetCore.Components.Web.LeptonXLiteTheme/side-menu/libs/chart.js/Chart.min.css");
context.Files.AddIfNotContains("/_content/Avalon.Abp.AspNetCore.Components.Web.LeptonXLiteTheme/side-menu/libs/bootstrap-datepicker/css/bootstrap-datepicker.min.css");
context.Files.AddIfNotContains("/_content/Avalon.Abp.AspNetCore.Components.Web.LeptonXLiteTheme/side-menu/libs/bootstrap-icons/font/bootstrap-icons.css");
var rtlPostfix = CultureHelper.IsRtl ? ".rtl" : string.Empty;
context.Files.AddIfNotContains($"/_content/Avalon.Abp.AspNetCore.Components.Web.LeptonXLiteTheme/side-menu/css/abp-bundle{rtlPostfix}.css");
context.Files.AddIfNotContains($"/_content/Avalon.Abp.AspNetCore.Components.Web.LeptonXLiteTheme/side-menu/css/blazor-bundle{rtlPostfix}.css");
context.Files.AddIfNotContains($"/_content/Avalon.Abp.AspNetCore.Components.Web.LeptonXLiteTheme/side-menu/css/bootstrap-dim{rtlPostfix}.css");
context.Files.AddIfNotContains($"/_content/Avalon.Abp.AspNetCore.Components.Web.LeptonXLiteTheme/side-menu/css/layout-bundle{rtlPostfix}.css");
context.Files.AddIfNotContains($"/_content/Avalon.Abp.AspNetCore.Components.Web.LeptonXLiteTheme/side-menu/css/font-bundle{rtlPostfix}.css");
}
}
在模块类中ConfigureServices
方法中如下配置AbpBundlingOptions
选项:
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpBundlingOptions>(options =>
{
options.StyleBundles
.Add(BlazorLeptonXLiteThemeBundles.Styles.Global, bundle =>
{
bundle.AddContributors(typeof(BlazorLeptonXLiteThemeStyleContributor));
});
options.ScriptBundles
.Add(BlazorLeptonXLiteThemeBundles.Scripts.Global, bundle =>
{
bundle.AddContributors(typeof(BlazorLeptonXLiteThemeScriptContributor));
});
});
}
Contributor依赖
一个bundle contributor可以对其他contributor有一个或多个依赖关系
[DependsOn(typeof(MyDependedBundleContributor))] //Define the dependency
public class MyExtensionStyleBundleContributor : BundleContributor
{
//...
}
当添加一个bundle contributor时,它的依赖项会自动地递归添加。依赖根据依赖顺序添加并去重。
标准Package的Contributors
所有标准NPM包都有内置的contributor。例如,如果您的contributor依赖于bootstrap,您可以直接声明它,而不是自己添加bootstrap.css。
[DependsOn(typeof(BootstrapStyleContributor))] //Define the bootstrap style dependency
public class MyExtensionStyleBundleContributor : BundleContributor
{
//...
}
使用标准包的内置contributors的优点:
- 防止您键入无效的资源路径。
- 防止在资源路径更改时更改您的contributor(依赖的contributor将处理它)。
- 防止多个模块添加重复的文件。
- 递归地管理依赖项(必要时添加依赖项的依赖项)。
需要按照Volo.Abp.AspNetCore.Mvc.UI.Packages
NuGet包。默认情况下,这个包已经安装在启动模板中。因此,大多数时候,您不需要手动安装它。如果没有使用启动模板,可以使用ABP CLI将其安装到项目中。在项目文件夹(包含.csproj
文件的文件夹)中执行以下命令:
abp add-package Volo.Abp.AspNetCore.Mvc.UI.Packages
访问IServiceProvider
虽然很少需要,但BundleConfigurationContext
有一个ServiceProvider
属性,你可以在ConfigureBundle
方法中解析服务依赖。
Bundle继承
在某些特定情况下,可能需要创建从其他bundle继承的新bundle。从一个bundle继承(递归地)将继承该bundle的所有文件和contributors。然后,派生的bundle可以添加或修改文件和contributors,而无需修改原始bundle。例子:
services.Configure<AbpBundlingOptions>(options =>
{
options
.StyleBundles
.Add("MyTheme.MyGlobalBundle", bundle => {
bundle
.AddBaseBundles("MyGlobalBundle") //Can add multiple
.AddFiles(
"/styles/mytheme-global-styles.css"
);
});
});
Bundling模式
在development
环境中,ABP将包文件分开添加到页面中。ABP会为其他环境(staging
、production
……)自动进行打包和最小化。大多数情况下,这是你想要的行为。但是,在某些情况下,您可能需要手动配置它。有四种模式:
-
Auto
: 根据环境自动确定模式。 -
None
: 没有捆绑或缩小。 -
Bundle
: 捆绑但不缩小。 -
BundleAndMinify
: 捆绑和缩小。
你可以在模块的ConfigureServices
中配置AbpBundlingOptions
。
示例:
Configure<AbpBundlingOptions>(options =>
{
options.Mode = BundlingMode.Bundle;
});
Blazor WebAssembly中
Blazor WebAssembly中的 Bundling 和 Minification 是不是动态执行的,而是通过bundle命令执行。
创建Bundle Contributor
在Blazor WebAssembly项目中,创建一个实现IBundleContributor
接口的类。
IBundleContributor
接口包含两个方法,都以BundleContext
作为参数:
-
AddScripts(...)
-
AddStyles(...)
public class MyProjectBundleContributor : IBundleContributor
{
public void AddScripts(BundleContext context)
{
context.Add("site.js");
}
public void AddStyles(BundleContext context)
{
context.Add("main.css");
context.Add("custom-styles.css");
}
}
默认情况下,启动模板中有一个实现
IBundleContributor
接口的<ProjectName>BundleContributor
类。所以,大多数时候,您不需要手动添加它。
配置
在Blazor WebAssembly项目的wwwroot/appsettings.json
文件的AbpCli.Bundle
节点中包含了Bundling配置。
示例如下:
{
"AbpCli": {
"Bundle": {
"Mode": "BundleAndMinify", /* Options: None, Bundle, BundleAndMinify */
"Name": "global",
"IsBlazorWebApp": true,
"InteractiveAuto": true,
"Parameters": {
}
}
}
}
-
Mode
:捆绑和缩小模式。可用的值有:-
BundleAndMinify
:将所有文件捆绑到一个文件中,并缩小内容。 -
Bundle
:将所有文件捆绑成一个文件,但不要缩小。 -
None
:单独添加文件,不要捆绑。
-
-
Name
:包文件名。默认值为global
。 -
Parameters
:您可以在此部分中定义其他键/值对参数。abp bundle
命令自动将这些参数发送给bundle贡献者,您可以在bundle贡献者中检查这些参数,并根据这些值采取一些操作。例如想要从bundle中排除某些资源:public class MyProjectNameBundleContributor : IBundleContributor { public void AddScripts(BundleContext context) { } public void AddStyles(BundleContext context) { var excludeThemeFromBundle = bool.Parse(context.Parameters.GetValueOrDefault("ExcludeThemeFromBundle")); context.Add("mytheme.css", excludeFromBundle: excludeThemeFromBundle); context.Add("main.css"); } }
bundle命令
在Blazor WebAssembly项目中执行bundle命令:
abp bundle
bundle命令将检测IBundleContributor
接口的实现类中包含的js和css,并读取appsettings.json
文件中的配置,根据配置打包资源,并更新index.html
文件。
例如,根据以上配置,将在wwwroot
生成global.css
和global.js
bundle包,在App.razor文件文件的<AbpStyles>
标签和<AbpScripts>
标签的WebAssemblyScriptFiles
属性中引用了这两个bundle包。
本文来自博客园,作者:星墨,转载请注明原文链接:https://www.cnblogs.com/yada/p/18657370
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix