问题
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
回答1:
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
Update
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.
回答2:
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
回答3:
Another solution, found in https://github.com/gruntjs/grunt/issues/696
module.exports = function (grunt) {
grunt.file.expand('../node_modules/grunt-*/tasks').forEach(grunt.loadTasks);
}
回答4:
Following is a simple workaround.
Change Gruntfile.js.
module.exports = function (grunt) {
var cwd = process.cwd();
process.chdir(cwd+'/../');
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
process.chdir(cwd);
}
来源:https://stackoverflow.com/questions/15225865/centralise-node-modules-in-project-with-subproject