等到 Webpack 开发服务器准备就绪
Wait Until Webpack Dev Server Is Ready
要求
我需要 运行 webpack-dev-server 并等待服务器准备好提供页面。
解决方案
// Start a webpack-dev-server
new WebpackDevServer(webpack(myConfig), {
publicPath: myConfig.output.publicPath,
hot: true,
historyApiFallback: true,
// It suppress error shown in console, so it has to be set to false.
quiet: false,
// It suppress everything except error, so it has to be set to false as well
// to see success build.
noInfo: false,
stats: {
// Config for minimal console.log mess.
assets: false,
colors: true,
version: false,
hash: false,
timings: false,
chunks: false,
chunkModules: false
}
}).listen(3000, '0.0.0.0', function(err) {
if(err) throw new gutil.PluginError('webpack-dev-server', err);
gutil.log('[webpack-dev-server]', 'http://0.0.0.0:3000/webpack-dev-server/index.html');
//this is to ensure that end to end test wouldn't start running until the server is ready
http.get({
hostname: '0.0.0.0',
port: 3000,
path: '/',
agent: false // create a new agent just for this one request
}, (/*res*/) => {
// Do stuff with response
done();
});
});
问题
在 Linux 等待服务器准备就绪。在 Windows 我得到一个异常,因为没有等待并且服务器没有准备好
C:\development\ucms-react>gulp webpack-dev-server [11:03:01] Requiring
external module babel-register [11:03:07] Using gulpfile
C:\development\ucms-react\gulpfile.babel.js [11:03:07] Starting
'webpack-dev-server'... [11:03:07] [webpack-dev-server]
http://0.0.0.0:3000/webpack-dev-server/index.html error events.js:141
throw er; // Unhandled 'error' event
^
Error: connect EADDRNOTAVAIL 0.0.0.0:3000
at Object.exports._errnoException (util.js:907:11)
at exports._exceptionWithHostPort (util.js:930:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1077:14)
C:\development\ucms-react>
我该如何解决这个问题?
处理此问题的一种方法是将服务器设置包装在 returns 和 Promise
的函数中。 Promise 在服务器连接时解析,或者在出现错误时被拒绝。
这是一个简化的例子:
function startServer() {
return new Promise((resolve, reject) => {
new WebpackDevServer(webpack(myConfig), {
// Do stuff
}).listen(3000, '0.0.0.0', function(err) {
resolve();
}).on('error', (error) => {
reject(error);
});
});
}
然后在服务器启动时提供回调:
var server = startServer();
server.then(function() {
// Run tests
});
Brett DeWoody 的另一个回答部分正确。它会正确地等到服务器启动。但是,这不会等待创建捆绑包。因此,如果此时您向 webpack 请求一个页面,它将 return 类似于“仍在编译”的东西。
要在尝试访问页面之前等待包完全编译(并且服务器正在侦听),您需要这样的东西:
function makeServer(config) {
return new Promise((resolve, reject) => {
const compiler = webpack(config);
let compiled = false;
let listening = false;
compiler.hooks.done.tap('IDoNotUnderstandWhatThisStringIsForButItCannotBeEmpty', () => {
// console.log('compiled');
if (listening) resolve(server);
else compiled = true;
});
const server = new WebpackDevServer(compiler, config.devServer);
server.listen(port, '0.0.0.0', err => {
if (err) return reject(err);
// console.log('listening');
if (compiled) resolve(server);
else listening = true;
});
});
}
然后,就像 Brett 的回答一样,await
结果:
var server = await makeServer(config);
或没有async
/await
:
makeServer(config).then(server => {
// Do something with server
});
这是另一个解决方案(灵感来自@CameronTacklind 的回答)。 setImmediate
使日志输出显示在初始编译器日志输出下方。
const PORT = process.env.PORT || 3000
const compiler = webpack(config)
new WebpackDevServer(compiler).listen(PORT, '0.0.0.0', err => {
if (err) {
console.log(err)
}
})
compiler.hooks.done.tap('done', () => {
setImmediate(() => {
console.log()
console.log(`Running at http://localhost:${PORT}`)
})
})
更新
这是一个不需要自定义服务器脚本的替代版本——您只需将其添加到您的 webpack 配置选项中即可。如果默认端口不可用,它还保留了自动使用不同端口的内置功能……当然,如果您更愿意指定端口,则不必使用该部分。
const chalk = require('chalk')
...
module.exports = {
....
devServer: {
onListening: server => {
const { port } = server.listeningApp.address()
server.compiler.hooks.done.tap('done', () => {
setImmediate(() => {
console.log()
console.log(
chalk.cyan.bold(`Running at http://localhost:${port}`)
)
})
})
},
}
}
要求
我需要 运行 webpack-dev-server 并等待服务器准备好提供页面。
解决方案
// Start a webpack-dev-server
new WebpackDevServer(webpack(myConfig), {
publicPath: myConfig.output.publicPath,
hot: true,
historyApiFallback: true,
// It suppress error shown in console, so it has to be set to false.
quiet: false,
// It suppress everything except error, so it has to be set to false as well
// to see success build.
noInfo: false,
stats: {
// Config for minimal console.log mess.
assets: false,
colors: true,
version: false,
hash: false,
timings: false,
chunks: false,
chunkModules: false
}
}).listen(3000, '0.0.0.0', function(err) {
if(err) throw new gutil.PluginError('webpack-dev-server', err);
gutil.log('[webpack-dev-server]', 'http://0.0.0.0:3000/webpack-dev-server/index.html');
//this is to ensure that end to end test wouldn't start running until the server is ready
http.get({
hostname: '0.0.0.0',
port: 3000,
path: '/',
agent: false // create a new agent just for this one request
}, (/*res*/) => {
// Do stuff with response
done();
});
});
问题
在 Linux 等待服务器准备就绪。在 Windows 我得到一个异常,因为没有等待并且服务器没有准备好
C:\development\ucms-react>gulp webpack-dev-server [11:03:01] Requiring external module babel-register [11:03:07] Using gulpfile C:\development\ucms-react\gulpfile.babel.js [11:03:07] Starting 'webpack-dev-server'... [11:03:07] [webpack-dev-server] http://0.0.0.0:3000/webpack-dev-server/index.html error events.js:141 throw er; // Unhandled 'error' event ^
Error: connect EADDRNOTAVAIL 0.0.0.0:3000 at Object.exports._errnoException (util.js:907:11) at exports._exceptionWithHostPort (util.js:930:20) at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1077:14)
C:\development\ucms-react>
我该如何解决这个问题?
处理此问题的一种方法是将服务器设置包装在 returns 和 Promise
的函数中。 Promise 在服务器连接时解析,或者在出现错误时被拒绝。
这是一个简化的例子:
function startServer() {
return new Promise((resolve, reject) => {
new WebpackDevServer(webpack(myConfig), {
// Do stuff
}).listen(3000, '0.0.0.0', function(err) {
resolve();
}).on('error', (error) => {
reject(error);
});
});
}
然后在服务器启动时提供回调:
var server = startServer();
server.then(function() {
// Run tests
});
Brett DeWoody 的另一个回答部分正确。它会正确地等到服务器启动。但是,这不会等待创建捆绑包。因此,如果此时您向 webpack 请求一个页面,它将 return 类似于“仍在编译”的东西。
要在尝试访问页面之前等待包完全编译(并且服务器正在侦听),您需要这样的东西:
function makeServer(config) {
return new Promise((resolve, reject) => {
const compiler = webpack(config);
let compiled = false;
let listening = false;
compiler.hooks.done.tap('IDoNotUnderstandWhatThisStringIsForButItCannotBeEmpty', () => {
// console.log('compiled');
if (listening) resolve(server);
else compiled = true;
});
const server = new WebpackDevServer(compiler, config.devServer);
server.listen(port, '0.0.0.0', err => {
if (err) return reject(err);
// console.log('listening');
if (compiled) resolve(server);
else listening = true;
});
});
}
然后,就像 Brett 的回答一样,await
结果:
var server = await makeServer(config);
或没有async
/await
:
makeServer(config).then(server => {
// Do something with server
});
这是另一个解决方案(灵感来自@CameronTacklind 的回答)。 setImmediate
使日志输出显示在初始编译器日志输出下方。
const PORT = process.env.PORT || 3000
const compiler = webpack(config)
new WebpackDevServer(compiler).listen(PORT, '0.0.0.0', err => {
if (err) {
console.log(err)
}
})
compiler.hooks.done.tap('done', () => {
setImmediate(() => {
console.log()
console.log(`Running at http://localhost:${PORT}`)
})
})
更新
这是一个不需要自定义服务器脚本的替代版本——您只需将其添加到您的 webpack 配置选项中即可。如果默认端口不可用,它还保留了自动使用不同端口的内置功能……当然,如果您更愿意指定端口,则不必使用该部分。
const chalk = require('chalk')
...
module.exports = {
....
devServer: {
onListening: server => {
const { port } = server.listeningApp.address()
server.compiler.hooks.done.tap('done', () => {
setImmediate(() => {
console.log()
console.log(
chalk.cyan.bold(`Running at http://localhost:${port}`)
)
})
})
},
}
}