Grunt: просмотр нескольких файлов, только компиляция Изменено
Я новичок в Grunt, и до сих пор мне это очень нравится.
Я хочу, чтобы Grunt собирал только измененные файлы при запуске grunt watch
В моей Grunfile.coffee у меня есть (соответствующие части).
Примечание: активы /javascript/app.coffee и assets/javascript/app.js являются каталогами
coffee:
default:
expand: true
cwd: "assets/javascript/app.coffee"
src: ["*.coffee"]
dest: "assets/javascript/app.js"
ext: ".js"
uglify:
dev:
options:
beautify: true
compress: false
mangle: false
preserveComments: 'all'
files:
"js/app.js": "assets/javascript/app.js/*.js"
"js/libs.js": "assets/javascript/libs/*.js"
watch:
coffeescript:
files: 'assets/javascript/**/*.coffee'
tasks: ["coffee"]
javascript:
files: "assets/**/*.js"
tasks: ["uglify:dev"]
livereload:
files: ["Gruntfile.coffee", "js/*.js", "*.php", "css/*.css", "images/**/*.{png,jpg,jpeg,gif,webp,svg}", "js/*.js", ]
options:
livereload: true
Вероятно, есть более короткий путь, но я сначала компилирую app.coffee в app.js, так что после того, как я буду распространять свою работу, люди, которые не устраивают Coffeescript, могут несколько раз просматривать код.
Проблема со всем этим заключается в том, что теперь, когда я сохраняю файл Coffeescript, я получаю слишком много шагов (я думаю):
>> File "assets/javascript/app.coffee/browse.coffee" changed.
Running "coffee:default" (coffee) task
File assets/javascript/app.js/browse.js created.
File assets/javascript/app.js/filters.js created.
Done, without errors.
Completed in 0.837s at Tue May 28 2013 12:30:18 GMT+0300 (EEST) - Waiting...
OK
>> File "assets/javascript/app.js/browse.js" changed.
>> File "assets/javascript/app.js/filters.js" changed.
Running "uglify:dev" (uglify) task
File "js/app.js" created.
File "js/libs.js" created.
Done, without errors.
Completed in 0.831s at Tue May 28 2013 12:30:19 GMT+0300 (EEST) - Waiting...
OK
>> File "js/app.js" changed.
>> File "js/libs.js" changed.
Completed in 0.000s at Tue May 28 2013 12:30:19 GMT+0300 (EEST) - Waiting...
В настоящее время я просто настраиваю свой проект, но у меня будет намного больше файлов Coffeescript, и я не хочу, чтобы Coffeescript перекомпилировал все файлы при каждом изменении файла.
Кроме того, libs.js вообще не участвует во всем этом, но я думаю, что он все еще скомпилирован, так как он также соответствует шаблону "assets/*/. js".
Есть ли способ заставить Grunt скомпилировать только файлы, которые изменились?
Ответы
Ответ 1
Наконец-то я нашел реальное решение! И это тоже очень просто!
npm install grunt-newer --save-dev
Затем в вашем файле Grunt (после загрузки задачи в grunt):
watch:
coffeescript:
files: 'assets/javascript/**/*.coffee'
tasks: ["newer:coffee"]
И это! Awesome grunt-newer - это потрясающе!
Ответ 2
Если вы объединяете все источники. coffee в один .js файл, вам придется перекомпилировать его каждый раз, если какой-либо из ваших источников изменится. Разделите его на несколько .js файлов и создайте задачу выпуска, в которой вы только присоединяете эти .js файлы. Таким образом, вам остается только добавить один .js файл.
См. Использование gruntjs, как следить за изменениями в файлах. coffee?
Ответ 3
Событие grunt.event.on
обнаруживает изменения в файлах, получая параметры action
и filepath
.
Здесь показан непроверенный пример, основанный на одном из моих файлов grunt. В этом случае все файлы исходного файла coffeescript хранятся в каталоге с именами источников, а для предварительного просмотра они компилируются и сохраняются в идентичную структуру каталогов в каталоге с именем dev
SOURCES_DIR = 'sources'
DEV_DIR = 'dev'
grunt.initConfig
watch :
all :
files : ["**/*.coffee"]
coffee :
dev :
files :
dest : "app.js"
grunt.loadNpmTasks 'grunt-contrib-watch'
grunt.loadNpmTasks 'grunt-contrib-coffee'
grunt.registerTask 'build', ['coffee:dev']
grunt.event.on('watch', (action,filepath) ->
# Determine the full directory of the changed file
wdi = filepath.lastIndexOf '/'
wd = filepath.substring 0,wdi
# remove `sources` prefix from that directory
fpath = wd.replace(SOURCES_DIR,'') + '/'
# determine the filename
fnamei = filepath.lastIndexOf '.'
fname = filepath.substring wdi+1,fnamei # NOTE: this breaks the case where in same dir
# concatenate fpath and fname with the dir to be compiled into
deststr = "#{DEV_DIR}#{fpath}#{fname}.coffee"
# set coffee.dev.files value in the coffee task to have am entry of form {"destination":"source"}
obj = {}
obj[deststr] = filepath
grunt.config "coffee.dev.files", obj
# fire the coffee task
grunt.task.run "coffee"
)
Надеюсь, что это поможет.
РЕДАКТИРОВАТЬ: Вероятно, не совсем то, что вы хотите, потому что, без сомнения, вы хотите получить доступ к промежуточным переменным, действиям и т.д. - но вы могли бы использовать grunt для запуска команды оболочки кофе. Задача grunt-shell
npm делает это, например
EDIT2: Я столкнулся с постоянными проблемами с grunt.watch.on
, не работающими последовательно с хреном 0.4.1 на OSX 10.8 и MacVim 7.3; по какой-то причине он перестает смотреть. Я вернусь обратно к простому базовому объекту grunt initConfig, но с гораздо большей детализацией, поэтому он только наблюдает и компилирует относительно небольшие группы файлов, а не всю партию. Это значительно замедляет время сборки, но оно намного более надежное. Ваш пробег может очень.
Ответ 4
Я тоже наткнулся на это и не нашел рабочих версий, которые работали с текущей версией (0.4.1). Но ответ Jof Arnolds показал хороший подход.
Вот что я придумал:
# only recompile changed files
grunt.event.on "watch", (action, filepath) ->
# note that we have to manually change the target file name to
# our desired format
targetName = filepath.replace(/\/(client|shared)/, "")
.replace(".coffee", ".js")
.replace("app/", "")
options =
src: filepath
dest: "public/javascripts/#{targetName}"
grunt.config ["coffee", "client"], options
У меня есть секция кофе, которая выглядит примерно так:
coffee:
client:
options:
sourceMap: false
files: [
expand: true
cwd: "app"
src: ["*/client/**/*.coffee", "helpers/{client,shared}/*.coffee"]
dest: "public/javascripts"
rename: (folder, name) ->
name = name.replace(/\/(client|shared)/, "")
[folder, name].join path.sep
ext: ".js"
]