I have 3 separate apps in 3 different folders. e.g. folder1, folder2 and folder3. folder3 is the combination of folder1 and folder2. Right now, I run dist task on both folder1 and folder2, then with bower link I link those dist folders with in folder3. Is there any way I could run a task with in folder3 that will create dist on folder1 and folder2, and link them with folder3? In short I want to run grunt task of folder1 and folder2 from folder3 and link them.
grunt.config.set('exec', {
loginapp: {
command: 'grunt -b C:/project/loginapp dist'
}
});
grunt.registerTask('all', [
'exec:loginapp'
]);
Folder structure
c:\project
----loginapp
dist
GruntFile.js
----webapp
public
bower_components
dist-loginapp
GruntFile.js
Hope this helps. I am in webapp > GruntFile where I run dist and that should run dist task on loginapp before its on dist task.
You can use -b flag to specify an alternate base path where there is a Gruntfile.
Then use grunt-exec to create task that run grunt task of your other projects.
E.g :
module.exports = function(grunt) {
grunt.config.set('exec', {
distFolder1: {
command: 'grunt -b relative/path/to/Gruntfile/of/folder1 taskName'
},
distFolder2: {
command: 'grunt -b relative/path/to/Gruntfile/of/folder2 taskName'
},
});
grunt.loadNpmTasks('grunt-exec');
};
Now you just have create a register task that run these two task and you other task.
E.g :
module.exports = function(grunt) {
grunt.registerTask('distAndLink', [
'exec:distfolder1',
'exec:distfolder2',
// your other task (bower link)
]);
};
and then run grunt distAndLink from folder 3.
Related
The source config example below processes files from src dir. There is src2 dir which also should be processed with the same tasks and putted to build2. What changes required in config.
module.exports = function (grunt) {
var saveLicense = require('uglify-save-license');
grunt.initConfig({
clean : {
build : {
src : ['build']
},
},
copy : {
files : {
cwd : 'src',
src : '**/*',
dest : 'build',
expand : true
}
},
...
Both grunt-contrib-copy and grunt-contrib-clean, like many other grunt plugins, allow multiple Targets to be specified in each Task.
For your scenario you can simply configure two Targets in the copy task (one Target to copy the src folder and another Target to copy the src2 folder).
You can also configure two Targets in the clean task (one Target to clean the build folder and another Target to clean the build2 folder).
Gruntfile.js
Your Gruntfile.js can be configured as ass follows:
module.exports = function(grunt) {
var saveLicense = require('uglify-save-license');
grunt.initConfig({
// The 'clean' task now includes two targets.
// named 'build1' and 'build2'
clean: {
build1: {
src: ['build']
},
build2: {
src: ['build2']
}
},
// The 'copy' task now includes two targets.
// named 'src1' and 'src2'
copy: {
src1: {
cwd: 'src',
src: '**/*',
dest: 'build',
expand: true
},
src2: {
cwd: 'src2',
src: '**/*',
dest: 'build2',
expand: true
}
}
// ...
});
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-clean');
// Registering the Targets in the Tasks....
grunt.registerTask('copySrc1', ['copy:src1']);
grunt.registerTask('cleanBuild1', ['clean:build1']);
grunt.registerTask('copySrc2', ['copy:src2']);
grunt.registerTask('cleanBuild2', ['clean:build2']);
grunt.registerTask('copyBoth', ['copy']);
grunt.registerTask('cleanBoth', ['clean']);
};
Running the Grunt Tasks
You'll notice that there are six calls to the .registerTask(...) function at the end of the snippet. Namely; copySrc1, cleanBuild1, copySrc2, cleanBuild2, copyBoth, and cleanBoth.
They allow you to run the following commands via your command line:
$ grunt copySrc1
(This will copy the src folder to the build folder)
$ grunt cleanBuild1
(This will clean the build folder)
$ grunt copySrc1
(This will copy the src2 folder to the build2 folder)
$ grunt cleanBuild2
(This will clean the build2 folder)
$ grunt copyBoth
(This will copy the src folder to the build folder and copy the src2 folder to the build2 folder)
$ grunt cleanBoth
(This will clean both the build and build2 folders)
Notes
You probably only need to keep the two .registerTask(...) functions as follows:
grunt.registerTask('copyBoth', ['copy']);
grunt.registerTask('cleanBoth', ['clean']);
However, I included the other four .registerTask(...) functions as they demonstrate how you can call a single Target inside a Task using the semicolon notation (:). For example:
grunt.registerTask('copySrc1', ['copy:src1']);
In the above snippet the ['copy:src1'] part simply runs only the Target named src1 inside the copy Task.
Whereas:
grunt.registerTask('copyBoth', ['copy']);
... does not reference any Targets in the copy task, (i.e. no semicolon notation is used), therefore all Targets will be run.
To further understand Tasks, Targets, you can read my answer to this post.
Hope that helps!
I have this gruntfile.js fragment
grunt.initConfig({
browserify: {
browser: {
src: [ require('./package.json').main ],
dest: './browser/shortid.js'
},
How would I perform exactly the same thing by calling browserify directly (without grunt) from bash command line? From what directory should I execute browserify?
The following command is equivalent and it would need to be executed in the same directory as your package.json:
browserify . > ./browser/shortid.js
using gurunt syncall, I want to dynamically sync every dir(and new dir created in the futrue) in project root except 'node_modules' dir to another dir.
using grunt watchall, I want to watch those dirs, when there are some changes in a dir, I want to automaticlly run the corresponding sync task.
here is my project root's structure:
├── Gruntfile.js
├── addon1
│ └── a.toc
├── adon3
│ └── 3.toc
├── node_modules
│ ├── grunt
│ ├── grunt-contrib-watch
│ └── grunt-sync
└── package.json
the grunt syncall command is ok, here is the result:
➜ testsync grunt syncall
Running "config" task
Running "sync:addon1" (sync) task
Running "sync:adon3" (sync) task
Done, without errors.
but the grunt watchall not ok. can you tell me why watchall tasks not work and how to fix it?
I start the command, and change and save the file '3.toc' in dir 'adon3', then grunt say:
➜ testsync grunt watchall
Running "config" task
Running "watch" task
Waiting...
>> File "adon3/3.toc" changed.
Running "sync:adon3" (sync) task
Verifying property sync.adon3 exists in config...ERROR
>> Unable to process task.
Warning: Required config property "sync.adon3" missing. Use --force to continue.
Aborted due to warnings.
here is my Gruntfile.js:
module.exports = function(grunt) {
grunt.initConfig({});
var destdir = "/Users/morrxy/project/testdest/";
// dynamic config sync and watch's targets for every dir except for node_modules
grunt.registerTask('config', 'config sync and watch', function() {
grunt.file.expand({filter: 'isDirectory'},
['*', '!node_modules']).forEach(function(dir) {
// config sync's targets
var sync = grunt.config.get('sync') || {};
sync[dir] = {
files: [{
cwd: dir,
src: '**',
dest: destdir + dir
}]
};
grunt.config.set('sync', sync);
// config watch's target
var watch = grunt.config.get('watch') || {};
watch[dir] = {
files: dir + '/**/*',
// is next line has problem?
// running 'grunt watchall'
// when I change and save the file '3.toc' in dir 'adon3', terminal say:
// >> File "adon3/3.toc" changed.
// Running "sync:adon3" (sync) task
// Verifying property sync.adon3 exists in config...ERROR
// >> Unable to process task.
// Warning: Required config property "sync.adon3" missing.
// but why 'grunt syncall' can work?
tasks: 'sync:' + dir
};
grunt.config.set('watch', watch);
});
});
grunt.loadNpmTasks('grunt-sync');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('syncall', ['config', 'sync']);
grunt.registerTask('watchall', ['config', 'watch']);
};
Finally, I solved this problem. I add a github repo for this question. If you want test, you can clone it run it locally. https://github.com/morrxy/dynasync
The reason watchall can watch files changes but can't run the corresponding sync task is that when watch find files changed, the config for each sync is finnished running, so the config for that sync target is gone, we didn't save the running config any where. So to solve this problem, we could add the config task into the watch task before the sync task, like this tasks: ['config_sync', 'sync:' + dir].
in new Gruntfile.js, I split the config task to two task, one for config watch, one for config sync, in the watch task, using the config sync task. Here is the new Gruntfile.js
module.exports = function(grunt) {
var destdir = "/media/data/projects/dynasync_dest/";
grunt.loadNpmTasks('grunt-sync');
grunt.loadNpmTasks('grunt-contrib-watch');
// dynamic config sync's targets for every dir except for node_modules
grunt.registerTask('config_sync', 'dynamically config sync', function() {
grunt.file.expand({filter: 'isDirectory'},
['*', '!node_modules']).forEach(function(dir) {
// config this dir's sync target
var sync = grunt.config.get('sync') || {};
sync[dir] = {
files: [{
cwd: dir,
src: '**/*',
dest: destdir + dir
}]
};
grunt.config.set('sync', sync);
});
});
// dynamic config watch's targets for every dir except for node_modules
grunt.registerTask('config_watch', 'dynamically config watch', function() {
grunt.file.expand({filter: 'isDirectory'},
['*', '!node_modules']).forEach(function(dir) {
// config this dir's watch target
var watch = grunt.config.get('watch') || {};
watch[dir] = {
files: dir + '/**/*',
// this line solve the problem
// when find file change, first dynamically config sync and then sync the dir
tasks: ['config_sync', 'sync:' + dir]
};
grunt.config.set('watch', watch);
});
});
grunt.registerTask('syncall', ['config_sync', 'sync']);
grunt.registerTask('watchall', ['config_watch', 'watch']);
grunt.registerTask('default', ['watchall']);
};
This time, when watch find file changes, it can run the corresponding sync task. like this
grunt watchall
Running "config_watch" task
Running "watch" task
Waiting...
>> File "adon3/3.toc" changed.
Running "config_sync" task
Running "sync:adon3" (sync) task
Done, without errors.
Completed in 0.888s at Thu Apr 10 2014 14:01:26 GMT+0800 (CST) - Waiting...
I need to move a file out of the way before one of my Grunt tasks run, and then put it back after the task has completed.
How do I do this with GruntJS?
Basically I want to run this command:
# move node-webkit out of the way
mv app/node-webkit ./tmp
# run grunt task
# move node-webkit back
mv ./tmp/node-webkit ./app/
Yeah, have a look at grunt-shell. In your init config:
shell: {
move: {
command: 'mv app/node-webkit ./tmp'
},
moveback: {
command: 'mv ./tmp/node-webkit ./app/'
}
}
Then, register a function that runs the move command before the other tasks you want to run, then run the moveback task.
module.exports = function(grunt) {
'use strict';
grunt.registerTask('mytask', [
'shell:move',
'othertaskshere',
'shell:moveback'
]);
};
Just installed latest Grunt on Ubuntu 12.04. Here is my gruntfile:
module.exports = function(grunt){
//project configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
slides : {
src : ['src/top.html', 'src/bottom.html'],
dest : ['build/index.html']
}
}
});
//enable plugins
grunt.loadNpmTasks('grunt-contrib');
grunt.registerTask('default', ['concat:slides']);
}
This creates the build/ directory fine, but gives me the output of:
Running "concat:slides" (concat) task Warning: Unable to write
"build/index.html" file (Error code: undefined). Use --force to
continue.
I tried running chmod 777 on the directory, as I thought it might have something to do with permissions, but that didn't seem to change anything.
How can I make it so Grunt will write to build/index.html?
Figured it out:
//Does not work
dest : ['build/index.html']
Works as a string, but not an array:
//Works
dest : 'build/index.html'
I changed tasks/concat.js to accept arrays for dest:
// Write the destination file.
// If f.dest is an array take the first element
var dest = ([].concat(f.dest))[0]
grunt.file.write(dest, src);
but later I decided to use the files form instead of src/dest:
files: { 'dest.js': ['a.js', 'b.js'] }