Is there any convention regarding naming custom grunt tasks that include more than one word? For example: grunt-json-schema grunt plugin has json_schema task. One name includes dashes (-), the other includes underscores (_).
Obviously, dashed-name can't be used as a JavaScript object key:
grunt.initConfig({
json-schema: { // WON'T work
they have to be enclosed in quotes:
grunt.initConfig({
'json-schema': { // will work
I checked all official plugins (grunt-contrib-*), but they all consist of only one word. The motivation foor this question is simple: I just want to follow conventions.
Short answer: Plugin/custom task names do not have to correlate to a specific config object name.
The Grunt.js api allows access to the config object using the method grunt.config. Tasks & Plugins have access to the entire object, not just the sub object correlating to the name.
For example, I could create a task called foo that accesses the config from bar:
grunt.initConfig({
bar: {
baz: true
}
});
grunt.registerTask('foo', 'example custom task', function () {
var config = grunt.config('bar');
grunt.log.ok(config);
});
Best practice: Plugin developers should name the key for their config object similar to the plugin name itself. This helps mitigate conflicts with other plugins who could reference similar.
grunt.initConfig({
foo: {
baz: true
}
});
grunt.registerTask('foo', 'example custom task', function () {
var config = grunt.config('foo');
grunt.log.ok(config);
});
I think the general convention is to use camelCase for tasks that consist of multiple words.
Related
I was wondering if it's possible to get the jest runtime config object or filepath.
My use case would be to use various runtime config properties on my custom matchers
// ./jest.config.js
const path = require("path");
module.exports = {
prop1: "foo",
prop2: "bar"
};
// my-custom-matcher.js
expect.extend({
matcherName(received: any, pathToFile: string) {
const relativeDir = path.join(runtimeconfigpath, pathToFile); // i need the path to the runtimeconfigpath being used here
const baz = runtimeconfig.foo // or access the config properties like this
}
});
I tried various stuff and dug around the docs but i dont see this anywhere.
The nearest possible alternative I can think of would be to use config globals but that would complicate stuff if 'preset' and config extensions come into play.
Any help would be appreciated.
Have you tried to simply import jest.config.js? Or is there a specific reason not to import it? At least it is loaded by jest itself, so you should be fine by just importing it.
As js code is only compiled once and the reused of other files also need it
Otherwise you could look into 5 Advanced npm package.json configuration tips and see if it helps.
Or crate a recursive function that searches for the file. Maybe there is even some way to instantly get the path to package.json and then you can use this to continue from there (I did not find it after a short search)
I'm using the requirejs-babel plugin which requires prepending 'es6!' to all module ids that need babel transpilation.
define(['es6!some-es6-module'], function(module) {
// ...
});
Is there an API in RequireJS that would allow me to inspect a module id and prepend the plugin id as-needed? For example, if I wanted to apply 'es6!' to all module ids in a specific directory?
Ultimately I need to be able to write defines like this define(['some-es6-module'], ...) and automatically add the es6! prefix depending on what the module id is.
Not looking for information on SystemJS or gulp tasks that do the transpilation ahead of time, etc.
The exact module ids are not known at configuration time- I just know in certain locations/directories, modules will need es6!.
Needs to work in the browser, at runtime
I am not 100% sure on your overall objective (do you want the es6 addition to module ID saved permanently or always auto-added?), but you may be able to use RequireJS mapping to substitute module ID's for defined modules. For example: -
requirejs.config({
map: {
// * - for all modules that require these, do this
'*': {
'some-es6-module': 'es6!some-es6-module'
}
}
});
However, considering your use-case you may need something more complicated than this, as mapping assumes you have actual different versions of files and is generally used for this purpose.
A more complicated solution I assume you are looking to avoid could be to dynamically loop your files before optimising them in r.js and loading/editing them via Node. It would get a little messy!
var config = requirejs.s.contexts._.config;
var needBabel = ['some-es6-module', 'another-module-name', 'another'];
for (var property in config.paths) {
if (config.paths.hasOwnProperty(property) && needBabel.indexOf(property) > -1) {
// load the module in node
// fs.readFileSync(__dirname + config.paths[property] + '.js');
// dynamically modify this file with text replacement
// save this file via Node again
}
}
// run Require JS optimiser
// undo everything you've just done when optimisation is complete
I ended up overriding the load method. The override uses the standard load for modules with mapped paths, otherwise it uses the es6 (requirejs-babel) plugin to load the module.
require.standardLoad = require.load;
require.load = function(context, moduleName, url) {
var config = requirejs.s.contexts._.config;
if (moduleName in config.paths) {
return require.standardLoad(context, moduleName, url);
}
require(['es6'], function(es6) {
es6.load(
moduleName,
require,
{
fromText: function(text) {
require.exec(text);
context.completeLoad(moduleName);
}
},
{});
});
};
Here it is in action: https://gist.run/?id=7542e061bc940cde506b
I am using grunt-contrib-concat and I have a simple concat task / config like below
concat: {
options: {
sourceMap: true
},
vendor: {
src:['lib/**/*.js'],
dest: 'dist/scripts/vendor.js'
},
app: {
src:['app/**/*.js'],
dest: 'dist/scripts/app.js'
}
}
So when I am running above task through console I would like to be able to specify enable / disable sourceMap generation. Source map generation can take forever.
I tried below but none worked.
grunt concat:vendor --sourceMap=false
grunt concat --sourceMap=false
Thanks.
I know one way to do this, it requires you to write a custom task, it's easy.
// Leave your `concat` task as above
concat: ...
// and then define a custom task as below (out of `grunt.config.init` call)
grunt.registerTask('TASK_NAME', 'OPTIONAL_DESCRIPTION', function (arg) {
// CLI can pass an argument which will be passed in this function as `arg` parameter
// We use this parameter to alter the `sourceMap` option
if (arg) {
grunt.config.set('concat.options.sourceMap', false);
}
// Just run `concat` with modified options or pass in an array as tasks list
grunt.task.run('concat');
});
This is simple, you can customize this template as your wishes.
To use it, just use a ":" to pass extra parameter(s) in CLI like below:
$ grunt concat:noSrcMap
Basically you can pass anything as the parameter, it will be treated like a string (or undefined if no parameter passed).
I'm using r.js to build a production script for my Require JS application and I'm looking for a way to either use an alternate compression library or change the defaults used. I want whitespace to be removed but for variable names to remain the same.
I have a particular requirement to retain variable names as they are and not have them altered. The need for constant variable names introduces a little 'code smell' but it makes the application's configuration file more robust against non-expert editors - so please try to avoid suggesting a design change here.
I currently have r.js configured to not optimise the JavaScript at all, which means not only are variable names retained but also whitespace. The relevant piece from gruntfile.js is provided below.
Can anyone suggest a way to compress whitespace but not change variable names in an r.js build?
english: {
options: {
baseUrl: "js",
mainConfigFile: "js/app-en.js",
name: "app-en",
out: "js/dist/<%= pkg.name %>-en.js",
optimize: "none"
}
}
The r.js optimizer has settings you can use to control how the minifier operates. The default minifier used is UglifyJS. The uglifyjs option tells r.js how to invoke it. Given the settings you've shown, removing optimize: "none" and adding uglify: { no_mangle: true } is what is needed:
english: {
options: {
baseUrl: "js",
mainConfigFile: "js/app-en.js",
name: "app-en",
out: "js/dist/<%= pkg.name %>-en.js",
uglify: {
no_mangle: true
},
}
}
The whole set of settings that UglifyJS takes is documented here. If you ever need or want to switch to UglifyJS2 or Closure, r.js has uglify2 and closure settings that you can use to set their options.
For Uglify2, the setting to prevent mangling would be:
uglify2: {
mangle: false
}
With Closure, I believe you'd want:
closure: {
CompilationLevel: 'WHITESPACE_ONLY',
},
I notice in the documentation there is a way to pass custom configuration into a module:
requirejs.config({
baseUrl: './js',
paths: {
jquery: 'libs/jquery-1.9.1',
jqueryui: 'libs/jquery-ui-1.9.2'
},
config: {
'baz': {
color: 'blue'
}
}
});
Which you can then access from the module:
define(['module'], function (module) {
var color = module.config().color; // 'blue'
});
But is there also a way to access the top-level paths configuration, something like this?
define(['module', 'require'], function (module, require) {
console.log( module.paths() ); // no method paths()
console.log( require.paths() ); // no method paths()
});
FYI, this is not for a production site. I'm trying to wire together some odd debug/config code inside a QUnit test page. I want to enumerate which module names have a custom path defined. This question touched on the issue but only lets me query known modules, not enumerate them.
It is available, but it's an implementation detail that shouldn't be depended on in production code ( which you've already said it's not for, but fair warning to others! )
The config for the main context is available at require.s.contexts._.config. Other configurations will also hang off of that contexts property with whatever name you associated with it.
I don't believe require exposes that anywhere, at least I can't find it looking through the immense codebase. There are two ways you could achieve this though. The first and most obvious is to define the config as a global variable. The second, and closer to what you want, is to create a require plugin that overrides the load function to attach the config to the module:
define({
load: function (name, req, onload, config) {
req([name], function (value) {
value.requireConfig = config;
onload(value);
});
}
});