我在尝试在不同文件夹上实现 grunt 时遇到问题,在我的根目录中:
<root>/package.json
<root>/node_modules
在另一个文件夹中,我的 gruntfile 包含我工作的不同子文件夹和文件:
<root>/apps/static/Gruntfile.js
如果我进入 root 并执行
grunt --gruntfile /apps/static/Gruntfile.js MyTaskName
我得到:
未找到本地 Npm 模块“grunt-contrib-concat”。安装了吗
未找到本地 Npm 模块“grunt-contrib-cssmin”。安装了吗
未找到本地 Npm 模块“grunt-contrib-clean”。安装了吗
未找到本地 Npm 模块“grunt-contrib-watch”。安装了吗
未找到本地 Npm 模块“grunt-contrib-uglify”。安装了吗
我跑了几次
npm install
。
在我的 gruntfile.js 上我有
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');
我三次检查,文件夹都正常(事实上,最初的 gruntfile 和包位于同一个文件夹中,一切都工作正常,运行几个任务,一切都正常)。我真的需要在根目录上有一个通用的 package.json 和 node_modules 以及在特定项目文件夹上的 Gruntfile.js
知道发生了什么事吗?预先感谢
Grunt 对
gruntfile.js
的位置做出了某些假设。
当您使用
gruntfile.js
选项指定 --gruntfile
的位置时,Grunt 将当前目录 设置为包含指定文件的目录:
// 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));
当 Grunt 加载 NPM 任务时,它会这样做相对于当前目录:
var root = path.resolve('node_modules');
var pkgfile = path.join(root, name, 'package.json');
--base
选项可以指定当前目录,但我不知道这是否会解决你的问题(不会引入其他问题)。最简单的解决方案可能是将 gruntfile.js
定位到它想要和期望的位置。
有时,项目可能需要将
Gruntfile.js
放在与 package.json
不同的文件夹中。
我有一个非常相似的用例,其中有多个子模块,每个子模块都有自己的构建过程,其中之一是 Grunt。但同时我希望有一个通用的
package.json
只是为了避免创建多个 node_modules
文件夹,以便通用依赖项(包括传递性)使用一次安装。它有助于减少安装时间以及磁盘使用量。
我期待 Grunt 本身有一个解决方案。但正如 @cartant 提到的,Grunt 做出了某些假设。
所以,这就是我所做的:
在
Gruntfile.js
,
定义一个函数:
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?');
}
}
而不是
grunt.loadNpmTasks('grunt-contrib-concat');
做:
loadExternalNpmTasks(grunt, 'grunt-contrib-concat');
参考:https://github.com/gruntjs/grunt/blob/master/lib/grunt/task.js#L396