_startWebpackDevServer() {
    const webpackConfig = this.webpackConfig;
    const hot = this.hot;

    let initPromise = Promise.resolve(null);
    if (this.hasteExternals) {
      initPromise = getReactNativeExternals({
        projectRoots: this.projectRoots,
        assetRoots: this.assetRoots,
        platforms: this.platforms,
      });
    }
    return initPromise.then(reactNativeExternals => {
      let configs = Array.isArray(webpackConfig) ? webpackConfig : [webpackConfig];
      configs.forEach(function (config) {
        // Coerce externals into an array, without clobbering it
        config.externals = Array.isArray(config.externals)
          ? config.externals
          : [(config.externals || {})];

        // Inject react native externals
        if (reactNativeExternals) {
          config.externals.push(reactNativeExternals);
        } else {
          config.externals.push(reactImportTransform);
        }

        // Transform static image references
        config.externals.push(staticImageTransform);

        // By default webpack uses webpack://[resource-path]?[hash] in the source
        // map which is handled by its dev server. Use absolute path instead so
        // React Native's exception manager can load the source maps.
        config.output = config.output || {};
        if (!config.output.devtoolModuleFilenameTemplate) {
          config.output.devtoolModuleFilenameTemplate = '[absolute-resource-path]';
        }

        // Update webpack config for hot mode.
        if (hot) {
          makeHotConfig(config);
        }
      });

      // Plug into webpack compilation to extract webpack dependency tree.
      // Any React Native externals from the application source need to be
      // require()'d in the RN packager's entry file. This allows for RN
      // modules that aren't part of the main 'react-native' dependency tree
      // to be included in the generated bundle (e.g. AdSupportIOS).
      const compiler = webpack(webpackConfig);

      const compilerPromise = new Promise(resolve => {
        compiler.plugin('done', () => {
          // Write out the RN packager's entry file
          this._writeEntryFiles().then(resolve);
        });
      });

      this.webpackServer = new WebpackDevServer(compiler, {
        hot: hot,
        headers: {
          'Access-Control-Allow-Origin': '*',
        },
        stats: {colors: true, chunkModules: false},
      });

      const serverPromise = new Promise(resolve => {
        this.webpackServer.listen(this.webpackPort, this.hostname, () => {
          console.log('Webpack dev server listening at ', this.webpackBaseURL);
          resolve();
        });
        // Disable any kind of automatic timeout behavior on incoming connections.
        this.webpackServer.timeout = 0;
      });

      // Ensure that both the server is up and the compiler's entry
      // file has been written for the React Native packager.
      return Promise.all([compilerPromise, serverPromise]);
    });
  }
Starting the server is neither fast nor completely reliable we end up
hitting its public api over http periodically so we must wait for it to
be actually ready.