diff --git a/src/utils/setupOutputFileSystem.js b/src/utils/setupOutputFileSystem.js index b54f83c77..49e461956 100644 --- a/src/utils/setupOutputFileSystem.js +++ b/src/utils/setupOutputFileSystem.js @@ -16,8 +16,31 @@ function setupOutputFileSystem(context) { const { outputFileSystem: outputFileSystemFromOptions } = context.options; outputFileSystem = outputFileSystemFromOptions; - } else { + } + // Don't use `memfs` when developer wants to write everything to a disk, because it doesn't make sense. + else if (context.options.writeToDisk !== true) { outputFileSystem = memfs.createFsFromVolume(new memfs.Volume()); + } else { + const isMultiCompiler = + /** @type {MultiCompiler} */ + (context.compiler).compilers; + + if (isMultiCompiler) { + // Prefer compiler with `devServer` option or fallback on the first + // TODO we need to support webpack-dev-server as a plugin or revisit it + const compiler = + /** @type {MultiCompiler} */ + (context.compiler).compilers.filter((item) => + Object.prototype.hasOwnProperty.call(item.options, "devServer") + ); + + ({ outputFileSystem } = + compiler[0] || + /** @type {MultiCompiler} */ + (context.compiler).compilers[0]); + } else { + ({ outputFileSystem } = context.compiler); + } } const compilers = diff --git a/test/middleware.test.js b/test/middleware.test.js index 45b9a9a1a..bd77eb320 100644 --- a/test/middleware.test.js +++ b/test/middleware.test.js @@ -2373,6 +2373,84 @@ describe.each([ }); }); + describe('should work with "true" value when the `output.clean` is `true`', () => { + const outputPath = path.resolve( + __dirname, + "./outputs/write-to-disk-true-with-clean" + ); + + let compiler; + + beforeAll((done) => { + compiler = getCompiler({ + ...webpackConfig, + output: { + clean: true, + filename: "bundle.js", + path: outputPath, + }, + }); + + instance = middleware(compiler, { writeToDisk: true }); + + fs.mkdirSync(outputPath, { + recursive: true, + }); + fs.writeFileSync(path.resolve(outputPath, "test.json"), "{}"); + + app = framework(); + app.use(instance); + + listen = listenShorthand(done); + + req = request(app); + }); + + afterAll((done) => { + del.sync(outputPath); + + close(done); + }); + + it("should find the bundle file on disk", (done) => { + request(app) + .get("/bundle.js") + .expect(200, (error) => { + if (error) { + return done(error); + } + + const bundlePath = path.resolve(outputPath, "bundle.js"); + + expect(fs.existsSync(path.resolve(outputPath, "test.json"))).toBe( + false + ); + + expect( + compiler.hooks.assetEmitted.taps.filter( + (hook) => hook.name === "DevMiddleware" + ).length + ).toBe(1); + expect(fs.existsSync(bundlePath)).toBe(true); + + instance.invalidate(); + + return compiler.hooks.done.tap( + "DevMiddlewareWriteToDiskTest", + () => { + expect( + compiler.hooks.assetEmitted.taps.filter( + (hook) => hook.name === "DevMiddleware" + ).length + ).toBe(1); + + done(); + } + ); + }); + }); + }); + describe('should work with "false" value', () => { let compiler;