buunguyen / combres

ASP.NET and MVC performance optimization library ⛺
Other
123 stars 36 forks source link

Failing to load resource set in v2.3.0.4 with .NET 4.5.2+ and MVC5 #52

Open peterlukerow opened 5 years ago

peterlukerow commented 5 years ago

We've been using Combres for a long time and recently upgraded to v2.3.0.4 after one of our test servers experienced an issue where it failed to load JS/CSS resources. Although as it turns out that didn't solve the issue, however we stuck with the latest version of Combres.

Unfortunately we are now experiencing a related issue. We have a JS resource set that includes another resource set plus a couple of other JS files. When running on local dev machines using real IIS on their machines it all works nicely in debug. However after building for release mode and thus using minified/concatenated settings in the combres.release.xml (vs combres.xml for debug) when we deploy this to a real IIS sever (Win Server 2012R2) that is used by our internal test team if fails to load a JS resource set, which as you might expect leads to various things not working.

The event log on my machine when using the release built version and the error is generated is:

    Exception type: EcmaScriptRuntimeException 
    Exception message: syntax error
   at Yahoo.Yui.Compressor.CustomErrorReporter.Error(String message, String sourceName, Int32 line, String lineSource, Int32 lineOffset)
   at EcmaScript.NET.Parser.AddError(String messageId)
   at EcmaScript.NET.Parser.ReportError(String messageId)
   at EcmaScript.NET.Parser.primaryExpr()
   at EcmaScript.NET.Parser.memberExpr(Boolean allowCallSyntax)
   at EcmaScript.NET.Parser.unaryExpr()
   at EcmaScript.NET.Parser.mulExpr()
   at EcmaScript.NET.Parser.addExpr()
   at EcmaScript.NET.Parser.shiftExpr()
   at EcmaScript.NET.Parser.relExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.eqExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.bitAndExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.bitXorExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.bitOrExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.andExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.orExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.condExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.assignExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.expr(Boolean inForInit)
   at EcmaScript.NET.Parser.primaryExpr()
   at EcmaScript.NET.Parser.memberExpr(Boolean allowCallSyntax)
   at EcmaScript.NET.Parser.unaryExpr()
   at EcmaScript.NET.Parser.mulExpr()
   at EcmaScript.NET.Parser.addExpr()
   at EcmaScript.NET.Parser.shiftExpr()
   at EcmaScript.NET.Parser.relExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.eqExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.bitAndExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.bitXorExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.bitOrExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.andExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.orExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.condExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.assignExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.expr(Boolean inForInit)
   at EcmaScript.NET.Parser.primaryExpr()
   at EcmaScript.NET.Parser.memberExpr(Boolean allowCallSyntax)
   at EcmaScript.NET.Parser.unaryExpr()
   at EcmaScript.NET.Parser.mulExpr()
   at EcmaScript.NET.Parser.addExpr()
   at EcmaScript.NET.Parser.shiftExpr()
   at EcmaScript.NET.Parser.relExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.eqExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.bitAndExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.bitXorExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.bitOrExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.andExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.orExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.condExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.assignExpr(Boolean inForInit)
   at EcmaScript.NET.Parser.expr(Boolean inForInit)
   at EcmaScript.NET.Parser.statementHelper(Node statementLabel)
   at EcmaScript.NET.Parser.statement()
   at EcmaScript.NET.Parser.Parse()
   at Yahoo.Yui.Compressor.JavaScriptCompressor.Parse(StreamReader stream, ErrorReporter reporter)
   at Yahoo.Yui.Compressor.JavaScriptCompressor.DoCompress(String source)
   at Combres.Minifiers.YuiJSMinifier.Minify(Settings settings, ResourceSet resourceSet, String combinedContent)
   at Combres.RequestProcessor.MinifyContent(MinifierInfo minifierInfo, IEnumerable`1 resources, String combinedContent)
   at Combres.DefaultProcessingWorkflow.ProcessMergeGroup(ICollection`1 minifiedContents, IEnumerable`1 mergeGroup, MinifierInfo currentMinifier)
   at Combres.DefaultProcessingWorkflow.Execute()
   at Combres.RequestProcessor.Execute()
   at Combres.CombresHandler.ProcessRequest(HttpContext context)
   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)
peterlukerow commented 5 years ago

In a game of wack-a-mole, if I config Combres to use msajax JS minifier then the public side of my site that caused the exception in the opening issue statement works fine. However, now the admin side of my site appears to not minify the JS correctly and this ends up with a JS syntax error that then prevents jQuery from working and thus the site fails to work correctly.

buunguyen commented 5 years ago

It looks like the minifier can't parse the JS. Maybe try with a different minifier to see if any luck? There are 3 JS minifiers in total.

Besides, I haven't updated Combres for a while so it's stuck with old version of minifier. Would be great if someone could bump the version of both CSS and JS minifiers, I'd be happy to review a PR and coordinate to update NuGet.

peterlukerow commented 5 years ago

I tried the msajax one which works for the public area but then fails for the admin area. The other minifier didn't work at all.

I manage to figure it out in the end. The problem with the YUI (default) minifier was that our JS was using some ECMAScript 6 syntax - specifically "() => { function code }" and "(event) => { function code }". Converting this JS to something like "function() { func code }" and "function(event) { func code}" solved the issue.

So it seems like none of the minifiers can correctly parse the latest JS standards correctly and if they can they fail for other reasons. I didn't figure out the other reasons because of the above change working so I was able to stick with the default minifier.

buunguyen commented 5 years ago

I see. The minifiers are very out of date, I'm sure the latest version would work. That being said, I don't even have a window box these days to build and test. So if anyone wanting to contribute, I'll add as collaborator on this repo.