You could use BundleTransformer to compile your LESS server side.
It can depend on how you want to serve the file. If you know all the tenants then just add add a bundle url for each tenant application to the bundle config.
var themeStyles = new CustomStyleBundle("~bundles/theme/tenant").Include("~/Content/theme.less");
themeStyles.Builder = new ThemeBuilder();
BundleTable.Bundles.Add(themeStyles);
If you don't and the tenants are flexible as was the case in our situation then add the following controller action for your themes.
[Route("bundles/theme/{id}")]
public ContentResult Theme(string id)
{
var tenantThemePath = string.Format("~/bundles/theme/{0}", id);
// Check that bundle has not already been added.
if (BundleTable.Bundles.All(x => x.Path != tenantThemePath))
{
var themeStyles = new CustomStyleBundle(tenantThemePath ).Include("~/Content/theme.less");
themeStyles.Builder = new ThemeBuilder();
BundleTable.Bundles.Add(themeStyles);
}
var context = new BundleContext(HttpContext, BundleTable.Bundles, institutionPath);
var response = BundleTable.Bundles.GetBundleFor(tenantThemePath).GenerateBundleResponse(context);
Response.Cache.SetCacheability(response.Cacheability);
return Content(response.Content, response.ContentType);
}
The ThemeBuilder implementation for BundleTransformer
public class ThemeBuilder : IBundleBuilder
{
public string BuildBundleContent(Bundle bundle, BundleContext context, IEnumerable<BundleFile> files)
{
var lessTranslator = bundle.Transforms.OfType<StyleTransformer>()
.Where(x => x != null)
.Select(x => x.Translators.OfType<LessTranslator>().FirstOrDefault())
.FirstOrDefault();
if (lessTranslator == null)
{
return string.Empty;
}
lessTranslator.GlobalVariables = GetThemeVariables();
return string.Empty;
}
private string GetThemeVariables()
{
// Simplified for brevity
// This will be translated to less variables by the BundleTransformer
// themeColour should correspond to a variable name in your less file.
return string.Format("themeColour={0}", themeColour);
}
}
You will need away of getting the theme colours out we stashed those variables in HttpContext stores so that we could pull them out using an extension method in the GetThemeVariables method.
I hope this helps.
UPDATE
I've expanded on my original answer and created a more reusable way of including themes.
Demo site here: http://bundletransformer-theme-builder.azurewebsites.net/
GitHub repo here: https://github.com/benembery/bundle-transformer-theme-builder
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…