Working with Bootstrap, Less and Azure

My website www.music4dance.net runs as an application service in Windows Azure and uses Boostrap 3 for styling. Several years ago I explored ways to use Less with Bootstrap in order to set up different themes for different parts of the site and landed on using BundleTransformer to compile the Less files on the fly.  At the time it seemed like the best solution and worked well for several years.

The fragile part of this solution is that it depended on having a JavaScript engine available.  On a machine that I control, this is no big deal.  But in the context of an Azure Application Service I don’t control the image and don’t really know what is available.  I don’t recall exactly how I landed on this solution, but I found that of the options listed in the JavaScriptEngineSwitcher that JavaScriptEngineSwitcher.Msie worked for my purposes.

When my website mysteriously started crashing a couple of days ago, I discovered that this solution was no longer working.  After a bit of instrumenting, I discovered that the line of code that was performing the bunding was throwing an exception:

During translation of LESS code, readed from the file ‘/Content/bootstrap/music-theme.less’, to CSS code error has occurred.

See more details: A fatal exception has occurred in a JavaScript runtime

Check out the full call stack if you’re interested.

My first thought was to try a fully managed version of a JavaScript enginge.  JavaScriptEngineSwitcher supports two – Jint and Jurassic.  Jurassic didn’t work even on my local machine, it threw a stack overflow exception.  Jint actually worked on my local machine but was incredibly slow.  When I attempted to deploy to Azure it just appeared to hang.

Now, I’m reasonably sure that the Chakra engine and possibly even V8 is running on an Azure application service.  But since I couldn’t figure out how to verify that or which version they were running I decided to look for a different solution.  Since I only have four themes there is no real need to generate them dynamically, I can just build them at compile time and deploy all four .css files.

So that’s what I’m doing.  Mads Kristensen’s web compiler does a perfectly good job of compiling Less to Css on save and at build time.   And since I’m using git for source control these days, I can just let it add the generated .css files to my project and deploy automatically (in older SCC systems I would have had to worry about the files getting locked).  No more dependencies on server-side JavaScript engines and there’s a small bonus that I suspect that the site spins up a bit faster.

I would still be interested in knowing what JavaScript engines are available on Azure Application Service instances and how I can determine versions so that I could test on a local instance, but it is no longer urgent since the web compiler solution is a more than adequate substitution.

Call Stack for BundleConfig Exception:

Void InnerTranslate(BundleTransformer.Core.Assets.IAsset, BundleTransformer.Less.Internal.LessCompiler, Boolean)
at BundleTransformer.Less.Translators.LessTranslator.InnerTranslate(IAsset asset, LessCompiler lessCompiler, Boolean enableNativeMinification)
at BundleTransformer.Less.Translators.LessTranslator.Translate(IList`1 assets)
at BundleTransformer.Core.Transformers.TransformerBase.Translate(IList`1 assets, Boolean isDebugMode)
at BundleTransformer.Core.Transformers.TransformerBase.Transform(IList`1 assets, BundleContext bundleContext, BundleResponse bundleResponse, VirtualPathProvider virtualPathProvider, Boolean isDebugMode)
at BundleTransformer.Core.Transformers.TransformerBase.Process(BundleContext bundleContext, BundleResponse bundleResponse, Boolean isDebugMode)
at BundleTransformer.Core.Transformers.TransformerBase.Process(BundleContext bundleContext, BundleResponse bundleResponse)
at System.Web.Optimization.Bundle.ApplyTransforms(BundleContext context, String bundleContent, IEnumerable`1 bundleFiles)
at System.Web.Optimization.Bundle.GenerateBundleResponse(BundleContext context)
at System.Web.Optimization.Bundle.GetBundleResponse(BundleContext context)
at System.Web.Optimization.BundleResolver.GetBundleContents(String virtualPath)
at System.Web.Optimization.AssetManager.EliminateDuplicatesAndResolveUrls(IEnumerable`1 refs)
at System.Web.Optimization.AssetManager.DeterminePathsToRender(IEnumerable`1 assets)
at System.Web.Optimization.AssetManager.RenderExplicit(String tagFormat, String[] paths)
at System.Web.Optimization.Styles.RenderFormat(String tagFormat, String[] paths)
at System.Web.Optimization.Styles.Render(String[] paths)
at ASP._Page_Views_Shared__Layout_cshtml.Execute() in D:\home\site\wwwroot\Views\Shared\_Layout.cshtml:line 42
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
at System.Web.WebPages.WebPageBase.<>c__DisplayClass3.<RenderPageCore>b__2(TextWriter writer)
at System.Web.WebPages.HelperResult.WriteTo(TextWriter writer)
at System.Web.WebPages.WebPageBase.Write(HelperResult result)
at System.Web.WebPages.WebPageBase.RenderSurrounding(String partialViewName, Action`1 body)
at System.Web.WebPages.WebPageBase.PopContext()
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)
at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)
at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<>c__DisplayClass2b.<BeginInvokeAction>b__1c()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult)
at System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult)
at System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult)
at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)<span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>

1 thought on “Working with Bootstrap, Less and Azure”

Leave a Reply