Can GruntJS remove the bower_components folder after copying files? - javascript

I am using Bower and GruntJS. I thought that grunt-bowercopy would remove the bower_components folder when it is done but this is not happening.
Can grunt-bowercopy remove the bower_components folder after copying the files to the locations I want?
Here is my folder setup:
->Project
->Themes
->Theme
->assets
->scripts
->styles
->tools
->build
->bower_components
->bower.json
->gruntfile.js
->package.json
Here is how I am running grunt-bowercopy in my gruntfile.js
module.exports = function (grunt) {
// Loads the necessary tasks for this Grunt file.
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
bowercopy: {
options: {
clear: true
},
js: {
options: {
destPrefix: '../../Themes/Theme/assets/'
},
//The key is the destination file. The value is the file from the bower_components folder
//The files will be added to a scripts folder at the location: ../../themes/3MTheme/assets/scripts
//The key is the name of the folder that is copied into the /assets folder.
src : 'scripts'
},
css: {
options: {
destPrefix: '../../Themes/Theme/assets/'
},
src: 'styles'
}
}
// Custom task, executed via the command "grunt bowercopy"
grunt.registerTask('bower', ['bowercopy']);
};

It doesn't seem as if grunt-bowercopy does this for you, but I've done something similar for clearing reports before running test commands.
Just create your own custom task called something like cleanbowercopy which executes an rmdir on the directory you are cleaning.
Then update your register task to call it after bowercopy:
grunt.registerTask('bower',['bowercopy','cleanbowercopy']);
That way it will accomplish what you are seeking within the same command, and can even be reused if you'd rather clean the dir at a different point in time.

I found the asnswer. I was using clear: true in the options when it should be clean: true
This works in my gruntfile.js
module.exports = function (grunt) {
// Loads the necessary tasks for this Grunt file.
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
bowercopy: {
options: {
clean: true
},
js: {
options: {
destPrefix: '../../Themes/Theme/assets/'
},
//The key is the destination file. The value is the file from the bower_components folder
//The files will be added to a scripts folder at the location: ../../themes/3MTheme/assets/scripts
//The key is the name of the folder that is copied into the /assets folder.
src : 'scripts'
},
css: {
options: {
destPrefix: '../../Themes/Theme/assets/'
},
src: 'styles'
}
}
// Custom task, executed via the command "grunt bowercopy"
grunt.registerTask('bower', ['bowercopy']);
};

Related

Use Grunt newer with custom task

I'm trying to use grunt-newer to watch files from a folder and if any is changed, trigger a custom task.
I have something like this in my Gruntfile.js:
grunt.initConfig({
watch: {
widgets: {
files: "/somepath/*.js",
tasks: ['newer:mycustomtask']
}
}
});
grunt.registerTask("mycustomtask", ["description of my task"], function() {
console.log("me has been triggered");
});
Whenever I run "grunt watch", I have this output:
Running "watch" task
Waiting...
File "/somepath/WidgetA.js" changed.
Running "newer:mycustomtask" (newer) task
Fatal error: The "newer" prefix is not supported for aliases
I googled but didn't found anything about this. Anyone knows how could I implement this? I need to now in my "customtask" which files have been changed
If you reference a task (inside watch or concurrent e.g.) which is either not installed or not configured you get this error output.
This happens often when you copy-paste a watch config from a different project.
I came across a similar requirement and the solution I ended up with is roughly as follows. Let's assume that the project structure is:
Gruntfile.js
package.json
src/
config.js
data.js
tasks/
customtask.js
Here, the src directory contains data which will be monitored by watch, while the definition of the custom task is stored in tasks/customtask.js. For the purpose of this example, this task will only print the file names of the changed files:
var fs = require('fs');
var path = require('path');
module.exports = function(grunt) {
grunt.registerMultiTask('customtask', function() {
var done = this.async();
if(!this.files){ done(); return; }
this.files[0].src.forEach(file_name => {
console.log(file_name);
});
done();
});
};
Now, Gruntfile.js looks like:
module.exports = function(grunt) {
const files = ['src/config.js', 'src/data.js'];
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
customtask: {
release: {
src: files
}
},
watch: {
data: {
files: files,
tasks: ['customtask:release']
},
options: {
spawn: false
}
}
});
grunt.loadTasks('tasks');
grunt.loadNpmTasks('grunt-contrib-watch');
var changedFiles = Object.create(null);
var onChange = grunt.util._.debounce(function() {
grunt.config('customtask.release.src', Object.keys(changedFiles));
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
changedFiles[filepath] = action;
onChange();
});
grunt.registerTask('build', ['watch:data']);
};
here, it specifies that:
the files of interest are ['src/config.js', 'src/data.js']
that our customtask operates in principle on these files (in case it would be invoked directly)
that watch is supposed to observe these files and launch customtask:release whenever something changes
grunt.loadTasks('tasks') loads all "tasks definitions" from the directory tasks, i.e., here only the customtask
grunt.registerTask('build', ['watch:data']) defines a "shortcut" for watch:data
Finally, in order to invoke customtask only for the changed files, this example uses the strategy employed in the documentation in the section "Compiling files as needed". In loose terms, it assembles all changed files in an object the keys of which are then used to modify the src property of the customtask on-the-fly.
Running grunt build then initiates the "watch". If one runs in another terminal window for example touch src/*.js, the output is:
Running "watch:data" (watch) task
Waiting...
>> File "src/config.js" changed.
>> File "src/data.js" changed.
Running "customtask:release" (customtask) task
src/config.js
src/data.js
where the last two lines come from customtask...
You just need to have a config entry (even an empty one) for your task:
grunt.initConfig({
mycustomtask: {
},
watch: {
widgets: {
files: "/somepath/*.js",
tasks: ['newer:mycustomtask']
}
}
});

How to I create a top-level grunt file and import it in another grunt file located in subfolders?

I want to create a common top-level Gruntfile.js configured to watch over less file change. When the less file changes, I want to compile it to css and then livereload the css file in browser. I have the functionality working but I have to duplicate most of code in Gruntfile.js for every project. So I was thinking if there is some way I can create a common Gruntfile.js and include/import it in different projects.
module.exports = function (grunt) {
'use strict';
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
less: {
options: {
compress: true
},
compile: {
extend: true,
src: 'less/**/project.less',
dest: 'css/project.css',
ext: '.css'
}
},
watch : {
less : {
files : ['less/**/*.less'],
tasks : ['less']
},
css : {
files : ['css/*.css'],
options : {
livereload: true,
spawn : false
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-less');
};
I solved the problem using grunt plugin - 'gruntfile'. It lets you import top-level Gruntfile.js to be included in other Gruntfiles.
I set parameters dynamically of parent Gruntfile from within other gruntfiles.
You can find more about the plugin and usage examples on : https://github.com/shama/gruntfile

grunt watch executes tasks multiple times

I've the following Grunfile.js File:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
dist: {
options: {
style: 'compressed'
},
files: {
'css/build/style.css': 'css/style.scss'
}
}
},
watch: {
stylesheets: {
files: ['css/*.scss'],
tasks: ['newer:sass']
}
}
});
// Load the plugin that compiles sass
grunt.loadNpmTasks('grunt-contrib-sass');
// watch for, and run grunt if files change
grunt.loadNpmTasks('grunt-contrib-watch');
// Plugin for Grunt tasks to run with newer files only.
grunt.loadNpmTasks('grunt-newer');
// Grunt Tasks:
grunt.registerTask('default', ['newer:sass']);
};
After running grunt watch and saving my scss File, the console output is the following:
Running "watch" task
Waiting...
>> File "css\style.scss" changed.
Running "newer:sass" (newer) task
Running "newer:sass:dist" (newer) task
Running "sass:dist" (sass) task
File css/build/style.css created.
Running "newer-postrun:sass:dist:1:D:\xampp\htdocs\grunt-test\node_modules\grunt-newer\.cache" (newer-postrun) task
Done, without errors.
The problem is, the .scss file is compiled every time. Even if there was no change.
I don't understand why grunt is running 3 tasks (newer:sass, newer:sass:dist, sass:dist), instead of only running the task defined under watch (newer:sass).
Hope someone has an idea to fix this. :)
I'm not positive this is the problem, but try specifying that you don't want to run all of sass, just sass:dist. So try: grunt.registerTask('default', ['newer:sass:dist']);

bootstrap less grunt not working

I can't seem to get my gruntfile to compile my less files from bootstrap, here is my gruntfile:
module.exports = function(grunt) {
// Configuration goes here
grunt.initConfig({
less: {
options: {
paths: ["public/bower_components/bootstrap/less"]
},
files: {
"public/css/bootstrap.css" : "public/bower_components/bootstrap/less/bootstrap.less"
}
}
});
// Load plugins here
grunt.loadNpmTasks("grunt-contrib");
grunt.loadNpmTasks("grunt-contrib-less");
// Define your tasks here
};
When I run grunt less I get
Running "less:files" (less) task
Done, without errors.
Bootstrap has it's own grunt file that comes with its bower install, I don't suppose it would cause some sort of conflict? I have triple checked my paths and they are fine.
EDIT: my folder structure:
Thanks
My grunt less config has blocks for the development and production targets. Does this work?
module.exports = function(grunt) {
// Configuration goes here
grunt.initConfig({
less: {
development: {
options: {
paths: ["public/bower_components/bootstrap/less"]
},
files: {
"public/css/bootstrap.css" : "public/bower_components/bootstrap/less/bootstrap.less"
}
}
}
});
// Load plugins here
grunt.loadNpmTasks("grunt-contrib");
grunt.loadNpmTasks("grunt-contrib-less");
// Define your tasks here
};

How to concatenate and minify multiple CSS and JavaScript files with Grunt.js (0.3.x)

Note: This question is only relevant for Grunt 0.3.x and has been left for reference. For help with the latest Grunt 1.x release please see my comment below this question.
I'm currently trying to use Grunt.js to setup an automatic build process for first concatenating and then minifying CSS and JavaScript files.
I have been able to successfully concatenate and minify my JavaScript files, although each time I run grunt it seems to just append to the file instead of overwriting them.
As for the minifying or even concatenating CSS, I have been unable to do this as of yet!
In terms of grunt CSS modules I have tried using consolidate-css, grunt-css & cssmin but to no avail. Could not get my head around how to use them!
My directory structure is as follows (being a typical node.js application):
app.js
grunt.js
/public/index.html
/public/css/[various css files]
/public/js/[various javascript files]
Here is what my grunt.js file currently looks like in the root folder of my application:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: '<json:package.json>',
concat: {
dist: {
src: 'public/js/*.js',
dest: 'public/js/concat.js'
}
},
min: {
dist: {
src: 'public/js/concat.js',
dest: 'public/js/concat.min.js'
}
},
jshint: {
options: {
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
boss: true,
eqnull: true,
node: true
},
globals: {
exports: true,
module: false
}
},
uglify: {}
});
// Default task.
grunt.registerTask('default', 'concat min');
};
So just to summarise I need help with two questions:
How to concatenate and minify all my css files under the folder /public/css/ into one file, say main.min.css
Why does grunt.js keep on appending to the concatenated and minified javascript files concat.js and concat.min.js under /public/js/ instead of overwriting them each time the command grunt is run?
Updated 5th of July 2016 - Upgrading from Grunt 0.3.x to Grunt 0.4.x or 1.x
Grunt.js has moved to a new structure in Grunt 0.4.x (the file is now called Gruntfile.js). Please see my open source project Grunt.js Skeleton for help with setting up a build process for Grunt 1.x.
Moving from Grunt 0.4.x to Grunt 1.x should not introduce many major changes.
concat.js is being included in the concat task's source files public/js/*.js. You could have a task that removes concat.js (if the file exists) before concatenating again, pass an array to explicitly define which files you want to concatenate and their order, or change the structure of your project.
If doing the latter, you could put all your sources under ./src and your built files under ./dest
src
├── css
│   ├── 1.css
│   ├── 2.css
│   └── 3.css
└── js
├── 1.js
├── 2.js
└── 3.js
Then set up your concat task
concat: {
js: {
src: 'src/js/*.js',
dest: 'dest/js/concat.js'
},
css: {
src: 'src/css/*.css',
dest: 'dest/css/concat.css'
}
},
Your min task
min: {
js: {
src: 'dest/js/concat.js',
dest: 'dest/js/concat.min.js'
}
},
The build-in min task uses UglifyJS, so you need a replacement. I found grunt-css to be pretty good. After installing it, load it into your grunt file
grunt.loadNpmTasks('grunt-css');
And then set it up
cssmin: {
css:{
src: 'dest/css/concat.css',
dest: 'dest/css/concat.min.css'
}
}
Notice that the usage is similar to the built-in min.
Change your default task to
grunt.registerTask('default', 'concat min cssmin');
Now, running grunt will produce the results you want.
dest
├── css
│   ├── concat.css
│   └── concat.min.css
└── js
├── concat.js
└── concat.min.js
I want to mention here a very, VERY, interesting technique that is being used in huge projects like jQuery and Modernizr for concatenate things.
Both of this projects are entirely developed with requirejs modules (you can see that in their github repos) and then they use the requirejs optimizer as a very smart concatenator. The interesting thing is that, as you can see, nor jQuery neither Modernizr needs on requirejs to work, and this happen because they erase the requirejs syntatic ritual in order to get rid of requirejs in their code. So they end up with a standalone library that was developed with requirejs modules! Thanks to this they are able to perform cutsom builds of their libraries, among other advantages.
For all those interested in concatenation with the requirejs optimizer, check out this post
Also there is a small tool that abstracts all the boilerplate of the process: AlbanilJS
I agree with above answer. But here is another way of CSS compression.
You can concat your CSS by using YUI compressor:
module.exports = function(grunt) {
var exec = require('child_process').exec;
grunt.registerTask('cssmin', function() {
var cmd = 'java -jar -Xss2048k '
+ __dirname + '/../yuicompressor-2.4.7.jar --type css '
+ grunt.template.process('/css/style.css') + ' -o '
+ grunt.template.process('/css/style.min.css')
exec(cmd, function(err, stdout, stderr) {
if(err) throw err;
});
});
};
You don't need to add the concat package, you can do this via cssmin like this:
cssmin : {
options: {
keepSpecialComments: 0
},
minify : {
expand : true,
cwd : '/library/css',
src : ['*.css', '!*.min.css'],
dest : '/library/css',
ext : '.min.css'
},
combine : {
files: {
'/library/css/app.combined.min.css': ['/library/css/main.min.css', '/library/css/font-awesome.min.css']
}
}
}
And for js, use uglify like this:
uglify: {
my_target: {
files: {
'/library/js/app.combined.min.js' : ['/app.js', '/controllers/*.js']
}
}
}
I think may be more automatic, grunt task usemin take care to do all this jobs for you, only need some configuration:
https://stackoverflow.com/a/33481683/1897196

Categories

Resources