Skip to content

Commit

Permalink
Merge pull request #14637 from abpframework/liangshiwei/cli-maui
Browse files Browse the repository at this point in the history
Bundle command supports maui-blazor project
  • Loading branch information
maliming authored Nov 14, 2022
2 parents e9e1c89 + cd81402 commit a2bc40f
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 30 deletions.
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

0 comments on commit a2bc40f

Please sign in to comment.