Тёрка в тагах


Друзья

Его(2) Общие(0) Хотят дружить(0)


  • Atrinax

  • Blackoff

  • login

  • login

  • login

  • login

Враги

Его(0) Общие(0) Обиженные(1)

Большая Тёрка / Мысли / Личная лента olegchir /


olegchir

Node.js server automatic reloading without nodemon (grunt + watch task + grunt-shell-spawn)

Везде в интернетах пишут про использование nodemon, но имхо он какой-то не очень удобный. Он не умеет интегрироваться с watch.
Вот понаписал я кучу всяких кастомных вотчей, и что теперь, стирать это сосать лапу, перегружая всё сразу (минус статический список игноров)?

Теперь решение.

Вначале npm install grunt-shell-spawn --save-dev.
Это форк grunt-shell, умеющий запускать фоновые процессы.
Всё то же самое, но появляется опция async: true.

Теперь нам есть чем запускать Ноду, но убить ее так не получится: т.к. запуск асинхронный, watch запускает новый рестарт до того, как отработал старый. failOnError: false в данном случае не помогает. Неважно как запускается: или через встроенную возможность последовательного выполнения, или через "killall node || node ./app.js || true".

Поэтому для killall node будем юзать просто grunt.util.spawn.
Внимание на окончание: fallback: 0 }, function (error, result, code) {return 0}.
Эта строчка проглатывает ошибки и позволяет процессу продолжаться, даже если с killall'ом что-то случилось.

Под катом важные части Gruntfile:
Читать далее


module.exports = function (grunt) {

...

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

...

    grunt.registerTask('stopNode', function() {
        grunt.util.spawn({
            cmd: 'killall',
            args: ['node'],
            fallback: 0
        }, function (error, result, code) {return 0});
    });
    grunt.registerTask('startNode', ['shell:startNode']);
    grunt.registerTask('restartNode', ['stopNode','startNode']);

...

        watch: {
            options: {
                livereload: true,
                nospawn: true
            },
            coffee: {
                files: ["./*.coffee", 'routes/*.coffee'],
                tasks: [
                    "coffee",
             "restartNode"
                ]
            }
        },
        shell: {
            startNode: {
                command: ["node ./app.js"],
                options: {
                    async: true,
                    execOptions: {
                        cwd: './',
                        detached: true
                    }
                }
            },
            options: {
                stdout: true,
                stderr: true,
                failOnError: false
            }
        }

...

    });
};