Gets in-memory runtime minifiy cache working, ensures no files can be accessed at the root, adds config to enable in-memory and configure a cache buster including a timestamp cache buster.
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
namespace Umbraco.Cms.Core.Configuration.Models
|
||||
{
|
||||
public enum RuntimeMinificationCacheBuster
|
||||
{
|
||||
Version,
|
||||
AppDomain,
|
||||
Timestamp
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Cms.Core.Configuration.Models
|
||||
{
|
||||
public class RuntimeMinificationSettings
|
||||
{
|
||||
public bool UseInMemoryCache { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// The cache buster type to use
|
||||
/// </summary>
|
||||
public RuntimeMinificationCacheBuster CacheBuster { get; set; } = RuntimeMinificationCacheBuster.Version;
|
||||
}
|
||||
}
|
||||
@@ -13,11 +13,10 @@ namespace Umbraco.Cms.Core.DependencyInjection
|
||||
|
||||
private static OptionsBuilder<TOptions> AddOptions<TOptions>(IUmbracoBuilder builder, string key)
|
||||
where TOptions : class
|
||||
{
|
||||
return builder.Services.AddOptions<TOptions>()
|
||||
=> builder.Services.AddOptions<TOptions>()
|
||||
.Bind(builder.Config.GetSection(key))
|
||||
.ValidateDataAnnotations();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add Umbraco configuration services and options
|
||||
/// </summary>
|
||||
@@ -57,6 +56,7 @@ namespace Umbraco.Cms.Core.DependencyInjection
|
||||
AddOptions<UmbracoPluginSettings>(builder, Constants.Configuration.ConfigPlugins);
|
||||
AddOptions<UnattendedSettings>(builder, Constants.Configuration.ConfigUnattended);
|
||||
AddOptions<RichTextEditorSettings>(builder, Constants.Configuration.ConfigRichTextEditor);
|
||||
AddOptions<RuntimeMinificationSettings>(builder, Constants.Configuration.ConfigRuntimeMinification);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.WebAssets
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// Thrown if any of the paths specified are not absolute
|
||||
/// </exception>
|
||||
void CreateCssBundle(string bundleName, params string[] filePaths);
|
||||
void CreateCssBundle(string bundleName, bool optimizeOutput, params string[] filePaths);
|
||||
|
||||
/// <summary>
|
||||
/// Renders the html link tag for the bundle
|
||||
|
||||
@@ -66,7 +66,8 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
|
||||
.AddRepositories()
|
||||
.AddServices()
|
||||
.AddCoreMappingProfiles()
|
||||
.AddFileSystems();
|
||||
.AddFileSystems()
|
||||
.AddWebAssets();
|
||||
|
||||
// register persistence mappers - required by database factory so needs to be done here
|
||||
// means the only place the collection can be modified is in a runtime - afterwards it
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Infrastructure.WebAssets;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.DependencyInjection
|
||||
{
|
||||
public static partial class UmbracoBuilderExtensions
|
||||
{
|
||||
internal static IUmbracoBuilder AddWebAssets(this IUmbracoBuilder builder)
|
||||
{
|
||||
builder.Services.AddSingleton<BackOfficeWebAssets>();
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,17 +48,18 @@ namespace Umbraco.Cms.Infrastructure.WebAssets
|
||||
{
|
||||
// Create bundles
|
||||
|
||||
_runtimeMinifier.CreateCssBundle(UmbracoInitCssBundleName,
|
||||
// TODO: I think we don't want to optimize these css if/when we get gulp to do that all for us
|
||||
_runtimeMinifier.CreateCssBundle(UmbracoInitCssBundleName, true,
|
||||
FormatPaths("lib/bootstrap-social/bootstrap-social.css",
|
||||
"assets/css/umbraco.css",
|
||||
"lib/font-awesome/css/font-awesome.min.css"));
|
||||
|
||||
_runtimeMinifier.CreateCssBundle(UmbracoUpgradeCssBundleName,
|
||||
_runtimeMinifier.CreateCssBundle(UmbracoUpgradeCssBundleName, true,
|
||||
FormatPaths("assets/css/umbraco.css",
|
||||
"lib/bootstrap-social/bootstrap-social.css",
|
||||
"lib/font-awesome/css/font-awesome.min.css"));
|
||||
|
||||
_runtimeMinifier.CreateCssBundle(UmbracoPreviewCssBundleName,
|
||||
_runtimeMinifier.CreateCssBundle(UmbracoPreviewCssBundleName, true,
|
||||
FormatPaths("assets/css/canvasdesigner.css"));
|
||||
|
||||
_runtimeMinifier.CreateJsBundle(UmbracoPreviewJsBundleName, false,
|
||||
@@ -81,7 +82,7 @@ namespace Umbraco.Cms.Infrastructure.WebAssets
|
||||
propertyEditorAssets.TryGetValue(AssetType.Javascript, out var scripts) ? scripts : Enumerable.Empty<string>())));
|
||||
|
||||
_runtimeMinifier.CreateCssBundle(
|
||||
UmbracoCssBundleName,
|
||||
UmbracoCssBundleName, true,
|
||||
FormatPaths(
|
||||
GetStylesheetsForBackOffice(
|
||||
propertyEditorAssets.TryGetValue(AssetType.Css, out var styles) ? styles : Enumerable.Empty<string>())));
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
using Umbraco.Cms.Core.Composing;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.WebAssets
|
||||
{
|
||||
public sealed class WebAssetsComponent : IComponent
|
||||
{
|
||||
private readonly BackOfficeWebAssets _backOfficeWebAssets;
|
||||
|
||||
public WebAssetsComponent(BackOfficeWebAssets backOfficeWebAssets)
|
||||
{
|
||||
_backOfficeWebAssets = backOfficeWebAssets;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
// TODO: This will eagerly scan types but we don't really want that, however it works for now.
|
||||
// We don't actually have to change Smidge or anything, all we have to do is postpone this call for when the first request on the website arrives.
|
||||
_backOfficeWebAssets.CreateBundles();
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using Umbraco.Cms.Core.Composing;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.WebAssets
|
||||
{
|
||||
public sealed class WebAssetsComposer : ComponentComposer<WebAssetsComponent>
|
||||
{
|
||||
public override void Compose(IUmbracoBuilder builder)
|
||||
{
|
||||
base.Compose(builder);
|
||||
builder.Services.AddUnique<BackOfficeWebAssets>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,8 @@ using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Serilog;
|
||||
using Smidge;
|
||||
using Smidge.FileProcessors;
|
||||
using Smidge.InMemory;
|
||||
using Smidge.Nuglify;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
@@ -34,6 +36,7 @@ using Umbraco.Cms.Core.Security;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Templates;
|
||||
using Umbraco.Cms.Core.Web;
|
||||
using Umbraco.Cms.Core.WebAssets;
|
||||
using Umbraco.Cms.Infrastructure.DependencyInjection;
|
||||
using Umbraco.Cms.Infrastructure.HostedServices;
|
||||
using Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration;
|
||||
@@ -53,6 +56,7 @@ using Umbraco.Cms.Web.Common.ModelBinders;
|
||||
using Umbraco.Cms.Web.Common.Mvc;
|
||||
using Umbraco.Cms.Web.Common.Profiler;
|
||||
using Umbraco.Cms.Web.Common.Routing;
|
||||
using Umbraco.Cms.Web.Common.RuntimeMinification;
|
||||
using Umbraco.Cms.Web.Common.Security;
|
||||
using Umbraco.Cms.Web.Common.Templates;
|
||||
using Umbraco.Cms.Web.Common.UmbracoContext;
|
||||
@@ -233,10 +237,17 @@ namespace Umbraco.Extensions
|
||||
new GlobPatternFilterFileProvider(
|
||||
hostEnv.ContentRootFileProvider,
|
||||
// only include js or css files within App_Plugins
|
||||
new[] { "App_Plugins/**/*.js", "App_Plugins/**/*.css" }));
|
||||
new[] { "/App_Plugins/**/*.js", "/App_Plugins/**/*.css" }));
|
||||
});
|
||||
|
||||
builder.Services.AddSmidge(builder.Config.GetSection(Constants.Configuration.ConfigRuntimeMinification));
|
||||
builder.Services.AddSmidgeNuglify();
|
||||
builder.Services.AddSmidgeInMemory(false); // it will be enabled based on config/cachebuster
|
||||
|
||||
builder.Services.AddUnique<IRuntimeMinifier, SmidgeRuntimeMinifier>();
|
||||
builder.Services.AddUnique<SmidgeHelperAccessor>();
|
||||
builder.Services.AddTransient<IPreProcessor, SmidgeNuglifyJs>();
|
||||
builder.Services.ConfigureOptions<SmidgeOptionsSetup>();
|
||||
|
||||
return builder;
|
||||
}
|
||||
@@ -426,7 +437,7 @@ namespace Umbraco.Extensions
|
||||
var wrappedHostingSettings = new OptionsMonitorAdapter<HostingSettings>(hostingSettings);
|
||||
var wrappedWebRoutingSettings = new OptionsMonitorAdapter<WebRoutingSettings>(webRoutingSettings);
|
||||
|
||||
return new AspNetCoreHostingEnvironment(wrappedHostingSettings,wrappedWebRoutingSettings, webHostEnvironment);
|
||||
return new AspNetCoreHostingEnvironment(wrappedHostingSettings, wrappedWebRoutingSettings, webHostEnvironment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,15 +6,19 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Smidge.Options;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Hosting;
|
||||
using Umbraco.Cms.Core.Logging;
|
||||
using Umbraco.Cms.Core.Routing;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Security;
|
||||
using Umbraco.Cms.Core.Web;
|
||||
using Umbraco.Cms.Infrastructure.PublishedCache;
|
||||
using Umbraco.Cms.Infrastructure.WebAssets;
|
||||
using Umbraco.Cms.Web.Common.Profiler;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
@@ -41,11 +45,21 @@ namespace Umbraco.Cms.Web.Common.Middleware
|
||||
private readonly PublishedSnapshotServiceEventHandler _publishedSnapshotServiceEventHandler;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly UmbracoRequestPaths _umbracoRequestPaths;
|
||||
private readonly BackOfficeWebAssets _backOfficeWebAssets;
|
||||
private readonly SmidgeOptions _smidgeOptions;
|
||||
private readonly WebProfiler _profiler;
|
||||
private static bool s_cacheInitialized = false;
|
||||
|
||||
private static bool s_cacheInitialized;
|
||||
private static bool s_cacheInitializedFlag = false;
|
||||
private static object s_cacheInitializedLock = new object();
|
||||
|
||||
#pragma warning disable IDE0044 // Add readonly modifier
|
||||
private static bool s_firstBackOfficeRequest;
|
||||
private static bool s_firstBackOfficeReqestFlag;
|
||||
private static object s_firstBackOfficeRequestLocker = new object();
|
||||
#pragma warning restore IDE0044 // Add readonly modifier
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoRequestMiddleware"/> class.
|
||||
/// </summary>
|
||||
@@ -56,7 +70,10 @@ namespace Umbraco.Cms.Web.Common.Middleware
|
||||
PublishedSnapshotServiceEventHandler publishedSnapshotServiceEventHandler,
|
||||
IEventAggregator eventAggregator,
|
||||
IProfiler profiler,
|
||||
IHostingEnvironment hostingEnvironment)
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
UmbracoRequestPaths umbracoRequestPaths,
|
||||
BackOfficeWebAssets backOfficeWebAssets,
|
||||
IOptions<SmidgeOptions> smidgeOptions)
|
||||
{
|
||||
_logger = logger;
|
||||
_umbracoContextFactory = umbracoContextFactory;
|
||||
@@ -64,6 +81,9 @@ namespace Umbraco.Cms.Web.Common.Middleware
|
||||
_publishedSnapshotServiceEventHandler = publishedSnapshotServiceEventHandler;
|
||||
_eventAggregator = eventAggregator;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_umbracoRequestPaths = umbracoRequestPaths;
|
||||
_backOfficeWebAssets = backOfficeWebAssets;
|
||||
_smidgeOptions = smidgeOptions.Value;
|
||||
_profiler = profiler as WebProfiler; // Ignore if not a WebProfiler
|
||||
}
|
||||
|
||||
@@ -73,6 +93,8 @@ namespace Umbraco.Cms.Web.Common.Middleware
|
||||
// do not process if client-side request
|
||||
if (context.Request.IsClientSideRequest())
|
||||
{
|
||||
// we need this here because for bundle requests, these are 'client side' requests that we need to handle
|
||||
LazyInitializeBackOfficeServices(context.Request.Path);
|
||||
await next(context);
|
||||
return;
|
||||
}
|
||||
@@ -97,7 +119,8 @@ namespace Umbraco.Cms.Web.Common.Middleware
|
||||
_logger.LogTrace("Begin request [{HttpRequestId}]: {RequestUrl}", httpRequestId, pathAndQuery);
|
||||
|
||||
try
|
||||
{
|
||||
{
|
||||
LazyInitializeBackOfficeServices(context.Request.Path);
|
||||
await _eventAggregator.PublishAsync(new UmbracoRequestBegin(umbracoContextReference.UmbracoContext));
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -141,6 +164,30 @@ namespace Umbraco.Cms.Web.Common.Middleware
|
||||
_profiler?.UmbracoApplicationEndRequest(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to lazily initialize any back office services when the first request to the back office is made
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
/// <returns></returns>
|
||||
private void LazyInitializeBackOfficeServices(PathString absPath)
|
||||
{
|
||||
if (s_firstBackOfficeRequest)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_umbracoRequestPaths.IsBackOfficeRequest(absPath)
|
||||
|| absPath.Value.InvariantStartsWith($"/{_smidgeOptions.UrlOptions.CompositeFilePath}")
|
||||
|| absPath.Value.InvariantStartsWith($"/{_smidgeOptions.UrlOptions.BundleFilePath}"))
|
||||
{
|
||||
LazyInitializer.EnsureInitialized(ref s_firstBackOfficeRequest, ref s_firstBackOfficeReqestFlag, ref s_firstBackOfficeRequestLocker, () =>
|
||||
{
|
||||
_backOfficeWebAssets.CreateBundles();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private Uri GetApplicationUrlFromCurrentRequest(HttpRequest request)
|
||||
{
|
||||
// We only consider GET and POST.
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Smidge.FileProcessors;
|
||||
using Umbraco.Cms.Core.Composing;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.WebAssets;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Web.Common.RuntimeMinification
|
||||
{
|
||||
public sealed class SmidgeComposer : IComposer
|
||||
{
|
||||
public void Compose(IUmbracoBuilder builder)
|
||||
{
|
||||
// TODO: For this to work we need to have services.AddSmidge() based on the Smidge APIs but our composer APIs don't really let us do that
|
||||
// This makes it a bit awkward to boot the runtime since that call would need to be made outside of the composer... .hrm...
|
||||
|
||||
builder.Services.AddUnique<IRuntimeMinifier, SmidgeRuntimeMinifier>();
|
||||
builder.Services.AddUnique<SmidgeHelperAccessor>();
|
||||
builder.Services.AddTransient<IPreProcessor, SmidgeNuglifyJs>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using Smidge.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
|
||||
namespace Umbraco.Cms.Web.Common.RuntimeMinification
|
||||
{
|
||||
public class SmidgeOptionsSetup : IConfigureOptions<SmidgeOptions>
|
||||
{
|
||||
private readonly IOptions<RuntimeMinificationSettings> _runtimeMinificatinoSettings;
|
||||
|
||||
public SmidgeOptionsSetup(IOptions<RuntimeMinificationSettings> runtimeMinificatinoSettings)
|
||||
=> _runtimeMinificatinoSettings = runtimeMinificatinoSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Configures Smidge to use in-memory caching if configured that way or if certain cache busters are used
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
public void Configure(SmidgeOptions options)
|
||||
=> options.CacheOptions.UseInMemoryCache = _runtimeMinificatinoSettings.Value.UseInMemoryCache || _runtimeMinificatinoSettings.Value.CacheBuster == RuntimeMinificationCacheBuster.Timestamp;
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,16 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Smidge;
|
||||
using Smidge.Cache;
|
||||
using Smidge.CompositeFiles;
|
||||
using Smidge.FileProcessors;
|
||||
using Smidge.Models;
|
||||
using Smidge.Nuglify;
|
||||
using Smidge.Options;
|
||||
using Umbraco.Cms.Core.Configuration;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Hosting;
|
||||
using Umbraco.Cms.Core.WebAssets;
|
||||
using CssFile = Smidge.Models.CssFile;
|
||||
@@ -17,24 +20,12 @@ using JavaScriptFile = Smidge.Models.JavaScriptFile;
|
||||
|
||||
namespace Umbraco.Cms.Web.Common.RuntimeMinification
|
||||
{
|
||||
// public class UmbracoCacheBuster : ICacheBuster
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// Gets the cache buster value
|
||||
// /// </summary>
|
||||
// /// <returns></returns>
|
||||
// public string GetValue() => throw new NotImplementedException();
|
||||
|
||||
// // This doesn't do anything in Smidge (is removed in v4 unreleased version)
|
||||
// [EditorBrowsable(EditorBrowsableState.Never)]
|
||||
// public bool PersistProcessedFiles => throw new NotImplementedException();
|
||||
// }
|
||||
|
||||
public class SmidgeRuntimeMinifier : IRuntimeMinifier
|
||||
{
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly ISmidgeConfig _smidgeConfig;
|
||||
private readonly IConfigManipulator _configManipulator;
|
||||
private readonly CacheBusterResolver _cacheBusterResolver;
|
||||
private readonly RuntimeMinificationSettings _runtimeMinificationSettings;
|
||||
private readonly IBundleManager _bundles;
|
||||
private readonly SmidgeHelperAccessor _smidge;
|
||||
|
||||
@@ -43,47 +34,93 @@ namespace Umbraco.Cms.Web.Common.RuntimeMinification
|
||||
private readonly Lazy<PreProcessPipeline> _cssMinPipeline;
|
||||
|
||||
// default pipelines for processing js/css files for the back office
|
||||
private readonly Lazy<PreProcessPipeline> _jsPipeline;
|
||||
private readonly Lazy<PreProcessPipeline> _cssPipeline;
|
||||
private readonly Lazy<PreProcessPipeline> _jsOptimizedPipeline;
|
||||
private readonly Lazy<PreProcessPipeline> _jsNonOptimizedPipeline;
|
||||
private readonly Lazy<PreProcessPipeline> _cssOptimizedPipeline;
|
||||
private readonly Lazy<PreProcessPipeline> _cssNonOptimizedPipeline;
|
||||
private ICacheBuster _cacheBuster;
|
||||
private readonly Type _cacheBusterType;
|
||||
|
||||
public SmidgeRuntimeMinifier(
|
||||
IBundleManager bundles,
|
||||
SmidgeHelperAccessor smidge,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
ISmidgeConfig smidgeConfig,
|
||||
IConfigManipulator configManipulator)
|
||||
IConfigManipulator configManipulator,
|
||||
IOptions<RuntimeMinificationSettings> runtimeMinificationSettings,
|
||||
CacheBusterResolver cacheBusterResolver)
|
||||
{
|
||||
_bundles = bundles;
|
||||
_smidge = smidge;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_smidgeConfig = smidgeConfig;
|
||||
_configManipulator = configManipulator;
|
||||
|
||||
_cacheBusterResolver = cacheBusterResolver;
|
||||
_runtimeMinificationSettings = runtimeMinificationSettings.Value;
|
||||
_jsMinPipeline = new Lazy<PreProcessPipeline>(() => _bundles.PipelineFactory.Create(typeof(JsMinifier)));
|
||||
_cssMinPipeline = new Lazy<PreProcessPipeline>(() => _bundles.PipelineFactory.Create(typeof(NuglifyCss)));
|
||||
|
||||
// replace the default JsMinifier with NuglifyJs and CssMinifier with NuglifyCss in the default pipelines
|
||||
// for use with our bundles only (not modifying global options)
|
||||
_jsPipeline = new Lazy<PreProcessPipeline>(() => bundles.PipelineFactory.DefaultJs().Replace<JsMinifier, SmidgeNuglifyJs>(_bundles.PipelineFactory));
|
||||
_cssPipeline = new Lazy<PreProcessPipeline>(() => bundles.PipelineFactory.DefaultCss().Replace<CssMinifier, NuglifyCss>(_bundles.PipelineFactory));
|
||||
_jsOptimizedPipeline = new Lazy<PreProcessPipeline>(() => bundles.PipelineFactory.DefaultJs().Replace<JsMinifier, SmidgeNuglifyJs>(_bundles.PipelineFactory));
|
||||
_jsNonOptimizedPipeline = new Lazy<PreProcessPipeline>(() => bundles.PipelineFactory.DefaultJs());
|
||||
_cssOptimizedPipeline = new Lazy<PreProcessPipeline>(() => bundles.PipelineFactory.DefaultCss().Replace<CssMinifier, NuglifyCss>(_bundles.PipelineFactory));
|
||||
_cssNonOptimizedPipeline = new Lazy<PreProcessPipeline>(() => bundles.PipelineFactory.DefaultCss());
|
||||
|
||||
Type cacheBusterType = _runtimeMinificationSettings.CacheBuster switch
|
||||
{
|
||||
RuntimeMinificationCacheBuster.AppDomain => typeof(AppDomainLifetimeCacheBuster),
|
||||
RuntimeMinificationCacheBuster.Version => typeof(ConfigCacheBuster),
|
||||
RuntimeMinificationCacheBuster.Timestamp => typeof(TimestampCacheBuster),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
|
||||
_cacheBusterType = cacheBusterType;
|
||||
}
|
||||
|
||||
public string CacheBuster => _smidgeConfig.Version;
|
||||
public string CacheBuster => (_cacheBuster ??= _cacheBusterResolver.GetCacheBuster(_cacheBusterType)).GetValue();
|
||||
|
||||
// only issue with creating bundles like this is that we don't have full control over the bundle options, though that could
|
||||
public void CreateCssBundle(string bundleName, params string[] filePaths)
|
||||
public void CreateCssBundle(string bundleName, bool optimizeOutput, params string[] filePaths)
|
||||
{
|
||||
if (filePaths.Any(f => !f.StartsWith("/") && !f.StartsWith("~/")))
|
||||
{
|
||||
throw new InvalidOperationException("All file paths must be absolute");
|
||||
}
|
||||
|
||||
if (_bundles.Exists(bundleName))
|
||||
{
|
||||
throw new InvalidOperationException($"The bundle name {bundleName} already exists");
|
||||
}
|
||||
|
||||
// TODO: Here we could configure bundle options instead of using smidge's global defaults.
|
||||
// For example we can use our own custom cache buster for this bundle without having the global one
|
||||
// affect this or vice versa.
|
||||
var bundle = _bundles.Create(bundleName, _cssPipeline.Value, WebFileType.Css, filePaths);
|
||||
if (optimizeOutput)
|
||||
{
|
||||
var bundle = _bundles.Create(bundleName, _cssOptimizedPipeline.Value, WebFileType.Css, filePaths)
|
||||
.WithEnvironmentOptions(
|
||||
BundleEnvironmentOptions.Create()
|
||||
.ForDebug(builder => builder
|
||||
// auto-invalidate bundle if files change in debug
|
||||
.EnableFileWatcher()
|
||||
// keep using composite files in debug, not raw static files
|
||||
.EnableCompositeProcessing()
|
||||
// use the cache buster defined in config
|
||||
.SetCacheBusterType(_cacheBusterType))
|
||||
.ForProduction(builder => builder
|
||||
// use the cache buster defined in config
|
||||
.SetCacheBusterType(_cacheBusterType))
|
||||
.Build());
|
||||
}
|
||||
else
|
||||
{
|
||||
var bundle = _bundles.Create(bundleName, _cssNonOptimizedPipeline.Value, WebFileType.Css, filePaths)
|
||||
.WithEnvironmentOptions(
|
||||
BundleEnvironmentOptions.Create()
|
||||
.ForDebug(builder => builder
|
||||
// use the cache buster defined in config
|
||||
.SetCacheBusterType(_cacheBusterType))
|
||||
.ForProduction(builder => builder
|
||||
// use the cache buster defined in config
|
||||
.SetCacheBusterType(_cacheBusterType))
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> RenderCssHereAsync(string bundleName) => (await _smidge.SmidgeHelper.CssHereAsync(bundleName, _hostingEnvironment.IsDebugMode)).ToString();
|
||||
@@ -91,16 +128,45 @@ namespace Umbraco.Cms.Web.Common.RuntimeMinification
|
||||
public void CreateJsBundle(string bundleName, bool optimizeOutput, params string[] filePaths)
|
||||
{
|
||||
if (filePaths.Any(f => !f.StartsWith("/") && !f.StartsWith("~/")))
|
||||
{
|
||||
throw new InvalidOperationException("All file paths must be absolute");
|
||||
}
|
||||
|
||||
if (_bundles.Exists(bundleName))
|
||||
{
|
||||
throw new InvalidOperationException($"The bundle name {bundleName} already exists");
|
||||
}
|
||||
|
||||
// TODO: Here we could configure bundle options instead of using smidge's global defaults.
|
||||
// For example we can use our own custom cache buster for this bundle without having the global one
|
||||
// affect this or vice versa.
|
||||
var pipeline = optimizeOutput ? _jsPipeline.Value : _bundles.PipelineFactory.Create();
|
||||
var bundle = _bundles.Create(bundleName, pipeline, WebFileType.Js, filePaths);
|
||||
if (optimizeOutput)
|
||||
{
|
||||
var bundle = _bundles.Create(bundleName, _jsOptimizedPipeline.Value, WebFileType.Js, filePaths)
|
||||
.WithEnvironmentOptions(
|
||||
BundleEnvironmentOptions.Create()
|
||||
.ForDebug(builder => builder
|
||||
// auto-invalidate bundle if files change in debug
|
||||
.EnableFileWatcher()
|
||||
// keep using composite files in debug, not raw static files
|
||||
.EnableCompositeProcessing()
|
||||
// use the cache buster defined in config
|
||||
.SetCacheBusterType(_cacheBusterType))
|
||||
.ForProduction(builder => builder
|
||||
// use the cache buster defined in config
|
||||
.SetCacheBusterType(_cacheBusterType))
|
||||
.Build());
|
||||
}
|
||||
else
|
||||
{
|
||||
var bundle = _bundles.Create(bundleName, _jsNonOptimizedPipeline.Value, WebFileType.Js, filePaths)
|
||||
.WithEnvironmentOptions(
|
||||
BundleEnvironmentOptions.Create()
|
||||
.ForDebug(builder => builder
|
||||
// use the cache buster defined in config
|
||||
.SetCacheBusterType(_cacheBusterType))
|
||||
.ForProduction(builder => builder
|
||||
// use the cache buster defined in config
|
||||
.SetCacheBusterType(_cacheBusterType))
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> RenderJsHereAsync(string bundleName) => (await _smidge.SmidgeHelper.JsHereAsync(bundleName, _hostingEnvironment.IsDebugMode)).ToString();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
@@ -30,10 +30,9 @@
|
||||
<PackageReference Include="NETStandard.Library" Version="2.0.3" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp.Web" Version="1.0.2" />
|
||||
<PackageReference Include="Smidge" Version="4.0.0-beta.*" />
|
||||
<PackageReference Include="Smidge.Nuglify" Version="4.0.0-beta.*" />
|
||||
<PackageReference Include="Smidge.InMemory" Version="4.0.0-beta.*" />
|
||||
<PackageReference Include="Smidge.InMemory" Version="4.0.0-beta.*" />
|
||||
<PackageReference Include="Smidge" Version="4.0.0-beta.274" />
|
||||
<PackageReference Include="Smidge.Nuglify" Version="4.0.0-beta.274" />
|
||||
<PackageReference Include="Smidge.InMemory" Version="4.0.0-beta.274" />
|
||||
<PackageReference Include="Dazinator.Extensions.FileProviders" Version="2.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -17,30 +17,34 @@
|
||||
]
|
||||
},
|
||||
"Umbraco": {
|
||||
"CMS": {
|
||||
"Global": {
|
||||
"Smtp": {
|
||||
//"From": "your@email.here",
|
||||
//"Host": "localhost",
|
||||
// "Port": "25"
|
||||
}
|
||||
},
|
||||
"Hosting": {
|
||||
"Debug": true
|
||||
},
|
||||
"RichTextEditor": {
|
||||
"Commands" : [
|
||||
{
|
||||
"Alias": "fullscreen",
|
||||
"Name": "Full Screen",
|
||||
"Mode": "All"
|
||||
}
|
||||
],
|
||||
"Plugins": [
|
||||
"fullscreen"
|
||||
]
|
||||
"CMS": {
|
||||
"Global": {
|
||||
"Smtp": {
|
||||
//"From": "your@email.here",
|
||||
//"Host": "localhost",
|
||||
// "Port": "25"
|
||||
}
|
||||
},
|
||||
"Hosting": {
|
||||
"Debug": true
|
||||
},
|
||||
"RuntimeMinification": {
|
||||
"useInMemoryCache": true,
|
||||
"cacheBuster": "Timestamp"
|
||||
},
|
||||
"RichTextEditor": {
|
||||
"Commands": [
|
||||
{
|
||||
"Alias": "fullscreen",
|
||||
"Name": "Full Screen",
|
||||
"Mode": "All"
|
||||
}
|
||||
],
|
||||
"Plugins": [
|
||||
"fullscreen"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user