build.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import webpack, {Stats} from 'webpack';
  2. import chalk from 'chalk';
  3. import config from '../config/webpack.config.ts';
  4. import {
  5. errorLogger,
  6. clearBuildFolder,
  7. printBuildError,
  8. clearConsole,
  9. } from './utils.ts';
  10. import formatWebpackMessage from './formatWebpackMessage.ts';
  11. import {outputPath} from '../config/paths.ts';
  12. import {
  13. measureFileSizesBeforeBuild,
  14. printFileSizesAfterBuild,
  15. } from './fileSizeUtils.ts';
  16. import {SWTEnv} from '../config/env.ts';
  17. const MAX_CHUNK_SIZE = Number(
  18. (process.env as unknown as SWTEnv).MAX_CHUNK_SIZE ?? 0,
  19. );
  20. function build(previousFileSizes: {
  21. root: string;
  22. sizes: Record<string, number>;
  23. }) {
  24. const compiler = webpack(config);
  25. return new Promise<{
  26. stats: Stats;
  27. previousFileSizes: {
  28. root: string;
  29. sizes: Record<string, number>;
  30. };
  31. warnings: string[];
  32. }>(function(resolve, reject) {
  33. compiler.run(function(err, stats) {
  34. let message:
  35. | string
  36. | {
  37. errors: string[];
  38. warnings: string[];
  39. } = '';
  40. if (err) {
  41. if (!err.message) {
  42. return reject(err);
  43. }
  44. message = formatWebpackMessage({
  45. errors: [err.message],
  46. warnings: [],
  47. });
  48. } else {
  49. message = formatWebpackMessage(
  50. stats?.toJson({all: false, warnings: true, errors: true}) as any,
  51. );
  52. }
  53. if (message.errors.length) {
  54. // Only keep the first error. Others are often indicative
  55. // of the same problem, but confuse the reader with noise.
  56. if (message.errors.length > 1) {
  57. message.errors.length = 1;
  58. }
  59. return reject(new Error(message.errors.join('\n\n')));
  60. }
  61. return resolve({
  62. stats: stats!,
  63. previousFileSizes,
  64. warnings: message.warnings,
  65. });
  66. });
  67. });
  68. }
  69. measureFileSizesBeforeBuild(outputPath)
  70. .then(function(prevFileSizes) {
  71. clearBuildFolder();
  72. clearConsole();
  73. return build(prevFileSizes);
  74. })
  75. .then(
  76. function({stats, previousFileSizes, warnings}) {
  77. if (warnings.length) {
  78. console.log(chalk.yellow('Compiled with warnings.\n'));
  79. console.log(warnings.join('\n\n'));
  80. console.log(
  81. '\nSearch for the '
  82. + chalk.underline(chalk.yellow('keywords'))
  83. + ' to learn more about each warning.',
  84. );
  85. console.log(
  86. 'To ignore, add '
  87. + chalk.cyan('// eslint-disable-next-line')
  88. + ' to the line before.\n',
  89. );
  90. } else {
  91. console.log(chalk.green('Successfully 🤩'));
  92. }
  93. printFileSizesAfterBuild({
  94. webpackStats: stats,
  95. previousSizeMap: previousFileSizes,
  96. buildFolder: outputPath,
  97. maxSize: MAX_CHUNK_SIZE,
  98. });
  99. },
  100. function(err) {
  101. errorLogger('Failed to compile');
  102. console.log();
  103. printBuildError(err);
  104. console.log();
  105. process.exit(1);
  106. },
  107. )
  108. .catch(function(err) {
  109. if (err && err.message) {
  110. console.log();
  111. console.log(err.message);
  112. console.log();
  113. }
  114. process.exit(1);
  115. });