setupWriteToDisk.js 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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 = /** @type {MultiCompiler} */
  19. context.compiler.compilers || [context.compiler];
  20. for (const compiler of compilers) {
  21. compiler.hooks.emit.tap("DevMiddleware",
  22. /**
  23. * @param {Compilation} compilation
  24. */
  25. compilation => {
  26. // @ts-ignore
  27. if (compiler.hasWebpackDevMiddlewareAssetEmittedCallback) {
  28. return;
  29. }
  30. compiler.hooks.assetEmitted.tapAsync("DevMiddleware", (file, info, callback) => {
  31. /**
  32. * @type {string}
  33. */
  34. let targetPath;
  35. /**
  36. * @type {Buffer}
  37. */
  38. let content;
  39. // 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, {});
  55. // @ts-ignore
  56. content = info;
  57. targetPath = path.join(outputPath, targetFile);
  58. }
  59. const {
  60. writeToDisk: filter
  61. } = context.options;
  62. const allowWrite = filter && typeof filter === "function" ? filter(targetPath) : true;
  63. if (!allowWrite) {
  64. return callback();
  65. }
  66. const dir = path.dirname(targetPath);
  67. const name = compiler.options.name ? `Child "${compiler.options.name}": ` : "";
  68. return fs.mkdir(dir, {
  69. recursive: true
  70. }, mkdirError => {
  71. if (mkdirError) {
  72. context.logger.error(`${name}Unable to write "${dir}" directory to disk:\n${mkdirError}`);
  73. return callback(mkdirError);
  74. }
  75. return fs.writeFile(targetPath, content, writeFileError => {
  76. if (writeFileError) {
  77. context.logger.error(`${name}Unable to write "${targetPath}" asset to disk:\n${writeFileError}`);
  78. return callback(writeFileError);
  79. }
  80. context.logger.log(`${name}Asset written to disk: "${targetPath}"`);
  81. return callback();
  82. });
  83. });
  84. });
  85. // @ts-ignore
  86. compiler.hasWebpackDevMiddlewareAssetEmittedCallback = true;
  87. });
  88. }
  89. }
  90. module.exports = setupWriteToDisk;