Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bundle command supports maui-blazor project #14637

Merged
merged 2 commits into from
Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions docs/en/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Here, is the list of all available commands before explaining their details:
* **`login`**: Authenticates on your computer with your [abp.io](https://abp.io/) username and password.
* **`login-info`**: Shows the current user's login information.
* **`logout`**: Logouts from your computer if you've authenticated before.
* **`bundle`**: Generates script and style references for an ABP Blazor project.
* **`bundle`**: Generates script and style references for ABP Blazor and MAUI Blazor project.
* **`install-libs`**: Install NPM Packages for MVC / Razor Pages and Blazor Server UI types.

### help
Expand Down Expand Up @@ -531,7 +531,7 @@ abp logout

### bundle

This command generates script and style references for an ABP Blazor WebAssembly project and updates the **index.html** file. It helps developers to manage dependencies required by ABP modules easily. In order ```bundle``` command to work, its **executing directory** or passed ```--working-directory``` parameter's directory must contain a Blazor project file(*.csproj).
This command generates script and style references for ABP Blazor WebAssembly and MAUI Blazor project and updates the **index.html** file. It helps developers to manage dependencies required by ABP modules easily. In order ```bundle``` command to work, its **executing directory** or passed ```--working-directory``` parameter's directory must contain a Blazor or MAUI Blazor project file(*.csproj).

Usage:

Expand All @@ -543,8 +543,11 @@ abp bundle [options]

* ```--working-directory``` or ```-wd```: Specifies the working directory. This option is useful when executing directory doesn't contain a Blazor project file.
* ```--force``` or ```-f```: Forces to build project before generating references.
* ```--project-type``` or ```-t```: Specifies the project type. Default type is `webassembly`. Available types:
* `webassembly`
* `maui-blazor`

`bundle` command reads the `appsettings.json` file inside the Blazor project for bundling options. For more details about managing style and script references in Blazor apps, see [Managing Global Scripts & Styles](UI/Blazor/Global-Scripts-Styles.md)
`bundle` command reads the `appsettings.json` file inside the Blazor and MAUI Blazor project for bundling options. For more details about managing style and script references in Blazor or MAUI Blazor apps, see [Managing Global Scripts & Styles](UI/Blazor/Global-Scripts-Styles.md)

### install-libs

Expand Down
21 changes: 21 additions & 0 deletions docs/zh-Hans/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ dotnet tool update -g Volo.Abp.Cli
* **`login`**: 使用你在[abp.io](https://abp.io/)的用户名和密码在你的计算机上认证.
* **`login-info`**: 展示当前登录用户信息.
* **`logout`**: 在你的计算机注销认证.
* **`bundle`**: 为 ABP Blazor 和 MAUI Blazor 项目生成引用的脚本和样式.
* **`install-libs`**: 为 MVC / Razor Pages 和 Blazor Server UI 类型安装NPM包.

### help
Expand Down Expand Up @@ -432,6 +433,26 @@ abp login-info
abp logout
```

### bundle

这个命令为ABP Blazor WebAssembly 和 MAUI Blazor 项目生成引用的脚本和样式并且更新 **index.html** 文件, 它帮助开发者轻松的管理ABP模块的依赖. 为了使 ```bundle``` 命令工作, 它的**执行目录**或者传递 ```--working-directory``` 参数的目录必须包含Blazor或MAUI Blazor项目文件(*.csproj)

用法:

````bash
abp bundle [options]
````

#### Options

* ```--working-directory``` 或 ```-wd```: 指定当前执行目录, 这个命令在当前目录不包含项目文件时非常有用.
* ```--force``` 或 ```-f```: 在生成引用之前强制构建项目.
* ```--project-type``` 或 ```-t```: 指定项目类型. 默认类型是 `webassembly`. 可用的类型有:
* `webassembly`
* `maui-blazor`

`bundle` command reads the `appsettings.json` file inside the Blazor and MAUI Blazor project for bundling options. For more details about managing style and script references in Blazor or MAUI Blazor apps, see [Managing Global Scripts & Styles](UI/Blazor/Global-Scripts-Styles.md)

### install-libs

为 MVC / Razor Pages 和 Blazor Server UI 类型安装NPM包, 它的 **执行目录** 或者传递的 ```--working-directory``` 目录必须包含一个项目文件(*.csproj).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public class BundleOptions

[NotNull]
public string ProjectFileName { get; set; }

[NotNull]
public string ProjectType { get; set; }

public bool Minify { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public string Bundle(BundleOptions options, BundleContext context)
var bundleFileDefinitions = context.BundleDefinitions.Where(t => t.ExcludeFromBundle == false).ToList();
var fileDefinitionsExcludingFromBundle = context.BundleDefinitions.Where(t => t.ExcludeFromBundle).ToList();

var bundledContent = BundleFiles(options, bundleFileDefinitions);
var bundledContent = options.ProjectType == BundlingConsts.WebAssembly? BundleWebAssemblyFiles(options, bundleFileDefinitions) : BundleMauiBlazorFiles(options, bundleFileDefinitions);
File.WriteAllText(bundleFilePath, bundledContent);

return GenerateDefinition(bundleFilePath,fileDefinitionsExcludingFromBundle);
Expand All @@ -59,7 +59,7 @@ private bool IsMinFile(string fileName, string content)
return false;
}

private string BundleFiles(BundleOptions options, List<BundleDefinition> bundleDefinitions)
private string BundleWebAssemblyFiles(BundleOptions options, List<BundleDefinition> bundleDefinitions)
{
var staticAssetsFilePath = Path.Combine(options.Directory, "bin", "Debug", options.FrameworkVersion,
$"{options.ProjectFileName}.staticwebassets.runtime.json");
Expand Down Expand Up @@ -99,7 +99,7 @@ private string BundleFiles(BundleOptions options, List<BundleDefinition> bundleD
var fileName =
definition.Source.Substring(slashIndex + 1, definition.Source.Length - slashIndex - 1);
var filePath =
Path.Combine(PathHelper.GetFrameworkFolderPath(options.Directory, options.FrameworkVersion),
Path.Combine(PathHelper.GetWebAssemblyFrameworkFolderPath(options.Directory, options.FrameworkVersion),
fileName);
content = GetFileContent(filePath, false);
}
Expand All @@ -119,6 +119,29 @@ private string BundleFiles(BundleOptions options, List<BundleDefinition> bundleD
}
}

private string BundleMauiBlazorFiles(BundleOptions options, List<BundleDefinition> bundleDefinitions)
{
var builder = new StringBuilder();
foreach (var definition in bundleDefinitions)
{
var filePath = Path.Combine(definition.Source.Split('/'));

var fileFullPath = Directory.GetFiles(options.Directory, string.Empty, SearchOption.AllDirectories).FirstOrDefault(x => x.EndsWith(filePath));
if(fileFullPath == null)
{
throw new AbpException("Not found: " + definition.Source);
}

var content = GetFileContent(fileFullPath, options.Minify);
content = ProcessBeforeAddingToTheBundle(definition.Source, Path.Combine(options.Directory, "wwwroot"),
content);

builder.AppendLine(content);
}

return builder.ToString();
}

private string GetFileContent(string filePath, bool minify)
{
var content = File.ReadAllText(filePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ internal static class BundlingConsts
internal const string ScriptPlaceholderStart = "<!--ABP:Scripts-->";
internal const string ScriptPlaceholderEnd = "<!--/ABP:Scripts-->";
internal const string SupportedWebAssemblyProjectType = "Microsoft.NET.Sdk.BlazorWebAssembly";
internal const string SupportedMauiBlazorProjectType = "Microsoft.NET.Sdk.Razor";
internal const string WebAssembly = "webassembly";
internal const string MauiBlazor = "maui-blazor";
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class BundlingService : IBundlingService, ITransientDependency
public IStyleBundler StyleBundler { get; set; }
public IConfigReader ConfigReader { get; set; }

public async Task BundleAsync(string directory, bool forceBuild)
public async Task BundleAsync(string directory, bool forceBuild, string projectType = BundlingConsts.WebAssembly)
{
var projectFiles = Directory.GetFiles(directory, "*.csproj");
if (!projectFiles.Any())
Expand All @@ -40,9 +40,9 @@ public async Task BundleAsync(string directory, bool forceBuild)

var projectFilePath = projectFiles[0];

CheckProjectIsSupportedType(projectFilePath);
CheckProjectIsSupportedType(projectFilePath, projectType);

var config = ConfigReader.Read(PathHelper.GetWwwRootPath(directory));
var config = projectType == BundlingConsts.WebAssembly? ConfigReader.Read(PathHelper.GetWwwRootPath(directory)): ConfigReader.Read(directory);
var bundleConfig = config.Bundle;

if (forceBuild)
Expand All @@ -55,17 +55,17 @@ public async Task BundleAsync(string directory, bool forceBuild)
DotNetProjectBuilder.BuildProjects(projects, string.Empty);
}

var frameworkVersion = GetTargetFrameworkVersion(projectFilePath);
var frameworkVersion = GetTargetFrameworkVersion(projectFilePath, projectType);
var projectName = Path.GetFileNameWithoutExtension(projectFilePath);
var assemblyFilePath = PathHelper.GetAssemblyFilePath(directory, frameworkVersion, projectName);
var assemblyFilePath = projectType == BundlingConsts.WebAssembly? PathHelper.GetWebAssemblyFilePath(directory, frameworkVersion, projectName) : PathHelper.GetMauiBlazorAssemblyFilePath(directory, projectName);
var startupModule = GetStartupModule(assemblyFilePath);

var bundleDefinitions = new List<BundleTypeDefinition>();
FindBundleContributorsRecursively(startupModule, 0, bundleDefinitions);
bundleDefinitions = bundleDefinitions.OrderByDescending(t => t.Level).ToList();

var styleContext = GetStyleContext(bundleDefinitions, bundleConfig.Parameters);
var scriptContext = GetScriptContext(bundleDefinitions, bundleConfig.Parameters);
var scriptContext = GetScriptContext(bundleDefinitions, bundleConfig.Parameters, projectType);
string styleDefinitions;
string scriptDefinitions;

Expand All @@ -77,7 +77,8 @@ public async Task BundleAsync(string directory, bool forceBuild)
FrameworkVersion = frameworkVersion,
ProjectFileName = projectName,
BundleName = bundleConfig.Name.IsNullOrEmpty() ? "global" : bundleConfig.Name,
Minify = bundleConfig.Mode == BundlingMode.BundleAndMinify
Minify = bundleConfig.Mode == BundlingMode.BundleAndMinify,
ProjectType = projectType
};

Logger.LogInformation("Generating style bundle...");
Expand All @@ -101,17 +102,20 @@ public async Task BundleAsync(string directory, bool forceBuild)
}

private BundleContext GetScriptContext(List<BundleTypeDefinition> bundleDefinitions,
BundleParameterDictionary parameters)
BundleParameterDictionary parameters, string projectType)
{
var scriptContext = new BundleContext
{
Parameters = parameters
};

scriptContext.BundleDefinitions.AddIfNotContains(
x => x.Source == "_framework/blazor.webassembly.js",
() => new BundleDefinition { Source = "_framework/blazor.webassembly.js" });

if (projectType == BundlingConsts.WebAssembly)
{
scriptContext.BundleDefinitions.AddIfNotContains(
x => x.Source == "_framework/blazor.webassembly.js",
() => new BundleDefinition { Source = "_framework/blazor.webassembly.js" });
}

foreach (var bundleDefinition in bundleDefinitions)
{
var contributor = CreateContributorInstance(bundleDefinition.BundleContributorType);
Expand Down Expand Up @@ -283,24 +287,41 @@ private Type GetStartupModule(string assemblyPath)
.SingleOrDefault(AbpModule.IsAbpModule);
}

private string GetTargetFrameworkVersion(string projectFilePath)
private string GetTargetFrameworkVersion(string projectFilePath, string projectType)
{
var document = new XmlDocument();
document.Load(projectFilePath);

return document.SelectSingleNode("//TargetFramework").InnerText;
return projectType switch {
BundlingConsts.WebAssembly => document.SelectSingleNode("//TargetFramework").InnerText,
BundlingConsts.MauiBlazor => document.SelectNodes("//TargetFrameworks")[0].InnerText,
_ => null
};
}

private void CheckProjectIsSupportedType(string projectFilePath)
private void CheckProjectIsSupportedType(string projectFilePath, string projectType)
{
var document = new XmlDocument();
document.Load(projectFilePath);

var sdk = document.DocumentElement.GetAttribute("Sdk");
if (sdk != BundlingConsts.SupportedWebAssemblyProjectType)

switch (projectType)
{
throw new BundlingException(
$"Unsupported project type. Project type must be {BundlingConsts.SupportedWebAssemblyProjectType}.");
case BundlingConsts.WebAssembly:
if (sdk != BundlingConsts.SupportedWebAssemblyProjectType)
{
throw new BundlingException(
$"Unsupported project type. Project type must be {BundlingConsts.SupportedWebAssemblyProjectType}.");
}
break;
case BundlingConsts.MauiBlazor:
if (sdk != BundlingConsts.SupportedMauiBlazorProjectType)
{
throw new BundlingException(
$"Unsupported project type. Project type must be {BundlingConsts.SupportedMauiBlazorProjectType}.");
}
break;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ namespace Volo.Abp.Cli.Bundling;

public interface IBundlingService
{
Task BundleAsync(string directory, bool forceBuild);
Task BundleAsync(string directory, bool forceBuild, string projectType = BundlingConsts.WebAssembly);
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
using System.IO;
using System.Linq;

namespace Volo.Abp.Cli.Bundling;

internal static class PathHelper
{
internal static string GetFrameworkFolderPath(string projectDirectory, string frameworkVersion)
internal static string GetWebAssemblyFrameworkFolderPath(string projectDirectory, string frameworkVersion)
{
return Path.Combine(projectDirectory, "bin", "Debug", frameworkVersion, "wwwroot", "_framework"); ;
}

internal static string GetAssemblyFilePath(string directory, string frameworkVersion, string projectFileName)
internal static string GetWebAssemblyFilePath(string directory, string frameworkVersion, string projectFileName)
{
var outputDirectory = GetFrameworkFolderPath(directory, frameworkVersion);
var outputDirectory = GetWebAssemblyFrameworkFolderPath(directory, frameworkVersion);
return Path.Combine(outputDirectory, projectFileName + ".dll");
}

internal static string GetMauiBlazorAssemblyFilePath(string directory, string projectFileName)
{
return Directory.GetFiles(directory, "*.dll", SearchOption.AllDirectories).First(f => !f.Contains("android") && f.EndsWith(projectFileName + ".dll"));
}

internal static string GetWwwRootPath(string directory)
{
return Path.Combine(directory, "wwwroot");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Threading.Tasks;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Bundling;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;

namespace Volo.Abp.Cli.Commands;
Expand All @@ -29,7 +30,8 @@ public async Task ExecuteAsync(CommandLineArgs commandLineArgs)

var forceBuild = commandLineArgs.Options.ContainsKey(Options.ForceBuild.Short) ||
commandLineArgs.Options.ContainsKey(Options.ForceBuild.Long);


var projectType = GetProjectType(commandLineArgs);

if (!Directory.Exists(workingDirectory))
{
Expand All @@ -42,7 +44,7 @@ public async Task ExecuteAsync(CommandLineArgs commandLineArgs)

try
{
await BundlingService.BundleAsync(workingDirectory, forceBuild);
await BundlingService.BundleAsync(workingDirectory, forceBuild, projectType);
}
catch (BundlingException ex)
{
Expand All @@ -68,11 +70,24 @@ public string GetUsageInfo()
sb.AppendLine("");
sb.AppendLine("-wd|--working-directory <directory-path> (default: empty)");
sb.AppendLine("-f | --force (default: false)");
sb.AppendLine("-t | --project-type (default: webassembly)");
sb.AppendLine("");
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI");

return sb.ToString();
}

private string GetProjectType(CommandLineArgs commandLineArgs)
{
var projectType = commandLineArgs.Options.GetOrNull(Options.ProjectType.Short, Options.ProjectType.Long);
projectType ??= BundlingConsts.WebAssembly;

return projectType.ToLower() switch {
"webassembly" => BundlingConsts.WebAssembly,
"maui-blazor" => BundlingConsts.MauiBlazor,
_ => throw new CliUsageException(ExceptionMessageHelper.GetInvalidOptionExceptionMessage("Project Type"))
};
}

public static class Options
{
Expand All @@ -82,6 +97,12 @@ public static class WorkingDirectory
public const string Long = "working-directory";
}

public static class ProjectType
{
public const string Short = "t";
public const string Long = "project-type";
}

public static class ForceBuild
{
public const string Short = "f";
Expand Down