#javascript #node.js #npm #gruntjs
#javascript #node.js #npm #gruntjs
Вопрос:
У меня возникли проблемы при попытке реализовать 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.
В моем 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 находились в одной папке, и все работало идеально, запустите несколько задач, и все в порядке). Мне действительно нужно иметь общий package.json и node_modules для root и Gruntfile.js в определенной папке проекта
Есть идеи, что происходит? заранее спасибо
Ответ №1:
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
там, где оно хочет и ожидает, что оно будет расположено.
Комментарии:
1. Я читал о —base, но у меня все еще есть проблемы, я в корневой папке и получаю: не удалось найти действительный файл Gruntfile. Пожалуйста, ознакомьтесь с руководством по началу работы для получения дополнительной информации о том, как настроить grunt: gruntjs.com/getting-started Неустранимая ошибка: не удается найти Gruntfile. И gruntfile есть. Моя проблема в том, что это большой проект, и наличие всего в одном файле может быть сложным. Я работаю с этим на 8 веб-сайтах, и у каждого должен быть свой конкретный grunt, чтобы упростить его
2. Я думаю, что, пытаясь найти
gruntfile.js
место, где оно на самом деле не хочет находиться, вы попадаете в мир боли. Это похоже на проблему XY . Если ваша проблема сложная, у Grunt есть некоторые другие механизмы, которые могут предложить менее болезненные решения (напримерgrunt.config.merge
). Я бы предложил задать еще один вопрос, в котором спрашивается, как можно решить вашу проблему сложности. Я думаю, что на вопрос «почему это не работает» был дан ответ.
Ответ №2:
Иногда может потребоваться, чтобы проект 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