Проблема
В настоящее время я работаю над проектом, в котором у нас есть родительское веб-приложение (оказывается, приложение AngularJS) и несколько дочерних модулей Bower (содержащих Javascript, SASS, изображения и т. д.), которые включены в родитель с помощью Bower.
Например, родительский файл bower.json выглядит так:
{
"name": "parent-app",
"version": "1.0.0",
"dependencies": {
"child-1-module": "1.0.0",
"child-2-module": "1.0.0"
}
}
При выполнении «bower install» на родительском объекте дочерние модули будут установлены в:
bower_components/child-1-module
bower_components/child-2-module
Затем мы используем 'bower link' для каждого из дочерних модулей.
Затем «bower link child-1-module» и «bower link child-2-module» на родительском элементе для создания локальных программных ссылок, таких как:
bower_components/child-1-module -> /some/where/else/child-1-module
bower_components/child-2-module -> /some/where/else/child-2-module
Это позволяет нам локально вносить изменения в отдельные дочерние модули и видеть результаты в родительском приложении.
Затем мы также используем Grunt с grunt-contrib-watch в родительском приложении, чтобы отслеживать изменения в родительском приложении, а затем выполнять другие задачи Grunt или выполнять «живую перезагрузку» для обновления браузера, используемого для просмотра приложения.
Урезанный пример Gruntfile.js, который просматривает файлы .js, а затем выполняет задачу «jshint» и «livereload», приведен ниже:
grunt.initConfig({
// Watches files for changes and runs tasks based on the changed files
watch: {
js: {
files: [
'scripts/{,*/}*.js',
],
tasks: ['newer:jshint:all'],
options: {
livereload: true
}
}
}
}
Это хорошо работает для наблюдения за изменениями в родительском приложении, но мы также хотели бы знать, когда изменяются файлы в дочерних модулях. В настоящее время есть ряд решений, о которых я подумал/исследовал со смешанными результатами.
Потенциальное решение 1. Добавьте Bower_components для просмотра grunt в родительском
Поэтому я мог бы просто изменить файл Grunt, чтобы дополнительно просматривать файлы .js в папке Bower_components, например:
grunt.initConfig({
// Watches files for changes and runs tasks based on the changed files
watch: {
js: {
files: [
'scripts/**/*.js',
'bower_components/**/*.js'
],
tasks: ['newer:jshint:all'],
options: {
livereload: true
}
}
}
}
Однако может быть много дочерних модулей (содержащих много файлов .js), поэтому производительность резко снижается и часто даже не запускается из-за проблемы "EMFILE: слишком много открытых файлов" (см. здесь).
Кроме того, дочерние модули добавляются динамически, поэтому мы не можем заранее указать в Gruntfile только конкретные, например:
'bower_components/child-1-module/**/*.js'
Потенциальное решение 2. Добавьте часы grunt в дочерние и родительские модули.
Вместо этого мы могли бы добавить Gruntfile.js в каждый дочерний модуль, содержащий часы для просмотра собственных файлов.
Когда файл изменяется в дочернем модуле, мы можем обновить определенный файл «livereload», а затем в родительском модуле мы можем отслеживать только эти конкретные файлы.
Пример «Gruntfile.js» в дочернем модуле-1
grunt.initConfig({
watch: {
js: {
files: ['scripts/**/*.js'],
tasks: ['livereloadEvent:js', 'newer:jshint:all']
}
}
}
grunt.registerTask('livereloadEvent', function() {
// create a 'livereload/livereload.{arg}' file for the event specified
grunt.file.mkdir('livereload');
for(var i = 0; i < this.args.length; i++) {
// contents of the file is the current timestamp
grunt.file.write('livereload/livereload.'+ this.args[i], new Date());
}
});
Затем в родительском элементе мы можем добавить к нашим часам следующую папку:
'bower_components/**/livereload/livereload.js'
Это работает нормально. Родителю теперь не нужно просматривать слишком много файлов, теперь дочерний процесс может осуществлять собственное наблюдение и в основном уведомлять родителя.
Недостаток в том, что каждый ребенок должен осознавать это и реализовывать это одинаково.
Другие возможные решения...
Как еще другие справились с этим? Существует ли общепринятый и широко используемый шаблон для обработки этого?