Pablo
Pablo

Reputation: 485

Grunt: have package.json and Gruntfile.js on different folders

I'm having problems trying to implement grunt on different folders, in my root I have:

<root>/package.json
<root>/node_modules

And inside another folder, my gruntfile with different subfolders and files which I work:

<root>/apps/static/Gruntfile.js

If I go to root and execute

grunt --gruntfile /apps/static/Gruntfile.js MyTaskName

I get:

Local Npm module "grunt-contrib-concat" not found. Is it installed?

Local Npm module "grunt-contrib-cssmin" not found. Is it installed?

Local Npm module "grunt-contrib-clean" not found. Is it installed?

Local Npm module "grunt-contrib-watch" not found. Is it installed?

Local Npm module "grunt-contrib-uglify" not found. Is it installed?

And I run npm install several times.

On my gruntfile.js I have

grunt.loadNpmTasks('grunt-contrib-concat');

grunt.loadNpmTasks('grunt-contrib-cssmin');

grunt.loadNpmTasks('grunt-contrib-clean');

grunt.loadNpmTasks('grunt-contrib-watch');

grunt.loadNpmTasks('grunt-contrib-uglify');

I triple check and folders are ok (in fact, originally gruntfile and package where in the same folder and everything was working perfectly, run several task and everything is ok). I really need to have a common package.json and node_modules on root and the Gruntfile.js on a specific project folder

Any idea what's going on? Thanks in advance

Upvotes: 4

Views: 1565

Answers (2)

Vaibhav Nigam
Vaibhav Nigam

Reputation: 1487

Sometimes, it may be the need of project to have Gruntfile.js in a different folder than package.json.

I had a very similar use-case where there were multiple submodules each with its own build process, one of them was Grunt. But at the same time I wanted to have a common package.json just to avoid multiple node_modules folders being created, so that common dependencies (including transitive) use to install once. It helped in reducing install time as well as disk usage.

I was expecting a solution in Grunt itself. But as @cartant mentioned, Grunt has made certain assumptions.

So, here is what I did:

In Gruntfile.js,

Define a function:

function loadExternalNpmTasks(grunt, name) {
  const tasksdir = path.join(root, 'node_modules', name, 'tasks');
  if (grunt.file.exists(tasksdir)) {
    grunt.loadTasks(tasksdir);
  } else {
    grunt.log.error('Npm module "' + name + '" not found. Is it installed?');
  }
}

And instead of

grunt.loadNpmTasks('grunt-contrib-concat');

do:

loadExternalNpmTasks(grunt, 'grunt-contrib-concat');

Reference: https://github.com/gruntjs/grunt/blob/master/lib/grunt/task.js#L396

Upvotes: 0

cartant
cartant

Reputation: 58440

Grunt makes certain assumptions regarding the location of gruntfile.js.

When you specify the location of gruntfile.js using the --gruntfile option, Grunt sets the current directory to the directory containing the specified file:

// Change working directory so that all paths are relative to the
// Gruntfile's location (or the --base option, if specified).
process.chdir(grunt.option('base') || path.dirname(gruntfile));

And when Grunt loads NPM tasks, it does so relative to the current directory:

var root = path.resolve('node_modules');
var pkgfile = path.join(root, name, 'package.json');

There is a --base option with which the current directory can be specifed, but whether or not that will solve your problem (without introducing other problems) I do not know. The simplest solution is likely to locate gruntfile.js where it wants and expects to be located.

Upvotes: 2

Related Questions