Adds bundle options to the package manifest

to more control over how bundling works for static file processing for app_plugins
This commit is contained in:
Shannon
2021-07-15 13:26:32 -06:00
parent 91d5820982
commit df9c4a0160
17 changed files with 373 additions and 90 deletions

View File

@@ -64,7 +64,7 @@ namespace Umbraco.Cms.Core.Configuration.Grid
}
// add manifest editors, skip duplicates
foreach (var gridEditor in _manifestParser.Manifest.GridEditors)
foreach (var gridEditor in _manifestParser.CombinedManifest.GridEditors)
{
if (editors.Contains(gridEditor) == false) editors.Add(gridEditor);
}

View File

@@ -33,7 +33,7 @@ namespace Umbraco.Cms.Core.ContentApps
// its dependencies too, and that can create cycles or other oddities
var manifestParser = factory.GetRequiredService<IManifestParser>();
var ioHelper = factory.GetRequiredService<IIOHelper>();
return base.CreateItems(factory).Concat(manifestParser.Manifest.ContentApps.Select(x => new ManifestContentAppFactory(x, ioHelper)));
return base.CreateItems(factory).Concat(manifestParser.CombinedManifest.ContentApps.Select(x => new ManifestContentAppFactory(x, ioHelper)));
}
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
@@ -19,7 +19,7 @@ namespace Umbraco.Cms.Core.Dashboards
// its dependencies too, and that can create cycles or other oddities
var manifestParser = factory.GetRequiredService<IManifestParser>();
var dashboardSections = Merge(base.CreateItems(factory), manifestParser.Manifest.Dashboards);
var dashboardSections = Merge(base.CreateItems(factory), manifestParser.CombinedManifest.Dashboards);
return dashboardSections;
}

View File

@@ -0,0 +1,26 @@
namespace Umbraco.Cms.Core.Manifest
{
public enum BundleOptions
{
/// <summary>
/// The default bundling behavior for assets in the package folder.
/// </summary>
/// <remarks>
/// The assets will be bundled with the typical packages bundle.
/// </remarks>
Default = 0,
/// <summary>
/// The assets in the package will not be processed at all and will all be requested as individual assets.
/// </summary>
/// <remarks>
/// This will essentially be a bundle that has composite processing turned off for both debug and production.
/// </remarks>
None = 1,
/// <summary>
/// The packages assets will be processed as it's own separate bundle. (in debug, files will not be processed)
/// </summary>
Independent = 2
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using Umbraco.Cms.Core.PropertyEditors;
namespace Umbraco.Cms.Core.Manifest
{
/// <summary>
/// A package manifest made up of all combined manifests
/// </summary>
public class CompositePackageManifest
{
public CompositePackageManifest(
IReadOnlyList<IDataEditor> propertyEditors,
IReadOnlyList<IDataEditor> parameterEditors,
IReadOnlyList<GridEditor> gridEditors,
IReadOnlyList<ManifestContentAppDefinition> contentApps,
IReadOnlyList<ManifestDashboard> dashboards,
IReadOnlyList<ManifestSection> sections,
IReadOnlyDictionary<BundleOptions, IReadOnlyList<ManifestAssets>> scripts,
IReadOnlyDictionary<BundleOptions, IReadOnlyList<ManifestAssets>> stylesheets)
{
PropertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors));
ParameterEditors = parameterEditors ?? throw new ArgumentNullException(nameof(parameterEditors));
GridEditors = gridEditors ?? throw new ArgumentNullException(nameof(gridEditors));
ContentApps = contentApps ?? throw new ArgumentNullException(nameof(contentApps));
Dashboards = dashboards ?? throw new ArgumentNullException(nameof(dashboards));
Sections = sections ?? throw new ArgumentNullException(nameof(sections));
Scripts = scripts ?? throw new ArgumentNullException(nameof(scripts));
Stylesheets = stylesheets ?? throw new ArgumentNullException(nameof(stylesheets));
}
/// <summary>
/// Gets or sets the property editors listed in the manifest.
/// </summary>
public IReadOnlyList<IDataEditor> PropertyEditors { get; }
/// <summary>
/// Gets or sets the parameter editors listed in the manifest.
/// </summary>
public IReadOnlyList<IDataEditor> ParameterEditors { get; }
/// <summary>
/// Gets or sets the grid editors listed in the manifest.
/// </summary>
public IReadOnlyList<GridEditor> GridEditors { get; }
/// <summary>
/// Gets or sets the content apps listed in the manifest.
/// </summary>
public IReadOnlyList<ManifestContentAppDefinition> ContentApps { get; }
/// <summary>
/// Gets or sets the dashboards listed in the manifest.
/// </summary>
public IReadOnlyList<ManifestDashboard> Dashboards { get; }
/// <summary>
/// Gets or sets the sections listed in the manifest.
/// </summary>
public IReadOnlyCollection<ManifestSection> Sections { get; }
public IReadOnlyDictionary<BundleOptions, IReadOnlyList<ManifestAssets>> Scripts { get; }
public IReadOnlyDictionary<BundleOptions, IReadOnlyList<ManifestAssets>> Stylesheets { get; }
}
}

View File

@@ -4,13 +4,13 @@ namespace Umbraco.Cms.Core.Manifest
{
public interface IManifestParser
{
string Path { get; set; }
//string Path { get; set; }
/// <summary>
/// Gets all manifests, merged into a single manifest object.
/// </summary>
/// <returns></returns>
PackageManifest Manifest { get; }
CompositePackageManifest CombinedManifest { get; }
/// <summary>
/// Parses a manifest.

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
namespace Umbraco.Cms.Core.Manifest
{
public class ManifestAssets
{
public ManifestAssets(string packageName, IReadOnlyList<string> assets)
{
PackageName = packageName ?? throw new ArgumentNullException(nameof(packageName));
Assets = assets ?? throw new ArgumentNullException(nameof(assets));
}
public string PackageName { get; }
public IReadOnlyList<string> Assets { get; }
}
}

View File

@@ -6,6 +6,7 @@ using Umbraco.Extensions;
namespace Umbraco.Cms.Core.Manifest
{
/// <summary>
/// Represents the content of a package manifest.
/// </summary>
@@ -47,6 +48,8 @@ namespace Umbraco.Cms.Core.Manifest
/// </remarks>
[IgnoreDataMember]
public string Source { get; set; }
[DataMember(Name = "bundleOptions")]
public BundleOptions BundleOptions { get; set; }
/// <summary>
/// Gets or sets the scripts listed in the manifest.

View File

@@ -9,7 +9,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
public ParameterEditorCollection(DataEditorCollection dataEditors, IManifestParser manifestParser)
: base(() => dataEditors
.Where(x => (x.Type & EditorType.MacroParameter) > 0)
.Union(manifestParser.Manifest.PropertyEditors))
.Union(manifestParser.CombinedManifest.PropertyEditors))
{ }
// note: virtual so it can be mocked

View File

@@ -9,7 +9,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
public PropertyEditorCollection(DataEditorCollection dataEditors, IManifestParser manifestParser)
: base(() => dataEditors
.Where(x => (x.Type & EditorType.PropertyValue) > 0)
.Union(manifestParser.Manifest.PropertyEditors))
.Union(manifestParser.CombinedManifest.PropertyEditors))
{ }
public PropertyEditorCollection(DataEditorCollection dataEditors)

View File

@@ -18,7 +18,7 @@ namespace Umbraco.Cms.Core.Sections
// its dependencies too, and that can create cycles or other oddities
var manifestParser = factory.GetRequiredService<IManifestParser>();
return base.CreateItems(factory).Concat(manifestParser.Manifest.Sections);
return base.CreateItems(factory).Concat(manifestParser.CombinedManifest.Sections);
}
}
}

View File

@@ -62,22 +62,22 @@ namespace Umbraco.Cms.Core.Manifest
/// <summary>
/// Initializes a new instance of the <see cref="ManifestParser"/> class.
/// </summary>
private ManifestParser(AppCaches appCaches, ManifestValueValidatorCollection validators, ManifestFilterCollection filters, string path, ILogger<ManifestParser> logger, IIOHelper ioHelper, IHostingEnvironment hostingEnvironment)
private ManifestParser(AppCaches appCaches, ManifestValueValidatorCollection validators, ManifestFilterCollection filters, string appPluginsPath, ILogger<ManifestParser> logger, IIOHelper ioHelper, IHostingEnvironment hostingEnvironment)
{
if (appCaches == null) throw new ArgumentNullException(nameof(appCaches));
_cache = appCaches.RuntimeCache;
_validators = validators ?? throw new ArgumentNullException(nameof(validators));
_filters = filters ?? throw new ArgumentNullException(nameof(filters));
if (path == null) throw new ArgumentNullException(nameof(path));
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(path));
if (appPluginsPath == null) throw new ArgumentNullException(nameof(appPluginsPath));
if (string.IsNullOrWhiteSpace(appPluginsPath)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(appPluginsPath));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_ioHelper = ioHelper;
_hostingEnvironment = hostingEnvironment;
Path = path;
AppPluginsPath = appPluginsPath;
}
public string Path
public string AppPluginsPath
{
get => _path;
set => _path = value.StartsWith("~/") ? _hostingEnvironment.MapPathContentRoot(value) : value;
@@ -87,11 +87,12 @@ namespace Umbraco.Cms.Core.Manifest
/// Gets all manifests, merged into a single manifest object.
/// </summary>
/// <returns></returns>
public PackageManifest Manifest
=> _cache.GetCacheItem<PackageManifest>("Umbraco.Core.Manifest.ManifestParser::Manifests", () =>
public CompositePackageManifest CombinedManifest
=> _cache.GetCacheItem<CompositePackageManifest>("Umbraco.Core.Manifest.ManifestParser::Manifests", () =>
{
var manifests = GetManifests();
IEnumerable<PackageManifest> manifests = GetManifests();
return MergeManifests(manifests);
}, new TimeSpan(0, 4, 0));
/// <summary>
@@ -130,10 +131,10 @@ namespace Umbraco.Cms.Core.Manifest
/// <summary>
/// Merges all manifests into one.
/// </summary>
private static PackageManifest MergeManifests(IEnumerable<PackageManifest> manifests)
private static CompositePackageManifest MergeManifests(IEnumerable<PackageManifest> manifests)
{
var scripts = new HashSet<string>();
var stylesheets = new HashSet<string>();
var scripts = new Dictionary<BundleOptions, List<ManifestAssets>>();
var stylesheets = new Dictionary<BundleOptions, List<ManifestAssets>>();
var propertyEditors = new List<IDataEditor>();
var parameterEditors = new List<IDataEditor>();
var gridEditors = new List<GridEditor>();
@@ -141,10 +142,28 @@ namespace Umbraco.Cms.Core.Manifest
var dashboards = new List<ManifestDashboard>();
var sections = new List<ManifestSection>();
foreach (var manifest in manifests)
foreach (PackageManifest manifest in manifests)
{
if (manifest.Scripts != null) foreach (var script in manifest.Scripts) scripts.Add(script);
if (manifest.Stylesheets != null) foreach (var stylesheet in manifest.Stylesheets) stylesheets.Add(stylesheet);
if (manifest.Scripts != null)
{
if (!scripts.TryGetValue(manifest.BundleOptions, out List<ManifestAssets> scriptsPerBundleOption))
{
scriptsPerBundleOption = new List<ManifestAssets>();
scripts[manifest.BundleOptions] = scriptsPerBundleOption;
}
scriptsPerBundleOption.Add(new ManifestAssets(manifest.PackageName, manifest.Scripts));
}
if (manifest.Stylesheets != null)
{
if (!stylesheets.TryGetValue(manifest.BundleOptions, out List<ManifestAssets> stylesPerBundleOption))
{
stylesPerBundleOption = new List<ManifestAssets>();
stylesheets[manifest.BundleOptions] = stylesPerBundleOption;
}
stylesPerBundleOption.Add(new ManifestAssets(manifest.PackageName, manifest.Stylesheets));
}
if (manifest.PropertyEditors != null) propertyEditors.AddRange(manifest.PropertyEditors);
if (manifest.ParameterEditors != null) parameterEditors.AddRange(manifest.ParameterEditors);
if (manifest.GridEditors != null) gridEditors.AddRange(manifest.GridEditors);
@@ -153,17 +172,15 @@ namespace Umbraco.Cms.Core.Manifest
if (manifest.Sections != null) sections.AddRange(manifest.Sections.DistinctBy(x => x.Alias.ToLowerInvariant()));
}
return new PackageManifest
{
Scripts = scripts.ToArray(),
Stylesheets = stylesheets.ToArray(),
PropertyEditors = propertyEditors.ToArray(),
ParameterEditors = parameterEditors.ToArray(),
GridEditors = gridEditors.ToArray(),
ContentApps = contentApps.ToArray(),
Dashboards = dashboards.ToArray(),
Sections = sections.ToArray()
};
return new CompositePackageManifest(
propertyEditors,
parameterEditors,
gridEditors,
contentApps,
dashboards,
sections,
scripts.ToDictionary(x => x.Key, x => (IReadOnlyList<ManifestAssets>)x.Value),
stylesheets.ToDictionary(x => x.Key, x => (IReadOnlyList<ManifestAssets>)x.Value));
}
// gets all manifest files (recursively)

View File

@@ -73,25 +73,66 @@ namespace Umbraco.Cms.Infrastructure.WebAssets
_runtimeMinifier.CreateJsBundle(UmbracoCoreJsBundleName, false,
FormatPaths(GetScriptsForBackOfficeCore()));
// get the property editor assets
var propertyEditorAssets = ScanPropertyEditors()
.GroupBy(x => x.AssetType)
.ToDictionary(x => x.Key, x => x.Select(c => c.FilePath));
// get the back office custom assets
var customAssets = _customBackOfficeAssetsCollection.GroupBy(x => x.DependencyType).ToDictionary(x => x.Key, x => x.Select(c => c.FilePath));
var jsAssets = (customAssets.TryGetValue(AssetType.Javascript, out var customScripts) ? customScripts : Enumerable.Empty<string>())
.Union(propertyEditorAssets.TryGetValue(AssetType.Javascript, out var scripts) ? scripts : Enumerable.Empty<string>());
// This bundle includes all scripts from property editor assets,
// custom back office assets, and any scripts found in package manifests
// that have the default bundle options.
IEnumerable<string> jsAssets = (customAssets.TryGetValue(AssetType.Javascript, out IEnumerable<string> customScripts) ? customScripts : Enumerable.Empty<string>())
.Union(propertyEditorAssets.TryGetValue(AssetType.Javascript, out IEnumerable<string> scripts) ? scripts : Enumerable.Empty<string>());
_runtimeMinifier.CreateJsBundle(
UmbracoExtensionsJsBundleName, true,
UmbracoExtensionsJsBundleName,
true,
FormatPaths(
GetScriptsForBackOfficeExtensions(jsAssets)));
var cssAssets = (customAssets.TryGetValue(AssetType.Css, out var customStyles) ? customStyles : Enumerable.Empty<string>())
.Union(propertyEditorAssets.TryGetValue(AssetType.Css, out var styles) ? styles : Enumerable.Empty<string>());
// Create a bundle per package manifest that is declaring an Independent bundle type
RegisterPackageBundlesForIndependentOptions(_parser.CombinedManifest.Scripts, AssetType.Javascript);
// This bundle includes all CSS from property editor assets,
// custom back office assets, and any CSS found in package manifests
// that have the default bundle options.
IEnumerable<string> cssAssets = (customAssets.TryGetValue(AssetType.Css, out IEnumerable<string> customStyles) ? customStyles : Enumerable.Empty<string>())
.Union(propertyEditorAssets.TryGetValue(AssetType.Css, out IEnumerable<string> styles) ? styles : Enumerable.Empty<string>());
_runtimeMinifier.CreateCssBundle(
UmbracoCssBundleName, true,
UmbracoCssBundleName,
true,
FormatPaths(
GetStylesheetsForBackOffice(cssAssets)));
// Create a bundle per package manifest that is declaring an Independent bundle type
RegisterPackageBundlesForIndependentOptions(_parser.CombinedManifest.Stylesheets, AssetType.Css);
}
public static string GetIndependentPackageBundleName(ManifestAssets manifestAssets, AssetType assetType)
=> $"{manifestAssets.PackageName.ToLowerInvariant()}-{(assetType == AssetType.Css ? "css" : "js")}";
private void RegisterPackageBundlesForIndependentOptions(
IReadOnlyDictionary<BundleOptions, IReadOnlyList<ManifestAssets>> combinedPackageManifestAssets,
AssetType assetType)
{
// Create a bundle per package manifest that is declaring the matching BundleOptions
if (combinedPackageManifestAssets.TryGetValue(BundleOptions.Independent, out IReadOnlyList<ManifestAssets> manifestAssetList))
{
foreach (ManifestAssets manifestAssets in manifestAssetList)
{
_runtimeMinifier.CreateJsBundle(
GetIndependentPackageBundleName(manifestAssets, assetType),
true,
FormatPaths(manifestAssets.Assets.ToArray()));
}
}
}
/// <summary>
@@ -100,10 +141,15 @@ namespace Umbraco.Cms.Infrastructure.WebAssets
/// <returns></returns>
private string[] GetScriptsForBackOfficeExtensions(IEnumerable<string> propertyEditorScripts)
{
var scripts = new HashSet<string>();
foreach (string script in _parser.Manifest.Scripts)
var scripts = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
// only include scripts with the default bundle options here
if (_parser.CombinedManifest.Scripts.TryGetValue(BundleOptions.Default, out IReadOnlyList<ManifestAssets> manifestAssets))
{
scripts.Add(script);
foreach (string script in manifestAssets.SelectMany(x => x.Assets))
{
scripts.Add(script);
}
}
foreach (string script in propertyEditorScripts)
@@ -130,11 +176,15 @@ namespace Umbraco.Cms.Infrastructure.WebAssets
/// <returns></returns>
private string[] GetStylesheetsForBackOffice(IEnumerable<string> propertyEditorStyles)
{
var stylesheets = new HashSet<string>();
var stylesheets = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
foreach (string script in _parser.Manifest.Stylesheets)
// only include css with the default bundle options here
if (_parser.CombinedManifest.Stylesheets.TryGetValue(BundleOptions.Default, out IReadOnlyList<ManifestAssets> manifestAssets))
{
stylesheets.Add(script);
foreach (string script in manifestAssets.SelectMany(x => x.Assets))
{
stylesheets.Add(script);
}
}
foreach (string stylesheet in propertyEditorStyles)

View File

@@ -1,41 +0,0 @@
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.WebAssets;
using Umbraco.Cms.Infrastructure.WebAssets;
namespace Umbraco.Extensions
{
public static class RuntimeMinifierExtensions
{
/// <summary>
/// Returns the JavaScript to load the back office's assets
/// </summary>
/// <returns></returns>
public static async Task<string> GetScriptForLoadingBackOfficeAsync(this IRuntimeMinifier minifier, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment)
{
var coreScripts = await minifier.GetJsAssetPathsAsync(BackOfficeWebAssets.UmbracoCoreJsBundleName);
var extensionsScripts = await minifier.GetJsAssetPathsAsync(BackOfficeWebAssets.UmbracoExtensionsJsBundleName);
var result = BackOfficeJavaScriptInitializer.GetJavascriptInitialization(coreScripts.Union(extensionsScripts), "umbraco", globalSettings, hostingEnvironment);
result += await GetStylesheetInitializationAsync(minifier);
return result;
}
/// <summary>
/// Gets the back office css bundle paths and formats a JS call to lazy load them
/// </summary>
private static async Task<string> GetStylesheetInitializationAsync(IRuntimeMinifier minifier)
{
var files = await minifier.GetCssAssetPathsAsync(BackOfficeWebAssets.UmbracoCssBundleName);
var sb = new StringBuilder();
foreach (var file in files)
sb.AppendFormat("{0}LazyLoad.css('{1}');", Environment.NewLine, file);
return sb.ToString();
}
}
}

View File

@@ -17,6 +17,7 @@ using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Configuration.Grid;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Manifest;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Serialization;
@@ -63,6 +64,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
private readonly IBackOfficeExternalLoginProviders _externalLogins;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IBackOfficeTwoFactorOptions _backOfficeTwoFactorOptions;
private readonly IManifestParser _manifestParser;
private readonly ServerVariablesParser _serverVariables;
public BackOfficeController(
@@ -81,6 +83,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
IBackOfficeExternalLoginProviders externalLogins,
IHttpContextAccessor httpContextAccessor,
IBackOfficeTwoFactorOptions backOfficeTwoFactorOptions,
IManifestParser manifestParser,
ServerVariablesParser serverVariables)
{
_userManager = userManager;
@@ -98,6 +101,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
_externalLogins = externalLogins;
_httpContextAccessor = httpContextAccessor;
_backOfficeTwoFactorOptions = backOfficeTwoFactorOptions;
_manifestParser = manifestParser;
_serverVariables = serverVariables;
}
@@ -213,7 +217,11 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
[AllowAnonymous]
public async Task<IActionResult> Application()
{
var result = await _runtimeMinifier.GetScriptForLoadingBackOfficeAsync(_globalSettings, _hostingEnvironment);
var result = await _runtimeMinifier.GetScriptForLoadingBackOfficeAsync(
_globalSettings,
_hostingEnvironment,
_manifestParser,
Url);
return new JavaScriptResult(result);
}

View File

@@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Manifest;
using Umbraco.Cms.Core.WebAssets;
using Umbraco.Cms.Infrastructure.WebAssets;
namespace Umbraco.Extensions
{
public static class RuntimeMinifierExtensions
{
/// <summary>
/// Returns the JavaScript to load the back office's assets
/// </summary>
/// <returns></returns>
public static async Task<string> GetScriptForLoadingBackOfficeAsync(
this IRuntimeMinifier minifier,
GlobalSettings globalSettings,
IHostingEnvironment hostingEnvironment,
IManifestParser manifestParser,
IUrlHelper urlHelper)
{
var files = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
foreach(var file in await minifier.GetJsAssetPathsAsync(BackOfficeWebAssets.UmbracoCoreJsBundleName))
{
files.Add(file);
}
foreach (var file in await minifier.GetJsAssetPathsAsync(BackOfficeWebAssets.UmbracoExtensionsJsBundleName))
{
files.Add(file);
}
// process the independent bundles
if (manifestParser.CombinedManifest.Scripts.TryGetValue(BundleOptions.Independent, out IReadOnlyList<ManifestAssets> independentManifestAssetsList))
{
foreach (ManifestAssets manifestAssets in independentManifestAssetsList)
{
var bundleName = BackOfficeWebAssets.GetIndependentPackageBundleName(manifestAssets, AssetType.Javascript);
foreach(var asset in await minifier.GetJsAssetPathsAsync(bundleName))
{
files.Add(asset);
}
}
}
// process the "None" bundles, meaning we'll just render the script as-is
if (manifestParser.CombinedManifest.Scripts.TryGetValue(BundleOptions.None, out IReadOnlyList<ManifestAssets> noneManifestAssetsList))
{
foreach (ManifestAssets manifestAssets in noneManifestAssetsList)
{
foreach(var asset in manifestAssets.Assets)
{
files.Add(urlHelper.Content(asset));
}
}
}
var result = BackOfficeJavaScriptInitializer.GetJavascriptInitialization(
files,
"umbraco",
globalSettings,
hostingEnvironment);
result += await GetStylesheetInitializationAsync(minifier, manifestParser, urlHelper);
return result;
}
/// <summary>
/// Gets the back office css bundle paths and formats a JS call to lazy load them
/// </summary>
private static async Task<string> GetStylesheetInitializationAsync(
IRuntimeMinifier minifier,
IManifestParser manifestParser,
IUrlHelper urlHelper)
{
var files = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
foreach(var file in await minifier.GetCssAssetPathsAsync(BackOfficeWebAssets.UmbracoCssBundleName))
{
files.Add(file);
}
// process the independent bundles
if (manifestParser.CombinedManifest.Stylesheets.TryGetValue(BundleOptions.Independent, out IReadOnlyList<ManifestAssets> independentManifestAssetsList))
{
foreach (ManifestAssets manifestAssets in independentManifestAssetsList)
{
var bundleName = BackOfficeWebAssets.GetIndependentPackageBundleName(manifestAssets, AssetType.Css);
foreach (var asset in await minifier.GetCssAssetPathsAsync(bundleName))
{
files.Add(asset);
}
}
}
// process the "None" bundles, meaning we'll just render the script as-is
if (manifestParser.CombinedManifest.Stylesheets.TryGetValue(BundleOptions.None, out IReadOnlyList<ManifestAssets> noneManifestAssetsList))
{
foreach (ManifestAssets manifestAssets in noneManifestAssetsList)
{
foreach (var asset in manifestAssets.Assets)
{
files.Add(urlHelper.Content(asset));
}
}
}
var sb = new StringBuilder();
foreach (string file in files)
{
sb.AppendFormat("{0}LazyLoad.css('{1}');", Environment.NewLine, file);
}
return sb.ToString();
}
}
}

View File

@@ -60,9 +60,21 @@ namespace Umbraco.Cms.Web.Common.RuntimeMinification
// replace the default JsMinifier with NuglifyJs and CssMinifier with NuglifyCss in the default pipelines
// for use with our bundles only (not modifying global options)
_jsOptimizedPipeline = new Lazy<PreProcessPipeline>(() => bundles.PipelineFactory.DefaultJs().Replace<JsMinifier, SmidgeNuglifyJs>(_bundles.PipelineFactory));
_jsNonOptimizedPipeline = new Lazy<PreProcessPipeline>(() => bundles.PipelineFactory.DefaultJs());
_jsNonOptimizedPipeline = new Lazy<PreProcessPipeline>(() =>
{
PreProcessPipeline defaultJs = bundles.PipelineFactory.DefaultJs();
// remove minification from this pipeline
defaultJs.Processors.RemoveAll(x => x is JsMinifier);
return defaultJs;
});
_cssOptimizedPipeline = new Lazy<PreProcessPipeline>(() => bundles.PipelineFactory.DefaultCss().Replace<CssMinifier, NuglifyCss>(_bundles.PipelineFactory));
_cssNonOptimizedPipeline = new Lazy<PreProcessPipeline>(() => bundles.PipelineFactory.DefaultCss());
_cssNonOptimizedPipeline = new Lazy<PreProcessPipeline>(() =>
{
PreProcessPipeline defaultCss = bundles.PipelineFactory.DefaultCss();
// remove minification from this pipeline
defaultCss.Processors.RemoveAll(x => x is CssMinifier);
return defaultCss;
});
Type cacheBusterType = _runtimeMinificationSettings.CacheBuster switch
{