Browse Source

Refactored bundle tag helpers and bundle manager

pull/301/head
Halil ibrahim Kalkan 8 years ago
parent
commit
8c78a6ffbd
  1. 56
      src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpBundleTagHelperServiceBase.cs
  2. 2
      src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpScriptBundleTagHelper.cs
  3. 43
      src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpScriptBundleTagHelperService.cs
  4. 3
      src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpStyleBundleTagHelper.cs
  5. 44
      src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpStyleBundleTagHelperService.cs
  6. 7
      src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/IBundleTagHelper.cs
  7. 39
      src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleCollection.cs
  8. 21
      src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleManager.cs
  9. 6
      src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/IBundleManager.cs

56
src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpBundleTagHelperServiceBase.cs

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling
{
public abstract class AbpBundleTagHelperServiceBase<TTagHelper> : AbpTagHelperService<TTagHelper>
where TTagHelper : TagHelper, IBundleTagHelper
{
protected IBundleManager BundleManager { get; }
protected AbpBundleTagHelperServiceBase(IBundleManager bundleManager)
{
BundleManager = bundleManager;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = null;
var bundleName = TagHelper.Name;
var files = await GetFileList(context, output);
if (bundleName.IsNullOrEmpty())
{
bundleName = GenerateBundleName(context, output, files);
}
CreateBundle(bundleName, files);
var bundleFiles = GetBundleFiles(bundleName);
await output.GetChildContentAsync(); //TODO: Suppress child execution!
output.Content.Clear();
AddHtmlTags(context, output, bundleFiles);
}
protected abstract void CreateBundle(string bundleName, List<string> files);
protected abstract List<string> GetBundleFiles(string bundleName);
protected abstract void AddHtmlTags(TagHelperContext context, TagHelperOutput output, List<string> files);
protected virtual string GenerateBundleName(TagHelperContext context, TagHelperOutput output, List<string> fileList)
{
return fileList.JoinAsString("|").ToMd5();
}
protected virtual async Task<List<string>> GetFileList(TagHelperContext context, TagHelperOutput output)
{
var fileList = new List<string>();
context.Items[AbpBundleFileTagHelperService.ContextFileListKey] = fileList;
await output.GetChildContentAsync();
return fileList;
}
}
}

2
src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpScriptBundleTagHelper.cs

@ -3,7 +3,7 @@
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling
{
[HtmlTargetElement("abp-script-bundle", TagStructure = TagStructure.NormalOrSelfClosing)]
public class AbpScriptBundleTagHelper : AbpTagHelper<AbpScriptBundleTagHelper, AbpScriptBundleTagHelperService>
public class AbpScriptBundleTagHelper : AbpTagHelper<AbpScriptBundleTagHelper, AbpScriptBundleTagHelperService>, IBundleTagHelper
{
public string Name { get; set; }

43
src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpScriptBundleTagHelperService.cs

@ -1,43 +1,32 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling
{
public class AbpScriptBundleTagHelperService : AbpTagHelperService<AbpScriptBundleTagHelper>
public class AbpScriptBundleTagHelperService : AbpBundleTagHelperServiceBase<AbpScriptBundleTagHelper>
{
private readonly IBundleManager _bundleManager;
public AbpScriptBundleTagHelperService(IBundleManager bundleManager)
: base(bundleManager)
{
_bundleManager = bundleManager;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
protected override void CreateBundle(string bundleName, List<string> files)
{
output.TagName = null;
var bundleName = TagHelper.Name;
var files = await GetFileList(context, output);
if (bundleName.IsNullOrEmpty())
{
bundleName = GenerateBundleName(context, output, files);
}
_bundleManager.CreateDynamicScriptBundle(
BundleManager.CreateScriptBundle(
bundleName,
configuration => configuration.AddFiles(files.ToArray())
);
}
var bundleFiles = _bundleManager.GetScriptBundleFiles(bundleName);
await output.GetChildContentAsync(); //TODO: Suppress child execution!
output.Content.Clear();
AddLinkTags(context, output, bundleFiles);
protected override List<string> GetBundleFiles(string bundleName)
{
return BundleManager.GetScriptBundleFiles(bundleName);
}
protected virtual void AddLinkTags(TagHelperContext context, TagHelperOutput output, List<string> files)
protected override void AddHtmlTags(TagHelperContext context, TagHelperOutput output, List<string> files)
{
foreach (var file in files)
{
@ -45,17 +34,5 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling
}
}
protected virtual string GenerateBundleName(TagHelperContext context, TagHelperOutput output, List<string> fileList)
{
return fileList.JoinAsString("|").ToMd5();
}
protected virtual async Task<List<string>> GetFileList(TagHelperContext context, TagHelperOutput output)
{
var fileList = new List<string>();
context.Items[AbpBundleFileTagHelperService.ContextFileListKey] = fileList;
await output.GetChildContentAsync();
return fileList;
}
}
}

3
src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpStyleBundleTagHelper.cs

@ -1,12 +1,11 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.Threading;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling
{
//TODO: Move to Volo.Abp.AspNetCore.Mvc.UI package.
[HtmlTargetElement("abp-style-bundle", TagStructure = TagStructure.NormalOrSelfClosing)]
public class AbpStyleBundleTagHelper : AbpTagHelper<AbpStyleBundleTagHelper, AbpStyleBundleTagHelperService>
public class AbpStyleBundleTagHelper : AbpTagHelper<AbpStyleBundleTagHelper, AbpStyleBundleTagHelperService>, IBundleTagHelper
{
public string Name { get; set; }

44
src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpStyleBundleTagHelperService.cs

@ -1,43 +1,32 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling
{
public class AbpStyleBundleTagHelperService : AbpTagHelperService<AbpStyleBundleTagHelper>
public class AbpStyleBundleTagHelperService : AbpBundleTagHelperServiceBase<AbpStyleBundleTagHelper>
{
private readonly IBundleManager _bundleManager;
public AbpStyleBundleTagHelperService(IBundleManager bundleManager)
: base(bundleManager)
{
_bundleManager = bundleManager;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
protected override void CreateBundle(string bundleName, List<string> files)
{
output.TagName = null;
var bundleName = TagHelper.Name;
var files = await GetFileList(context, output);
if (bundleName.IsNullOrEmpty())
{
bundleName = GenerateBundleName(context, output, files);
}
_bundleManager.CreateDynamicStyleBundle(
BundleManager.CreateStyleBundle(
bundleName,
configuration => configuration.AddFiles(files.ToArray())
);
}
var bundleFiles = _bundleManager.GetStyleBundleFiles(bundleName);
await output.GetChildContentAsync(); //TODO: Suppress child execution!
output.Content.Clear();
AddLinkTags(context, output, bundleFiles);
protected override List<string> GetBundleFiles(string bundleName)
{
return BundleManager.GetStyleBundleFiles(bundleName);
}
protected virtual void AddLinkTags(TagHelperContext context, TagHelperOutput output, List<string> files)
protected override void AddHtmlTags(TagHelperContext context, TagHelperOutput output, List<string> files)
{
foreach (var file in files)
{
@ -45,18 +34,5 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling
$"<link rel=\"stylesheet\" type=\"text/css\" href=\"{file}\" />{Environment.NewLine}");
}
}
protected virtual string GenerateBundleName(TagHelperContext context, TagHelperOutput output, List<string> fileList)
{
return fileList.JoinAsString("|").ToMd5();
}
protected virtual async Task<List<string>> GetFileList(TagHelperContext context, TagHelperOutput output)
{
var fileList = new List<string>();
context.Items[AbpBundleFileTagHelperService.ContextFileListKey] = fileList;
await output.GetChildContentAsync();
return fileList;
}
}
}

7
src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/IBundleTagHelper.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling
{
public interface IBundleTagHelper
{
string Name { get; }
}
}

39
src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleCollection.cs

@ -1,18 +1,18 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
{
public class BundleCollection
{
private readonly Dictionary<string, BundleConfiguration> _bundleContributors;
private readonly ConcurrentDictionary<string, BundleConfiguration> _bundleContributors;
public BundleCollection()
{
_bundleContributors = new Dictionary<string, BundleConfiguration>();
_bundleContributors = new ConcurrentDictionary<string, BundleConfiguration>();
}
//TODO: Seperate to Add and WithFiles/WithContributors methods instead of coupling
public BundleConfiguration Add(string bundleName)
{
if (_bundleContributors.ContainsKey(bundleName))
@ -20,43 +20,40 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
throw new AbpException($"There is already a bundle added with given {nameof(bundleName)}: {bundleName}");
}
var bundleConfiguration = new BundleConfiguration(bundleName);
_bundleContributors.Add(bundleName, bundleConfiguration);
return bundleConfiguration;
return _bundleContributors.AddOrUpdate(bundleName, new BundleConfiguration(bundleName), (n, c) => c);
}
public BundleConfiguration Get(string bundleName)
{
if (!_bundleContributors.ContainsKey(bundleName))
{
throw new AbpException($"There is no bundle added with given {nameof(bundleName)}: {bundleName}");
}
CheckBundle(bundleName);
return _bundleContributors[bundleName];
}
public BundleConfiguration GetOrAdd(string bundleName, Action<BundleConfiguration> configureAction = null)
public BundleConfiguration GetOrAdd(string bundleName)
{
return GetOrAdd(bundleName, c => { });
}
internal BundleConfiguration GetOrAdd(string bundleName, Action<BundleConfiguration> configureAction)
{
return _bundleContributors.GetOrAdd(
bundleName,
() =>
{
var configuration = new BundleConfiguration(bundleName);
configureAction?.Invoke(configuration);
configureAction.Invoke(configuration);
return configuration;
});
}
public List<string> GetFiles(string bundleName)
{
var bundleConfiguration = _bundleContributors.GetOrDefault(bundleName);
if (bundleConfiguration == null)
{
throw new AbpException("Undefined bundle: " + bundleName);
}
CheckBundle(bundleName);
var files = new List<string>();
var bundleConfiguration = _bundleContributors[bundleName];
foreach (var contributor in bundleConfiguration.Contributors)
{
contributor.Contribute(files);
@ -64,5 +61,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
return files;
}
private void CheckBundle(string bundleName)
{
if (!_bundleContributors.ContainsKey(bundleName))
{
throw new AbpException($"There is no bundle with given {nameof(bundleName)}: {bundleName}");
}
}
}
}

21
src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleManager.cs

@ -34,31 +34,16 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
public List<string> GetScriptBundleFiles(string bundleName)
{
//if (_hostingEnvironment.IsDevelopment())
{
return _options.ScriptBundles.GetFiles(bundleName);
}
return new List<string>
{
_cache.GetOrAdd(
"SCRIPT:" + bundleName,
() => _bundler.CreateBundle(
_options.ScriptBundles.GetFiles(bundleName)
)
)
};
return _options.ScriptBundles.GetFiles(bundleName);
}
public void CreateDynamicStyleBundle(string bundleName, Action<BundleConfiguration> configureAction)
public void CreateStyleBundle(string bundleName, Action<BundleConfiguration> configureAction)
{
//TODO: How to handle concurrency!
_options.StyleBundles.GetOrAdd(bundleName, configureAction);
}
public void CreateDynamicScriptBundle(string bundleName, Action<BundleConfiguration> configureAction)
public void CreateScriptBundle(string bundleName, Action<BundleConfiguration> configureAction)
{
//TODO: How to handle concurrency!
_options.ScriptBundles.GetOrAdd(bundleName, configureAction);
}
}

6
src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/IBundleManager.cs

@ -3,14 +3,16 @@ using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
{
//TODO: Bundle system needs refactoring/redesign
public interface IBundleManager
{
List<string> GetStyleBundleFiles(string bundleName);
List<string> GetScriptBundleFiles(string bundleName);
void CreateDynamicStyleBundle(string bundleName, Action<BundleConfiguration> configureAction);
void CreateStyleBundle(string bundleName, Action<BundleConfiguration> configureAction);
void CreateDynamicScriptBundle(string bundleName, Action<BundleConfiguration> configureAction);
void CreateScriptBundle(string bundleName, Action<BundleConfiguration> configureAction);
}
}
Loading…
Cancel
Save