webpack-dev-server.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #!/usr/bin/env node
  2. 'use strict';
  3. /* eslint-disable no-shadow, no-console */
  4. const fs = require('fs');
  5. const net = require('net');
  6. const debug = require('debug')('webpack-dev-server');
  7. const importLocal = require('import-local');
  8. const yargs = require('yargs');
  9. const webpack = require('webpack');
  10. const Server = require('../lib/Server');
  11. const setupExitSignals = require('../lib/utils/setupExitSignals');
  12. const colors = require('../lib/utils/colors');
  13. const processOptions = require('../lib/utils/processOptions');
  14. const createLogger = require('../lib/utils/createLogger');
  15. const findPort = require('../lib/utils/findPort');
  16. const getVersions = require('../lib/utils/getVersions');
  17. const options = require('./options');
  18. let server;
  19. setupExitSignals(server);
  20. // Prefer the local installation of webpack-dev-server
  21. if (importLocal(__filename)) {
  22. debug('Using local install of webpack-dev-server');
  23. return;
  24. }
  25. try {
  26. require.resolve('webpack-cli');
  27. } catch (err) {
  28. console.error('The CLI moved into a separate package: webpack-cli');
  29. console.error(
  30. "Please install 'webpack-cli' in addition to webpack itself to use the CLI"
  31. );
  32. console.error('-> When using npm: npm i -D webpack-cli');
  33. console.error('-> When using yarn: yarn add -D webpack-cli');
  34. process.exitCode = 1;
  35. }
  36. yargs.usage(
  37. `${getVersions()}\nUsage: https://webpack.js.org/configuration/dev-server/`
  38. );
  39. // webpack-cli@3.3 path : 'webpack-cli/bin/config/config-yargs'
  40. let configYargsPath;
  41. try {
  42. require.resolve('webpack-cli/bin/config/config-yargs');
  43. configYargsPath = 'webpack-cli/bin/config/config-yargs';
  44. } catch (e) {
  45. configYargsPath = 'webpack-cli/bin/config-yargs';
  46. }
  47. // eslint-disable-next-line import/no-extraneous-dependencies
  48. // eslint-disable-next-line import/no-dynamic-require
  49. require(configYargsPath)(yargs);
  50. // It is important that this is done after the webpack yargs config,
  51. // so it overrides webpack's version info.
  52. yargs.version(getVersions());
  53. yargs.options(options);
  54. const argv = yargs.argv;
  55. // webpack-cli@3.3 path : 'webpack-cli/bin/utils/convert-argv'
  56. let convertArgvPath;
  57. try {
  58. require.resolve('webpack-cli/bin/utils/convert-argv');
  59. convertArgvPath = 'webpack-cli/bin/utils/convert-argv';
  60. } catch (e) {
  61. convertArgvPath = 'webpack-cli/bin/convert-argv';
  62. }
  63. // eslint-disable-next-line import/no-extraneous-dependencies
  64. // eslint-disable-next-line import/no-dynamic-require
  65. const config = require(convertArgvPath)(yargs, argv, {
  66. outputFilename: '/bundle.js',
  67. });
  68. function startDevServer(config, options) {
  69. const log = createLogger(options);
  70. let compiler;
  71. try {
  72. compiler = webpack(config);
  73. } catch (err) {
  74. if (err instanceof webpack.WebpackOptionsValidationError) {
  75. log.error(colors.error(options.stats.colors, err.message));
  76. // eslint-disable-next-line no-process-exit
  77. process.exit(1);
  78. }
  79. throw err;
  80. }
  81. if (options.progress) {
  82. new webpack.ProgressPlugin({
  83. profile: argv.profile,
  84. }).apply(compiler);
  85. }
  86. try {
  87. server = new Server(compiler, options, log);
  88. } catch (err) {
  89. if (err.name === 'ValidationError') {
  90. log.error(colors.error(options.stats.colors, err.message));
  91. // eslint-disable-next-line no-process-exit
  92. process.exit(1);
  93. }
  94. throw err;
  95. }
  96. if (options.socket) {
  97. server.listeningApp.on('error', (e) => {
  98. if (e.code === 'EADDRINUSE') {
  99. const clientSocket = new net.Socket();
  100. clientSocket.on('error', (err) => {
  101. if (err.code === 'ECONNREFUSED') {
  102. // No other server listening on this socket so it can be safely removed
  103. fs.unlinkSync(options.socket);
  104. server.listen(options.socket, options.host, (error) => {
  105. if (error) {
  106. throw error;
  107. }
  108. });
  109. }
  110. });
  111. clientSocket.connect({ path: options.socket }, () => {
  112. throw new Error('This socket is already used');
  113. });
  114. }
  115. });
  116. server.listen(options.socket, options.host, (err) => {
  117. if (err) {
  118. throw err;
  119. }
  120. // chmod 666 (rw rw rw)
  121. const READ_WRITE = 438;
  122. fs.chmod(options.socket, READ_WRITE, (err) => {
  123. if (err) {
  124. throw err;
  125. }
  126. });
  127. });
  128. } else {
  129. findPort(options.port)
  130. .then((port) => {
  131. options.port = port;
  132. server.listen(options.port, options.host, (err) => {
  133. if (err) {
  134. throw err;
  135. }
  136. });
  137. })
  138. .catch((err) => {
  139. throw err;
  140. });
  141. }
  142. }
  143. processOptions(config, argv, (config, options) => {
  144. startDevServer(config, options);
  145. });