Node.js - Автоматическое обновление в Dev

Я пытаюсь улучшить опыт DEV в моем Node. Для этого хочу:

a) перезагрузите сервер при изменении кода на стороне сервера

b) обновите браузер, когда изменяется код на стороне клиента.

Чтобы сделать это, я начал интегрировать nodemon и browserSync в мой gulp script.

В моем gulp script у меня есть следующая задача:

gulp.task('startDevEnv', function(done) {
    // Begin watching for server-side file changes
    nodemon(
        { script: input.server, ignore:[input.views] })
        .on('start', function () {
            browserSync.init({
                proxy: "http://localhost:3002"
            });
        })
    ;    

    // Begin watching client-side file changes
    gulp.watch([ input.css, input.js, input.html ], function() { browserSync.reload(); });
    done();
});

При выполнении указанной задачи мой браузер открывает http://localhost:3000/. Мое приложение видно, как ожидалось. Однако в окне консоли я замечаю:

Error: listen EADDRINUSE :::3002

Я понимаю в некоторой степени. У меня есть app.set('port', process.env.PORT || 3002); в моем файле server.js. Тем не менее, я думал, что это цель установки значения прокси. Тем не менее, всякий раз, когда я делаю изменение кода, я вижу следующую связанную ошибку в окне консоли:

[07:08:19] [nodemon] restarting due to changes...
[07:08:19] [nodemon] starting `node ./dist/server.js`
events.js:142
      throw er; // Unhandled 'error' event
      ^

TypeError: args.cb is not a function
    at Object.init (/Users/me/Website/Develop/node_modules/browser-sync/lib/public/init.js:25:25)
    at null.<anonymous> (/Users/me/Website/Develop/gulpfile.js:142:25)
    at emitNone (events.js:73:20)
    at emit (events.js:167:7)
    at Object.run (/Users/me/Website/Develop/node_modules/nodemon/lib/monitor/run.js:97:7)
    at Function.run.kill (/Users/me/Website/Develop/node_modules/nodemon/lib/monitor/run.js:221:7)
    at null.<anonymous> (/Users/me/Website/Develop/node_modules/nodemon/lib/monitor/run.js:333:7)
    at emitOne (events.js:83:20)
    at emit (events.js:170:7)
    at restartBus (/Users/me/Website/Develop/node_modules/nodemon/lib/monitor/watch.js:162:7)
Me-MBP:Develop me$ events.js:142
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRINUSE :::3002
    at Object.exports._errnoException (util.js:856:11)
    at exports._exceptionWithHostPort (util.js:879:20)
    at Server._listen2 (net.js:1238:14)
    at listen (net.js:1274:10)
    at Server.listen (net.js:1370:5)
    at Object.<anonymous> (/Users/me/Website/Develop/dist/server.js:70:8)
    at Module._compile (module.js:399:26)
    at Object.Module._extensions..js (module.js:406:10)
    at Module.load (module.js:345:32)
    at Function.Module._load (module.js:302:12)

В этот момент изменения моего кода не отображаются в моем браузере. Я не понимаю, что я делаю неправильно. Я подозреваю, что мои порты неправильно сконфигурированы. Но я не уверен, как их настроить.

По умолчанию BrowserSync использует порт 3000. BrowserSync также использует порт 3001 для интерфейса BrowserSync. По этим двум причинам я решил установить порт на 3002 в файле server.js и создать прокси-сервер, показанный выше. Что я делаю неправильно?

Ответ 1

Вам действительно не нужно использовать gulp для этого.

a) перезагрузите мой сервер при изменении кода на стороне сервера

Установите nodemon глобально, используя npm i -g nodemon, затем в папке вашего приложения сделайте nodemon или nodemon ${index-file-of-your-app}.

b) обновите браузер, когда клиентский код будет изменен.

Используйте браузер или веб-пакет. Я предпочитаю использовать webpack; вам может понадобиться немного узнать о конфигурации, но хорошая вещь с webpack заключается в том, что вам не нужно ее обновлять. Как только изменения будут найдены, изменения будут автоматически отображены в браузере. https://github.com/webpack/docs/wiki/hot-module-replacement-with-webpack

Ответ 2

Возможно, мне не хватает некоторого контекста (например, я не уверен, что представляет собой input), однако я думаю, что модуль reload модуля npm может решить вашу проблему. Вот пример со страницы пакета npm:

var express = require('express')
  , http = require('http')
  , path = require('path')
  , reload = require('reload')
  , bodyParser = require('body-parser')
  , logger = require('morgan')

var app = express()

var publicDir = path.join(__dirname, '')

app.set('port', process.env.PORT || 3000)
app.use(logger('dev'))
app.use(bodyParser.json()) //parses json, multi-part (file), url-encoded  

app.get('/', function(req, res) {
  res.sendFile(path.join(publicDir, 'index.html'))
})

var server = http.createServer(app)

//reload code here 
//optional reload delay and wait argument can be given to reload, refer to [API](https://github.com/jprichardson/reload#api) below 
reload(server, app, [reloadDelay], [wait])

server.listen(app.get('port'), function(){
  console.log("Web server listening on port " + app.get('port'));
});

Ответ 3

Ошибка EADDRINUSE, как правило, связана с подключением, уже открытым на указанном порту. Вероятно, это связано с тем, что предыдущий экземпляр соединения не был правильно закрыт при перезапуске приложения.

Посмотрите этот смысл и, в частности, попробуйте что-то подобное в вашем файле gulp:

'use strict';

var gulp = require('gulp');
var browserSync = require('browser-sync');
var nodemon = require('gulp-nodemon');

gulp.task('default', ['browser-sync'], function () {});

gulp.task('browser-sync', ['nodemon'], function() {
    browserSync.init(null, {
        proxy: "http://localhost:3002"
    });
});

gulp.task('nodemon', function (cb) {

    var started = false;

    return nodemon({
        script: 'app.js'
    }).on('start', function () {
        // to avoid nodemon being started multiple times
        if (!started) {
            cb();
            started = true; 
        } 
    });
});

Ответ 4

@mateeyow прав.

Но если вы хотите, чтобы браузер автоматически перезагружался, вам также нужен плагин с настройками вставки.

Включить замену webpack-hot-замены только в памяти браузера, перезагрузить его.

Смотрите рок, например: https://github.com/orange727/rock/blob/master/app/templates/webpack/webpack.make.js#L255

Так же:

webpackConfig.plugins: [
  new webpack.HotModuleReplacementPlugin(),
  new LiveReloadPlugin({
    appendScriptTag: true,
    port: config.ports.livereload,
})];