is it possible to configure grunt in a way that you have the required modules on a central point?
I have following project structure
-Project
-- subproject
-- subproject
-- subproject
I build the project via grunt with all subprojects, and I can build each subproject for itself too. Currently I have a Gruntfile.js, package.json & folder node_modules (~50mb) with all required modules in each subproject and on the root level.
So is it possible to have the node_modules folder only on one level, for e.g. on the root level and the subprojects refer to the node_modules on root level?
-Project
--subproject
--subproject
--subproject
--node_modules
Is there a way to reference the node_module folder via package.json or anything else?
Edit:
Gruntfile.js (subproject level)
/*global module:false */
/*jshint node:true */
module.exports = function(grunt) {
"use strict";
// ================================================================================
// project configuration
// ================================================================================
grunt.initConfig({
pkg : grunt.file.readJSON('package.json'),
jshint: {
globals : {
d3:true,
Modernizr:true,
tempo:true
},
options: grunt.file.readJSON('.jshintrc')
},
csslint: {
subproject: {
src: 'css/**/*.css'
}
},
htmllint : {
subproject: {
src: 'html/**/*.html'
}
},
clean : [ 'output' ],
less : {
options: {
paths: ['./']
},
src: {
expand: true,
cwd: 'css/',
src: ['**/*.less'],
dest: 'css/',
ext: '.css'
}
},
copy: {
subproject: {
files: [
{src: ['img/**', 'js/**', 'folderX/**','!**/*.less'], dest: 'output/subproject/'}
]
}
}
});
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-html');
grunt.loadNpmTasks('grunt-css');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-copy');
// ================================================================================
// default task
// ================================================================================
grunt.registerTask('default', ['clean', 'less', 'csslint', 'htmllint', 'copy']);
};
package.json (subproejct level)
{
"description": "subproject",
"title": "Lorem Ipsum",
"devDependencies": {
"grunt-contrib-watch": "~0.2.0",
"grunt-contrib-jshint": "~0.1.1",
"grunt-contrib-less": "~0.5.0",
"grunt-contrib-uglify": "~0.1.1",
"grunt-contrib-copy": "~0.4.0",
"grunt-contrib-qunit": "~0.1.1",
"grunt-css": "~0.5.4",
"grunt-contrib-clean": "~0.4.0",
"grunt-html": "~0.3.3",
"grunt-contrib-concat": "~0.1.3"
}
}
BR, mybecks
Yes you can copy whole node_modules (have done it multiple times) from one project to another and use same package.
You could remove your node_modules/ folder and then reinstall the dependencies from package. json. This would erase all installed packages in the current folder and only install the dependencies from package.
Anybody can suggest if I delete node_modules folder and after re-creating it, will I get all the already installed packages back in the same way they were just before deleting? YES, you will get back all the packages listed in your package. json file.
This works out of the box. npm
looks for node_modules
in the current directory, and all its parent directories, then looks in the global location.
So you could even do this:
-Project
--subproject1
---node_modules
--subproject2
--subproject3
--node_modules
subproject1
will have access to all npms inside Project/subproject1/node_modules
and Project/node_modules
, while subproject2
and subproject3
will only find those inside Project/node_modules
There is a very little documented feature called grunt collections. It requires a bit of a setup, but you won't need a copy of all your grunt plugins in each subproject.
Here's the file layout
-Project
--subproject1
---node_modules
----grunt-collection
-----package.json
--subproject2
...
--subproject3
...
--node_modules
---grunt
---grunt-contrib-concat
---grunt-contrib-jshint
---grunt-contrib-qunit
---grunt-contrib-watch
---grunt-html
---grunt-contrib-clean
---grunt-contrib-copy
---grunt-contrib-less
---grunt-contrib-uglify
---grunt-css
--package.json
Project/package.json
{
"description": "subproject",
"version": "0.0.0",
"name": "Lorem",
"title": "Lorem Ipsum",
"devDependencies": {
"grunt": "*",
"grunt-contrib-watch": "~0.2.0",
"grunt-contrib-jshint": "~0.1.1",
"grunt-contrib-less": "~0.5.0",
"grunt-contrib-uglify": "~0.1.1",
"grunt-contrib-copy": "~0.4.0",
"grunt-contrib-qunit": "~0.1.1",
"grunt-css": "~0.5.4",
"grunt-contrib-clean": "~0.4.0",
"grunt-html": "~0.3.3",
"grunt-contrib-concat": "~0.1.3"
}
}
Project/subproject1/package.json
{
"description": "subproject",
"version": "0.0.0",
"name": "Lorem",
"title": "Lorem Ipsum",
"devDependencies": {
}
}
Project/subproject1/Gruntfile.js excerpt (you only need the grunt-collection task).
grunt.loadNpmTasks('grunt-collection');
// grunt.loadNpmTasks('grunt-contrib-jshint');
// grunt.loadNpmTasks('grunt-html');
// grunt.loadNpmTasks('grunt-css');
// grunt.loadNpmTasks('grunt-contrib-less');
// grunt.loadNpmTasks('grunt-contrib-copy');
Project/subproject1/node_modules/grunt-collection/package.json
{
"description": "subproject",
"version": "0.0.0",
"name": "Lorem",
"title": "Lorem Ipsum",
"dependencies": {
"grunt-contrib-watch": "~0.2.0",
"grunt-contrib-jshint": "~0.1.1",
"grunt-contrib-less": "~0.5.0",
"grunt-contrib-uglify": "~0.1.1",
"grunt-contrib-copy": "~0.4.0",
"grunt-contrib-qunit": "~0.1.1",
"grunt-css": "~0.5.4",
"grunt-contrib-clean": "~0.4.0",
"grunt-html": "~0.3.3",
"grunt-contrib-concat": "~0.1.3"
},
"keywords": ["gruntcollection"]
}
The key is to create in each of your subproject, a small module with just a package.json which includes the keyword
gruntcollection
and includes the dependencies your Grunfile uses.
Grunt will then load these using the same strategy require
uses, which means they can be found in the node_modules
of your parent project.
Caveat: the way grunt collection works by using the dependency tag of package.json, this means you can not install it with npm install, but you should be able to store it source control.
I created a npm module load-grunt-parent-tasks to fix the issue. It was inspired by the answer that Pascal Belloncle gave and uses a gruntcollection
hack.
All you need to do is require the module, pass it grunt
and a config object and it will do the rest.
module.exports = function(grunt) {
require('load-grunt-parent-tasks')(grunt, {
config: 'package.json',
pattern: 'grunt-*',
scope: 'dependencies',
module: 'grunt-collection'
});
};
You can filter which grunt tasks you would like to load based on the globbing pattern you pass to pattern
.
You can check out the module on Npm: https://www.npmjs.org/package/load-grunt-parent-tasks
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With