How could I specify output file name based on input file name? - gruntjs

How could I specify output file name based on input file name?
I'm specifically trying to use grunt task (grunt-closure-tools or grunt-closure-compiler) to compile (minify) multiple javascript files, let's say all satisfying '/source/**/*.js' and want to output them in format $(original_file_path_without_extension).min.js
In all samples I've seen, the output is specified as single file only but I need to minify each file separately and into the same folder where the original file comes from.

Finally, I figured out the configuration. The trick is in building the files object dynamically (as described here). My configuration for grunt-closure-tools looks like this:
closureCompiler: {
options: {
// .. YOUR OPTIONS (ommited)
},
minify: {
files: [
{
expand: true,
src: ['source/**/*.js', '!source/**/*.min.js'],
ext: '.min.js'
}
]
}
}

Closure-compiler is designed to simultaneously compile all of your javascript into a single file to minimize requests. There are really only two use cases where separate output files are supported:
Multiple modules
In order to preserve renaming references, you'll have to compile your files simultaneously. The way to do that and maintain separate files is with modules. See How do I split my javascript into modules using Google's Closure Compiler?
Non-related Files
If your files don't have inter-dependencies, then you would simply run your grunt task multiple times - one for each file.

Related

My LESS sourceMap file is missing the "file" when run through grunt

When I run lessc --source-map=styles.map assets/less/00_style.less dest/assets/prod.css in the command line, everything is working. The styles.map file ends in:
...AV2rEF;EAAiB,aAAA","file":"dest/assets/prod.css"}
However, when I run grunt less, the styles.map is missing the "file" part and just ends in:
...AV2rEF;EAAiB,aAAA"}
This stops the SourceMap from working. What could be going wrong? My less config is as follows:
less: {
dist: {
options: {
sourceMap: true,
sourceMapFilename: 'styles.map'
},
files: [{
src : 'assets/less/00_style.less',
dest: 'dest/assets/prod.css'
}]
}
}
Short answer:
Add the following additional option to your less Task in Gruntfile.js:
...
options: {
...
sourceMapURL: '../../styles.map'
},
...
Long answer:
When running the lessc command via the CLI, (as per your example), notice the the following comment is written to the resultant prod.css:
/*# sourceMappingURL=../../styles.map */
However, when running the grunt task, (using your current config), the following comment is written into the resultant prod.css:
/*# sourceMappingURL=styles.map */
Note the missing ../../ - therefore prod.css can't find styles.map
This is why your SourceMap isn't working and not so much to do with the "file:" missing in styles.map when run via grunt. The .css file ultimately points to the .map file - not vice versa.
Even after running the lessc command via the CLI then deleting the "file:" part from styles.map you will find that the SourceMap still works in the browser. Indicating that the "file:" part, whether included in the .map file or not, has no effect on preventing the SourceMap from working.
Besides, as noted in the most recent proposed SourceMap spec (v.3) the "file:" part is optional:
Line 3: An optional name of the generated code that this source map is associated with.
Explicitly defining the sourceMapURL in your grunt Task options will entail having to keep a flat folder structure inside the dest/assets/ directory if you intend on using multiple .less files. (I.e. You'll need to avoid saving any resultant .css files in subfolders)

How to specify relative paths in grunt for less plugin

I apologize for being a complete grunt newbie. I have node.js installed, i have grunt installed, and I am able to run "grunt less" on a gruntfile.js with a less target. It "runs", but it doesn't do anything.
My .less files live in a source respository: C:\Workspace\dev, in directories like:
C:\Workspace\dev\Webs\RP\Content\p1\less\p1.less
C:\Workspace\dev\Webs\RP\Content\p2\less\p2.less
My gruntfile.js file lives in C:\Tools\Grunt (at least as I am learning), so I need to run the "grunt less" command from C:\Tools\Grunt.
Some questions:
1. How can I run grunt from "anywhere" rather than where the gruntfile.js lives? I'm trying to integrate compiling less files as part of the build.
How do I specify the "home directory" for the .less files so I don't have to specify full paths to source and dest? In my case, home directory would be C:\Workspace\dev\Webs\RP\Content, and my less files: would be something like:
"rp1/less/rp1.css": "rp1/less/rp1.less" (there are several that need to be compiled).
Thanks in advance.
module.exports = function(grunt){
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
grunt.initConfig({
less: {
options: {
paths: ["/c/Workspace/dev/Webs/RP/Content"]
},
files: {
"rp1/less/rp1.css": "rp1/less/rp1.less",
"rp1/less/ie9.css": "rp1/less/ie9.less",
"rp2/less/rp2.css": "rp2/less/rp2.less",
"rp3/less/rp3.css": "rp3/less/rp3.less",
"rp4/less/rp4.css": "rp4/less/rp4.less",
"rp4/less/ie9.css": "rp4/less/ie9.less",
"rp5/less/rp5.css": "rp5/less/rp5.less",
"rp5/less/ie9.css": "rp5/less/ie9.less"
}
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.registerTask('default', ['less']);
};
You should read up on how to use the files object in Grunt. Basically, you want a wildcard pattern, rather than having to specify each file individually. I think something like this might work:
files: [
{
expand: true,
src: ['**/*.less'],
},
]
Haven't tested though. You might need a 'dest' property also (either empty or just './') if it's not smart enough to figure it out on its own.
Also consider using gulp instead of grunt if you're just starting your project, I find the way it separates out the 'src' and 'dest' config rather than combining them into a 'files' object much more natural. Also I've worked with less and sass and have found the latter to be vastly superior (mostly because of the mixin libraries available, but it's also a more capable language in its own right), and it's pretty easy to move across from one to the other.

How to detect root files in LESS using gulp compilation

Here is the thing. I have following structure of my LESS files:
/less/root.less
/less/includes1/*.less (a lot of less files)
/less/includes2/*.less (a lot of less files)
I am using gulp to compile my LESS files. Source:
gulp.task('less', function () {
var combined = combiner.obj([
gulp.src('./less/**/*.less'),
less(),
gulp.dest('./www/dist/screen.css')
]);
// any errors in the above streams will get caught by this listener, instead of being thrown:
combined.on('error', console.error.bind(console));
return combined;
});
The problem is in the specified path. I understand this path ./less/**/*.less like this: Recursively go through all folders and compile all files that ends .less. Problem is that compiler wants to compile each file one by one and doesnt know that all files are included to my source.less. It doesnt look for root files and doesnt know what files are included parts and what are root files.
How do I tell LESS parser which files are root and which files are to be imported. In SASS it is specified via underscore in file name like this: _includedPart.scss.
Well you can use https://github.com/robrich/gulp-ignore. See: How can I use a glob to ignore files that start with an underscore?
var condition = '_*.less'; //exclude condition
gulp.src('content/**/*.less')
.pipe(gulpIgnore.exclude(condition))
In many situations you all your Less code into a single CSS file. Your main file(s) contain #import directive which point all other required Less files.

GruntJS - Exclude files from the watch

how to exclude certain files from a directory from watched. for eg I have a stylesheets folder I am watching for *.css and create a *.min.css using cssmin. But it keeps going in a loop as the folder watched has a new/changed *.min.css(ending in css).
'stylesheet-css':
files: ['public/stylesheets/*.css']
tasks:['cssmin:stylesheet-css']
I tried couple of things..
'stylesheet-css':
files: [ '!(public/stylesheets/*.min.css)'] # any thing other than .min.css
tasks:['cssmin:stylesheet-css']
doesn't seem to work
You need to specify the files you want, then the files you don't want (both sets), so something like:
'stylesheet-css':
files: ['public/stylesheets/*.css', '!public/stylesheets/*.min.css']
tasks:['cssmin:stylesheet-css']
For reference, see Grunt globbing patterns.

Globbing file pattern

I am new to the Grunt Task Runer. I'm trying to do some file matching in one of my configurations. With this file matching, I need ignore all of my test files, except for one. The one test file that I need to keep is named 'basic.test.js' In an attempt to do this, I currently have the following configuration:
files: [
'src/**/*.js',
'!src/**/*.test.js',
'src/root/basic.test.js'
]
At this time, I am still getting ALL of my tests. This means that my tests in the other test files are still being seen. I'm trying to confirm if I'm doing my globbing pattern correctly. Does my globbing pattern look correct for my scenario?
Thank you!
If you only want one test then there is no need to match and then unmatch all the others. Just include the one test:
files: [
'src/root/basic.test.js'
]

Resources