【问题标题】:Wait Until Webpack Dev Server Is Ready等到 Webpack 开发服务器准备好
【发布时间】:2021-02-11 06:35:56
【问题描述】:

要求

我需要运行 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] 需要 外部模块 babel-register [11:03:07] 使用 gulpfile C:\development\ucms-react\gulpfile.babel.js [11:03:07] 开始 'webpack-dev-server'... [11:03:07] [webpack-dev-server] http://0.0.0.0:3000/webpack-dev-server/index.html错误事件.js:141 投掷者; // 未处理的“错误”事件 ^

错误:连接 EADDRNOTAVAIL 0.0.0.0:3000 在 Object.exports._errnoException (util.js:907:11) 在exports._exceptionWithHostPort (util.js:930:20) 在 TCPConnectWrap.afterConnect [as oncomplete] (net.js:1077:14)

C:\development\ucms-react>

我该如何解决这个问题?

【问题讨论】:

    标签: javascript node.js webpack webpack-dev-server


    【解决方案1】:

    Brett DeWoody 的另一个答案是部分正确的。它确实会等到服务器启动。但是,这不会等待创建捆绑包。因此,如果您此时向 webpack 请求页面,它将返回类似于“仍在编译”的内容。


    要在尝试访问页面之前等待包完全编译(并且服务器正在侦听),您需要这样的东西:

    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;
        });
      });
    }
    

    然后,就像布雷特的回答一样,await 结果:

    var server = await makeServer(config);
    

    或者没有async/await:

    makeServer(config).then(server => {
      // Do something with server
    });
    

    【讨论】:

      【解决方案2】:

      这是另一个解决方案(受@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}`)
                          )
                      })
                  })
              },
          }
      }
      

      【讨论】:

      【解决方案3】:

      处理此问题的一种方法是将服务器设置包装在一个返回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
      });
      

      【讨论】:

      • 布雷特,你是个传奇!
      • @calmbird - 您使用的是哪个版本?我会为较新的版本更新解决方案。
      猜你喜欢
      • 2018-12-03
      • 1970-01-01
      • 2019-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      相关资源
      最近更新 更多