fs.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. 'use strict';
  2. const fs = require('fs');
  3. const path = require('path');
  4. const MemoryFileSystem = require('memory-fs');
  5. const { colors } = require('webpack-log');
  6. const NodeOutputFileSystem = require('webpack/lib/node/NodeOutputFileSystem');
  7. const DevMiddlewareError = require('./DevMiddlewareError');
  8. const { mkdirp } = new NodeOutputFileSystem();
  9. module.exports = {
  10. toDisk(context) {
  11. const compilers = context.compiler.compilers || [context.compiler];
  12. for (const compiler of compilers) {
  13. compiler.hooks.afterEmit.tap('WebpackDevMiddleware', (compilation) => {
  14. const { assets } = compilation;
  15. const { log } = context;
  16. const { writeToDisk: filter } = context.options;
  17. let { outputPath } = compiler;
  18. if (outputPath === '/') {
  19. outputPath = compiler.context;
  20. }
  21. for (const assetPath of Object.keys(assets)) {
  22. let targetFile = assetPath;
  23. const queryStringIdx = targetFile.indexOf('?');
  24. if (queryStringIdx >= 0) {
  25. targetFile = targetFile.substr(0, queryStringIdx);
  26. }
  27. const targetPath = path.isAbsolute(targetFile)
  28. ? targetFile
  29. : path.join(outputPath, targetFile);
  30. const allowWrite =
  31. filter && typeof filter === 'function' ? filter(targetPath) : true;
  32. if (allowWrite) {
  33. const asset = assets[assetPath];
  34. let content = asset.source();
  35. if (!Buffer.isBuffer(content)) {
  36. // TODO need remove in next major release
  37. if (Array.isArray(content)) {
  38. content = content.join('\n');
  39. }
  40. content = Buffer.from(content, 'utf8');
  41. }
  42. mkdirp.sync(path.dirname(targetPath));
  43. try {
  44. fs.writeFileSync(targetPath, content, 'utf-8');
  45. log.debug(
  46. colors.cyan(
  47. `Asset written to disk: ${path.relative(
  48. process.cwd(),
  49. targetPath
  50. )}`
  51. )
  52. );
  53. } catch (e) {
  54. log.error(`Unable to write asset to disk:\n${e}`);
  55. }
  56. }
  57. }
  58. });
  59. }
  60. },
  61. setFs(context, compiler) {
  62. if (
  63. typeof compiler.outputPath === 'string' &&
  64. !path.posix.isAbsolute(compiler.outputPath) &&
  65. !path.win32.isAbsolute(compiler.outputPath)
  66. ) {
  67. throw new DevMiddlewareError(
  68. '`output.path` needs to be an absolute path or `/`.'
  69. );
  70. }
  71. let fileSystem;
  72. // store our files in memory
  73. const isConfiguredFs = context.options.fs;
  74. const isMemoryFs =
  75. !isConfiguredFs &&
  76. !compiler.compilers &&
  77. compiler.outputFileSystem instanceof MemoryFileSystem;
  78. if (isConfiguredFs) {
  79. // eslint-disable-next-line no-shadow
  80. const { fs } = context.options;
  81. if (typeof fs.join !== 'function') {
  82. // very shallow check
  83. throw new Error(
  84. 'Invalid options: options.fs.join() method is expected'
  85. );
  86. }
  87. // eslint-disable-next-line no-param-reassign
  88. compiler.outputFileSystem = fs;
  89. fileSystem = fs;
  90. } else if (isMemoryFs) {
  91. fileSystem = compiler.outputFileSystem;
  92. } else {
  93. fileSystem = new MemoryFileSystem();
  94. // eslint-disable-next-line no-param-reassign
  95. compiler.outputFileSystem = fileSystem;
  96. }
  97. // eslint-disable-next-line no-param-reassign
  98. context.fs = fileSystem;
  99. },
  100. };