setupWriteToDisk.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. "use strict";
  2. const fs = require("fs");
  3. const path = require("path");
  4. /** @typedef {import("webpack").Compiler} Compiler */
  5. /** @typedef {import("webpack").MultiCompiler} MultiCompiler */
  6. /** @typedef {import("webpack").Compilation} Compilation */
  7. /** @typedef {import("../index.js").IncomingMessage} IncomingMessage */
  8. /** @typedef {import("../index.js").ServerResponse} ServerResponse */
  9. /**
  10. * @template {IncomingMessage} Request
  11. * @template {ServerResponse} Response
  12. * @param {import("../index.js").Context<Request, Response>} context
  13. */
  14. function setupWriteToDisk(context) {
  15. /**
  16. * @type {Compiler[]}
  17. */
  18. const compilers =
  19. /** @type {MultiCompiler} */
  20. context.compiler.compilers || [context.compiler];
  21. for (const compiler of compilers) {
  22. compiler.hooks.emit.tap("DevMiddleware",
  23. /**
  24. * @param {Compilation} compilation
  25. */
  26. compilation => {
  27. // @ts-ignore
  28. if (compiler.hasWebpackDevMiddlewareAssetEmittedCallback) {
  29. return;
  30. }
  31. compiler.hooks.assetEmitted.tapAsync("DevMiddleware", (file, info, callback) => {
  32. /**
  33. * @type {string}
  34. */
  35. let targetPath;
  36. /**
  37. * @type {Buffer}
  38. */
  39. let content; // webpack@5
  40. if (info.compilation) {
  41. ({
  42. targetPath,
  43. content
  44. } = info);
  45. } else {
  46. let targetFile = file;
  47. const queryStringIdx = targetFile.indexOf("?");
  48. if (queryStringIdx >= 0) {
  49. targetFile = targetFile.slice(0, queryStringIdx);
  50. }
  51. let {
  52. outputPath
  53. } = compiler;
  54. outputPath = compilation.getPath(outputPath, {}); // @ts-ignore
  55. content = info;
  56. targetPath = path.join(outputPath, targetFile);
  57. }
  58. const {
  59. writeToDisk: filter
  60. } = context.options;
  61. const allowWrite = filter && typeof filter === "function" ? filter(targetPath) : true;
  62. if (!allowWrite) {
  63. return callback();
  64. }
  65. const dir = path.dirname(targetPath);
  66. const name = compiler.options.name ? `Child "${compiler.options.name}": ` : "";
  67. return fs.mkdir(dir, {
  68. recursive: true
  69. }, mkdirError => {
  70. if (mkdirError) {
  71. context.logger.error(`${name}Unable to write "${dir}" directory to disk:\n${mkdirError}`);
  72. return callback(mkdirError);
  73. }
  74. return fs.writeFile(targetPath, content, writeFileError => {
  75. if (writeFileError) {
  76. context.logger.error(`${name}Unable to write "${targetPath}" asset to disk:\n${writeFileError}`);
  77. return callback(writeFileError);
  78. }
  79. context.logger.log(`${name}Asset written to disk: "${targetPath}"`);
  80. return callback();
  81. });
  82. });
  83. }); // @ts-ignore
  84. compiler.hasWebpackDevMiddlewareAssetEmittedCallback = true;
  85. });
  86. }
  87. }
  88. module.exports = setupWriteToDisk;