I'd like to wrap my code in a custom type of Closure during build process with Grunt (and uglify). This manipulation must keep the sourceMap working.
My use case is to wrap all my code inside a try/catch block to allow logging of the errors in production - without losing access to the stacktrace (unlike window.onerror). I'd probably use Raven-js 1.0 to work this out.
Anyone know how I could manage this easily?
If you just have tips that might bring a full answer, that'll be accepted too
Finally, I've found a grunt plugin (grunt-wrap) who does exactly this:
wrap: {
modules: {
src: ['assets/*.js'],
dest: 'dist/',
wrapper: ['try {', '} catch(e) { Raven.captureException(e); }']
}
}
If you're interested in raven-js. I've been with the try/catch over Raven.context as this won't create a new global closure around the code.
Related
I'm writing tests for a JS application using Jasmine and testdouble.js as a mocking library. I am using AMD format to organize code in modules, and RequreJS as a module loader. I was wondering how to use testdouble.js to replace dependency for the module being tested that is in AMD format and it is loading via RequireJS. The documentation is unclear about this or I am missing something, so if someone could point me in the right direction.
I'll post the example bellow that illustrates my setup and the problem that I am facing.
car.js
define("car", ["engine"], function(engine) {
function drive = {
engine.run();
}
return {
drive: drive
}
});
engine.js
define("engine", function() {
function run() {
console.log("Engine running!");
}
return {
run: run
}
});
car.spec.js
define(["car"], function(car) {
describe("Car", function() {
it("should run the motor when driving", function() {
// I am not sure how to mock the engine's object run method
// and where to place that logic, in beforeEach or...
td.replace(engine, "run");
car.drive();
// How to verify that when car.run() has executed, it calls this mocked method
td.verify(engine.run());
});
});
});
testdouble.js does not have any explicit support for AMD modules. The only module-related tricks it offers are Node.js specific and built on top of Node's CJS module loader.
What you would need to do in this case is require from the test a reference to engine and replace the run property, which it seems like you've done (your example is incomplete).
If you do this, don't forget to run td.reset() in an afterEach to restore the original properties to anything you replace!
I am using Grunt as my Build Tool and ESLint as my linting tool for an app I am working on. I am also using the Underscore Node package, and have made use of it in my app. Unfortunately, when I run ESLint on my code, it thinks that _ is an undefined variable in the following line:
return _.pluck(objects, nameColumn);
This is the error it is giving me:
78:21 error "_" is not defined no-undef
I would prefer not to disable the no-undef rule for ESLint, and I have tried installing the Underscore plugin, but I am still receiving this error. If anyone else has any ideas for what to try with this, I would be very appreciative!
If there is any further information I can give that would help anyone with helping me get this figured out, just let me know!
The official documentation should give you an idea on how to fix this.
Any reference to an undeclared variable causes a warning, unless the variable is explicitly mentioned in a /*global ...*/ comment, or specified in the globals key in the configuration file.
The easiest fix would be to add
/* global _ */
at the top of your file.
Or better, explicitly specify that the variable is read-only, to disallow overwriting the variable:
/* global _:readonly */
But since you'll have to do that for each new js file, it can get annoying. If you are using underscore often, I'd suggest to add globals to your .eslintrc file, for example:
{
"globals": {
"_": "readonly"
}
}
And save this as .eslintrc in your project root, or optionally in your user home directory. Although some say the latter not recommended, it can sometimes be convenient, but you have to remember that you have it there :)
Explanation of the above rule: "_": "readonly" (used to be "_": false, now deprecated) means that a variable named _ tells eslint that this variable is defined globally and it will not emit any no-undef errors for this variable. As #sebastian pointed out, "readonly" (or false - deprecated) means that the variable can't be overwritten, so the code _ = 'something else' would yield an error no-global-assign. If you were to instead use "_": "writable" (or "_": true - deprecated), this means that the value can be re-assigned and the previously mentioned error will not occur.
But keep in mind that this will only happen if you assign directly to the global variable as I have shown in the example. You can still shadow it and eslint won't say anything. For example, these snippets wouldn't yield the no-global-assign:
const _ = 'haha I broke your _'
or as function argument name, e.g.
function (_) {
console.log(_, 'might not be the _ you were looking for')
}
If you are using jest for testing - in your environment - in eslintrc.json
"env":{
"jest":true
}
I have several task to concatenate css and javascript together, here is an example:
gulp.task('javascript', function() {
return gulp.src([
libPath + 'jquery-2.1.4.min.js',
libPath + '*.js',
jsPath + 'app.js'
])
.pipe(concat('app.min.js'))
.pipe(uglify())
.pipe(gulp.dest(jsPath))
});
Ideally (in this example) I would like following order jQuery -> libraries -> app.js and so far, using code above it seems to work. However I conducted a little research and people seem to be using plugins like gulp-order or require streamqueue .. method instead of require gulp.src, thus I wanted to make sure that these are needed, or does gulp take care of that now?
For what I saw in the links, those plugins are used to order the stream of multiple files, like: gulp.src(["js/*.js"]), but you are explicitly declaring the order, so it works.
I am getting started with grunt-init templating and trying to write conditional prompts. I've been kicking this around for a few hours, and have had no real success. It probably doesn't help that javascript isn't my strongest language.
I found this answer, but it doesn't really handle what I am trying to do: grunt-init template conditional prompts
I am trying to do something along the lines of the following:
exports.template = function(grunt, init, done) {
init.process({}, [
// Prompt for these values.
{
name: 'css',
message: 'Which CSS Preprocess are you using?',
default: 'SASS/Less/Stylus/none'
}
if (css.value == 'SASS'){
// prompt for Compass / Bourbon / None;
}
], function(err, props) {
...
Obviously this doesn't work, but I have tried going through the grunt-init source and documentation, and haven't found anything helpful.
If this isn't possible, are there other grunt project generators that CAN handle this kind of conditional logic?
For anyone wondering, it appears that to do what I am requesting, you would have to modify the grunt-init source to handle these kind of conditionals. I ended up using the yeoman generator instead.
http://yeoman.io/generators.html
I have a require.config in my main like the following.
require.config({
baseUrl:'scripts/',
paths:{
jquery:'shell/lib/jquery/jquery-1.7.1'
// many libraries and modules are aliased here
},
map:{
'*':{
'underscore':'shell/lib/underscore/underscore'
// a few other modules are mapped here
}
}
});
I did this because the files defined in map are using internal dependencies(in their respective folders) using relative paths.
Now when I run optimizer, the modules defined in path are saved as module IDs, like jquery saved as jquery while those in map are getting complete paths, like 'underscore' as 'shell/lib/underscore/underscore' instead of 'underscore'.
This is causing problems as I am using 'underscore' in other modules also and there the optimized file is having 'underscore' instead of 'shell/lib/underscore/underscore'.
Is there some specific way to optimize when we give map configs or something I am missing? Please tell me how to fix it.
Thanks
I'm not sure to understand the issue:
This is causing problems as I am using 'underscore' in other modules also and there the optimized file is having 'underscore' instead of 'shell/lib/underscore/underscore'.
This seems to be the expected behavior, you mapped underscore to that path for all modules. So basically you are telling to r.js: each time that you find the underscore dependency rewrite it to shell/lib/underscore/underscore. If your modules use "internal paths" and you want do do the opposite (make them to reference underscore), you need to do the opposite mapping:
'some/path/underscore': 'underscore'
In that case all the modules will be pointing to the same underscore module. Even those that use some strange path for underscore.
In the extreme case that you need to control how r.js writes modules on disk. You can use the onBuildWrite property (see https://github.com/jrburke/r.js/blob/master/build/example.build.js#L517).
For example:
onBuildWrite: function ( moduleName, path, contents ) {
if ( path === './src/somefile.js' ) {
return contents.replace(/^define\('src\/underscore'/, "define('underscore'");
} else {
return contents;
}
}
This example is a "hack" that tell to r.js: when you process somefile.js, replace src/underscore with underscore (is exactly what you do with map... but is just to show you how you can use onBuildWrite to do nasty things).