I bundle all my JS assets into one minified uglified file via r.js (part of requirejs).
If any unhandled errors occur on the browser, I use raygun (like Airbrake) to report it back to me. The only problem is the line number I get in my error message, refers to the bundled minified file. Which doesn't help much.
Is there a way to correctly map the line number of my single minified and uglified bundled asset, into the individual JS file with the correct line number?
The first thing you need to do is have r.js generate a source map of the bundle. To do this, in the options you pass to r.js you need to have the option generateSourceMaps set to true and you must set the optimize option to "uglify2" or
"closure" with a closure compiler jar build after r1592 (20111114 release)."
(I'm citing from this documentation.) I've done it with optimize set to "uglify2" and was able to get decent references to the original source code in Chrome.
The logging service must also support it. This post over at the raygun forums suggests that raygun does not yet support source maps.
Someone created a list of such services as a gist over at github. Some of the services are marked as supporting source maps. I can't vouch for its accuracy but it could be a good starting point to find a service that supports it.
Related
I'm writing a large application with several 3rd party libraries. Right now, I am using a post-build script to concatenate all of my .js files together, along with the output of all my combined typescript files. This works fine, but makes it so the source mappings are off for debugging.
What I'd like to accomplish is converting all of my 3rd party .js libraries into typescript (and by converting, I mean just renaming them from .js to .ts since typescript is a superset). From here, I can just use the typescript compiler to output all of the combined typescript files with accurate source maps so debugging in typescript will still work. However, the issue I'm running into is that the 3rd party libraries have various errors, so I cannot get the build to work.
Is there a way in Visual Studio to have my existing typescript files compiled as they are while having these third party libraries compiled but ignoring all errors and have the result all output into one single javascript file?
TypeScript is able to forgive a whole host of errors and still provide compiled JavaScript, but in some cases the error will prevent it - i.e. the code will no longer make sense to the compiler because it cannot determine enough information.
The solution would be to splatter lots of : any type annotations to suppress errors.
The real danger with your approach will be trying to keep your edited versions of all of the libraries updated as they change.
Here is an alternative...
Combine all of your third party libraries into a single file, then combine all of your TypeScript files into a single file (so your source maps work).
This will allow you to easily debug and you could always crush the two files together later if the extra HTTP request worries you.
The following article explains that in order to find the source map of a JavaScript file such as jQuery, the web browser looks inside the JavaScript code and looks for the line containing the sourceMappingURL directive embedded in a JavaScript comment. For instance, the jQuery 1.9.0 minified file contains such a directive at the end of a file. However, the more recent jQuery 1.11.1 minified distribution does not contain such a directive, but a jQuery 1.11.1 map file is also distributed with this (final stable jQuery 1) version. So how does the web browser find the map file for the minified file.
I guess the convention of web browsers looking for the sourceMappingURL directive was dropped in favor of following the naming convention of looking for a file of the same name, with .js replaced by .min. Is this what happened?
According to the documentation for the recently released Firefox Developer Edition, such browser still seems to be looking for the sourceMappingURL directive.
Thanks.
The reasoning behind dropping source mapping from recent versions is described on the JQuery blog
This release does not contain the sourcemap comment in the minified
file. Sourcemaps have proven to be a very problematic and puzzling
thing to developers, spawning hundreds of confused developers on
forums like StackOverflow and causing some to think jQuery itself was
broken.
We’ll still be generating and distributing sourcemaps, but you will
need to add the appropriate sourcemap comment at the end of the
minified file if the browser does not support manually associating map
files (currently, none do). If you generate your own jQuery file using
the custom build process, the sourcemap comment will be present in the
minified file and the map is generated; you can either leave it in and
use sourcemaps or edit it out and ignore the map file entirely.
We hope to bring back and improve sourcemap support in the future, but
at the moment neither the design nor the implementation seem suited
for situations like jQuery’s, where there are widely distributed files
on CDNs. We’d like sourcemaps (and browsers supporting them) to
gracefully handle situations like file renaming or missing files. See
our bug ticket for more information.
Why using jquery.min.map if:
jquery = 242 ko
jquery.min + jquery.min.map = 83 + 125 = 208 ko (the map is even greater than the library)
And if we remove the comments, we will get a small jquery that could be easier to read (and to debug).
So, why using the map if it will only add more than 100 ko and an extra request?
What is the best practice?
Source maps are loaded only when the developer tools are active. Browsers won't load them for application's users.
Edit: It should be mentioned that there are 2 types of source maps. One which is an external file and there is a link to it in the actual file and another one which is embedded in the main file. Browsers actually have to load the entire file (i.e. including the embedded source map) for the second type.
Check https://www.html5rocks.com/en/tutorials/developertools/sourcemaps/ for more information.
That's called a source map. This answer goes into detail about what they are, how they work, and why you would want to use it.
EDIT
Extracted answer from the above SO link for posterity. Answered by #aaronfrost
The .map files are for js and css files that have been minified. They are called SourceMaps. When you minify a file, like the angular.js file, it takes thousands of lines of pretty code and turns it into only a few lines of ugly code. Hopefully, when you are shipping your code to production, you are using the minified code instead of the full, unminified version. When your app is in production, and has an error, the sourcemap will help take your ugly file, and will allow you to see the original version of the code. If you didn't have the sourcemap, then any error would seem cryptic at best.
Same for CSS files. Once you take a SASS or LESS file and compile it to CSS, it looks nothing like it's original form. If you enable sourcemaps, then you can see the original state of the file, instead of the modified state.
What is it for?
To de-reference uglified code
How can a developer use it?
You use it for debugging a production app. In development mode you can use the full version of Angular. In production, you would use the minified version.
Should I care about creating a js.map file?
If you care about being able to debug production code easier, then yes, you should do it.
How does it get created?
It is created at build time. There are build tools that can build your .map file for you as it does other files. https://github.com/gruntjs/grunt-contrib-uglify/issues/71
I've been beginning a new Play project using Play v2.2.1 and am having difficulty getting the Google Closure compiler to properly handle goog.provide and goog.require statements. All of my Javascript files are in the app/assets folder and are being served up properly using Play's reverse routing. However, any time I try to use goog.require(_namespace_), I get the compilation error "required namespace namespace not provided yet." This happens whether I link to just the file with the require or both the requiring and providing .js files in my view template. However, it does not happen if I link to the minified version of the requiring file.
For the most part, the closure compiler seems to be working; for example, the .min.js files do exist (even if they don't actually seem to be getting minified, but that is probably a separate issue). I haven't changed any build settings in my Play project.
The Play documentation on using the Google Closure compiler for Play 2.2.x does not directly reference using goog.require() and goog.provide() for Javascript dependencies. It does, however, give a link to using RequireJS to do the job. Is there no way to take advantage of the Closure compiler's require system?
As a disclaimer, I am not very experienced with the Closure compiler. I have used it at work where we minify all of our Javascript to one file, so all I know is basically what result I expect to see. I was hoping Play would have taken care of most of the dirty work of making everything "just work", but it doesn't seem as straightforward as I'd hoped and I haven't had any success solving the problem after a few hours of scouring the web.
There is a plovr plugin that Benn McCann did based on some stuff I posted on the play mailing list a long time ago, which from what I remember was created because of this exact problem, maybe you could use that: https://github.com/benmccann/play-plovr-plugin
I think the question says most of it. I have an autogenerated ManualSpecRunner.html file as created by maven / jasmine plug-in and I've got it to put itself into the deployable .war by using:
<jasmineTargetDir>${basedir}/pathForMyWebapp</jasmineTargetDir>
However, all the links to js files within the ManualSpecRunner.html are hard coded file:/// references - this is a bit mental, I want them to just be the relative paths to the files that are also in the webapp i.e.
Currently it gives me this path:
file:///home/username/code/HEAD/pathForMyWebapp/js/yui.js
whereas I need it to have the far more simple
/pathForMyWebapp/js/yui.js
I have tried changing two other variables in the maven script, but neither seems to have the desired effect, neither of these configuration options do what I need, the second having seemingly no effect:
<jsSrcDir>/pathForMyWebapp</jsSrcDir>
nor
<jsTestSrcDir>/pathForMyWebapp</jsTestSrcDir>
I've looked through the documentation but think I must be missing something (also, more notes on various config params listed in https://github.com/searls/jasmine-maven-plugin/blob/master/src/main/java/com/github/searls/jasmine/AbstractJasmineMojo.java are meant to do would be helpful so I can work out if I'm doing it wrong or if it's not possible!)
Any suggestions?
[p.s. I've changed some of the path names as they've got sensitive info in them, so please ignore their oddness!]
I think I understand the source of your confusion. It looks like you're trying to direct the target of the jasmine-maven-plugin to a directory inside your project's packaged *.war file so that you can run your specs against the code after it's deployed to a server, is that correct?
Unfortunately, the plugin wasn't designed with that use in mind. The jasmineTargetDir directory is usually left at its default value of target/jasmine and wasn't intended to be bundled with your application (it's analogous to the target/surefire-reports generated by maven-surefire-plugin for Java unit tests). So the reason that the script tags in ManualSpecRunner.html point to invalid locations is because that file is generated in order to be run from the local filesystem in a browser from the workstation that's building the project (to facilitate TDD).
All of that to say, if I'm reading your intention right, I think it'd be a cool feature to build a third spec runner that could be deployed with the app and executed remotely. (Especially if the project's Jasmine specs are functional/integration as opposed to isolated unit tests.) Unfortunately that's not something the project does yet.
I'm afraid that for now, if you needed to bundle the jasmine tests and execute them on the deployed server, you would need to copy ManualSpecRunner.html and jasmine into your src/main/webapp, fix the script tag references, and then manually maintain it as files are added and removed.
Make sense?