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:
Shannon
2021-03-17 17:44:52 +11:00
parent 2d14d0bd4a
commit eba659b9ee
16 changed files with 266 additions and 137 deletions

View File

@@ -0,0 +1,9 @@
namespace Umbraco.Cms.Core.Configuration.Models
{
public enum RuntimeMinificationCacheBuster
{
Version,
AppDomain,
Timestamp
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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>())));

View File

@@ -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()
{
}
}
}

View File

@@ -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>();
}
}
}

View File

@@ -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);
}
}

View File

@@ -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.

View File

@@ -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>();
}
}
}

View File

@@ -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;
}
}

View File

@@ -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();

View File

@@ -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>

View File

@@ -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"
]
}
}
}
}