我正在尝试改善节点中的DEV体验。为此,我想:
a)更改服务器端代码时重启我的服务器
b)在客户端代码发生变化时刷新浏览器。
为了实现这一目标,我开始将nodemon和browserSync集成到我的gulp脚本中。
在我的gulp脚本中,我有以下任务:
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
我在某种程度上理解。我的server.js文件中有app.set('port', process.env.PORT || 3002);
。然而,我认为这是设置代理值的目的。不过,每当我进行代码更改时,我在控制台窗口中都会看到以下相关错误:
[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 UI。出于这两个原因,我想我会在我的server.js文件中将端口设置为3002并创建上面显示的代理。我做错了什么?
答案 0 :(得分:16)
你实际上不需要使用gulp来实现这一点。
a)在更改服务器端代码时重启我的服务器
使用npm i -g nodemon
全局安装nodemon,然后在您的应用文件夹上执行nodemon
或nodemon ${index-file-of-your-app}
。
b)在客户端代码发生变化时刷新浏览器。
使用browserify或webpack。我更喜欢使用webpack;你可能需要了解一下配置,但webpack的好处是你不需要刷新它。一旦找到更改,更改将自动反映在浏览器上。 https://github.com/webpack/docs/wiki/hot-module-replacement-with-webpack
答案 1 :(得分:1)
我可能会错过某些上下文(例如,我不确定input
代表什么),但是,我认为this 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'));
});
答案 2 :(得分:0)
EADDRINUSE错误通常是由于指定端口上已打开连接。这可能是由于重新启动应用程序时前一个连接实例未正确关闭。
看看this gist,特别是在你的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;
}
});
});
答案 3 :(得分:0)
@mateeyow是对的。
但如果您希望浏览器自动重新加载,您还需要livereload-plugin。
启用webpack-hot-replacement只替换浏览器内存中的代码,livereload-plugin会重新加载它。
请参阅rock:https://github.com/orange727/rock/blob/master/app/templates/webpack/webpack.make.js#L255
就像:
private bool setFocus = true;
private void MyText_LostFocus(object sender, RoutedEventArgs e)
{
if (setFocus == true)
{
MyText.Focus(FocusState.Programmatic);
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MyButton.Focus(FocusState.Programmatic);
}
private void MyButton_PointerEntered(object sender, PointerRoutedEventArgs e)
{
setFocus = false;
}
private void MyButton_PointerExited(object sender, PointerRoutedEventArgs e)
{
setFocus = true;
}
答案 4 :(得分:0)
您可以通过一起使用“ livereload”,“ connect-livereload”和“ nodemon”软件包将前端和后端更改实时重新加载到浏览器。而且,这种方式您不需要Gulp或Grunt。这些包如何一起玩:
livereload
打开一个高端口,并通知浏览器更改的公共文件connect-livereload
猴子用连接到此高端口的代码片段修补了每个投放的HTML页面nodemon
然后用于在更改的后端文件上重新启动服务器在Express中设置实时重载
将Express设置为既可以启动livereload服务器以监视公共目录,又可以在nodemon引起的重启期间对浏览器执行ping操作:
const livereload = require("livereload");
const connectLivereload = require("connect-livereload");
// open livereload high port and start to watch public directory for changes
const liveReloadServer = livereload.createServer();
liveReloadServer.watch(path.join(__dirname, 'public'));
// ping browser on Express boot, once browser has reconnected and handshaken
liveReloadServer.server.once("connection", () => {
setTimeout(() => {
liveReloadServer.refresh("/");
}, 100);
});
const app = express();
// monkey patch every served HTML so they know of changes
app.use(connectLivereload());
使用nodemon启动Express
然后,您可以通过运行npm run watch
使用nodemon启动服务器,例如,使用专用监视脚本启动它。
这里的关键点是忽略livereload已经监视的公共目录。您还可以配置带有非默认扩展名的文件,例如pug和mustache,以进行监视。
"scripts": {
"start": "node ./bin/www",
"watch": "nodemon --ext js,pug --ignore public"
},
您可以在"Refresh front and backend changes to browser with Express, LiveReload and Nodemon."
中阅读更长的解释