31

We are using the ASP.NET Web Optimization Framework with bundles and minification. One bundle just contains jquery and modernizr. This all worked fine with jquery 1.8.3 but since we updated to 1.9.0 the combination jquery/modernizer bundle is not working anymore.

bundles.Add(new ScriptBundle("~/st-scripts-load-first.js")
       .Include("~/Resources/JavaScript/jquery-1.9.0.js",
                "~/Resources/JavaScript/modernizr.form-placeholder.js"));

We have both jquery-1.9.0.js and jquery-1.9.0.min.js in the directory. If there is no .min file the optimization framework will generate one automatically. It doesn't work if the .min file is there or not.
It works if compilation debug="true" and there is no minification or bundling.

/* Minification failed. Returning unminified contents.
(5,2-3): run-time warning JS1195: Expected expression: *
(11,60-61): run-time warning JS1004: Expected ';': {
(395,2-3): run-time warning JS1195: Expected expression: )
(397,21-22): run-time warning JS1004: Expected ';': {
(397,4590-4591): run-time warning JS1195: Expected expression: )
(398,28-29): run-time warning JS1195: Expected expression: )
(398,84-85): run-time warning JS1002: Syntax error: }
(402,44-45): run-time warning JS1195: Expected expression: )
(408,1-2): run-time warning JS1002: Syntax error: }
(393,5-22): run-time warning JS1018: 'return' statement outside of function: return Modernizr;
(404,5,406,16): run-time warning JS1018: 'return' statement outside of function: return !!('placeholder' in (Modernizr.input || document.createElement('input')) &&
               'placeholder' in (Modernizr.textarea || document.createElement('textarea'))
             );
 */
Remy
  • 12,555
  • 14
  • 64
  • 104

4 Answers4

73

I'm sure that the cause of your problem is the last line of jquery-1.9.0.min.js:

//@ sourceMappingURL=jquery.min.map

The unminified version of jQuery 1.9 does not contain this. I'll explain why in a minute.

I've noticed myself that when jquery-1.9.0.min.js is bundled with another file - and that other file follows jquery-1.9.0.min.js - then the following JS file is, in a manner of speaking, corrupted.

The reason is that the start of the following file is appended to the "//@" line of jQuery, which means that it then becomes one long, extended comment. In your case this meant that the

window.Modernizr=function(n,t,i){function...

script at the start of Modernizr was outputed from the bundling process as a comment like so:

//@ sourceMappingURL=jquery.min.map window.Modernizr=function(n,t,i){function...

There's a discussion on jQuery's Bug Tracker regarding this.

Your options are either to remove that last line or to wrap it in multi-line comment symbols:

/*
//@ sourceMappingURL=jquery.min.map
*/

Also, you can see that Modernizr also contains a source map at the end of its minified version. And with good reason.

The rationale behind it is to help you in debugging a problem when the minified version of the code has been used. This line tells the browser that this minified file maps to another file which can aid in debugging. To take advantage of this you need to have that referenced file (jquery.min.map) on the server or downloaded to the client. Plus, I believe that Chrome is the only browser currently supporting this; it's still under development at Firefox.

This page has an excellent explanation of Source Maps.

So in summary, removing it shouldn't really cause you any problems unless you wish to map back to the original version of the source while debugging in the browser. In your case, because of the way that ASP.NET's Optimization Framework works, when debug="True" it will serve up the unminified versions anyway, so you probably don't have a need to use the sourceMappingURL.

awj
  • 7,482
  • 10
  • 66
  • 120
  • 6
    fixed in jquery but not in jquery.migrate :( – TheVillageIdiot Mar 19 '13 at 01:16
  • Village, thanks for the heads up. Same fix as jQuery. Add the /* */ tags around the sourceMapping at the end of jquery.migrate.min.js – Sam Apr 17 '13 at 18:05
  • I'm assuming that you'll want the comment in the end for debugging purposes, but I'm surprised the single line comment wasn't removed completely in any case by the optimizer, but I would have assumed it should be able to do that (and might be a nice idea in any case on a production system since you're less likely to need to debug it). – jamiebarrow May 03 '13 at 08:34
  • This is also a problem for Kendo UI v2013.3.1119. Thanks, this was very helpful. – Daniel Schilling Jan 27 '14 at 22:13
6

I was unable to reply to awj's answer, above, so I just voted it up. Fantastic piece of detective work. I wanted to add on to a comment, that while the problem was indeed fixed in jquery 1.9.1 it now shows up in the jquery-migrate-1.1.0

I noticed the map file reference as only a single-line comment at the end of the "jquery-migrate-1.1.0.min.js" file. So following awj's suggestion I made it a multi-line comment.

So line 3:

//@ sourceMappingURL=dist/jquery-migrate.min.map

now becomes lines 3, 4, and 5 as follows:

/*
//@ sourceMappingURL=dist/jquery-migrate.min.map
*/

Once I uploaded back to my ISP I have full ajax functionality again.

Thank you again AWJ, this has helped out greatly!

djmarquette
  • 712
  • 8
  • 17
3

Reading the answers, even the accepted answer, the advised solution to this problem is to modify your scripts so the bundler has no trouble with this. This makes no sense to me, this is clearly a bug of the bundler not concatenating different scripts properly, specifically the bundler has a trouble when the last line of the n script is a normal line comment

// this is the last line of the n script

and then your next script does not start with a single line comment

function(){ var ...

the bundler, is by default configured with a ; as a the ConcatenationToken so the bundled code ends up being something like this:

// this is the last line of the n script;function(){ var ...

Surely the script loading fails with a syntax error somewhere.

It has been proposed to modify the latest line of the script to not be an inline comment, make it a multiline comment, so when the code ends with */ the parser will be ok with a function declaration or something else right after it.

I don't like modifying my scripts, many are authored by somebody else (jquery, etc.) and I don't want to modify them, what if I have to upgrade them and will find this bug again after I upgrade a website and it doesn't run with debug="true" in the config.

I come with this solution working better for me

bundles.Add(new ScriptBundle("~/bundles/mobile") { 
                ConcatenationToken = ";\r\n" }
       .Include("~/Scripts/jquery-1.11.3*",
                "~/Scripts/jquery-timeago*",
                "~/Scripts/jquery.mobile-1.4.5*",

This way we force the bundler to always separate the scripts with a new line character. It should do this by default when the last line of the previous script is a single line comment.

Guillermo Ruffino
  • 2,940
  • 1
  • 26
  • 23
0

There may be something wrong with your copy of modernizr.form-placeholder.js .

I just ran into the same error trying to load jquery.peity.js.

When I removed the library, page loaded fine. So I just went and grabbed the raw js from their site and remade the file and it loaded with no problems.

zach
  • 782
  • 2
  • 10
  • 22
  • If you minified the file yourself then yes, the minified version probably will not include a source map reference. The sourceMappingURL is only included by some minification engines and by the sounds of it, not by the one that you've used. – awj Jan 24 '13 at 11:26