Skip to content

Commit e343d8a

Browse files
committed
fix: plugin uses infrastructureLogger and outputs the report.html to compiler.outputFileSystem
1 parent 8dce252 commit e343d8a

File tree

4 files changed

+76
-44
lines changed

4 files changed

+76
-44
lines changed

src/BundleAnalyzerPlugin.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
const fs = require('fs');
21
const path = require('path');
32
const {bold} = require('chalk');
43

54
const Logger = require('./Logger');
65
const viewer = require('./viewer');
76
const utils = require('./utils');
87
const {writeStats} = require('./statsUtils');
8+
const PLUGIN_NAME = 'webpack-bundle-analyzer';
99

1010
class BundleAnalyzerPlugin {
1111
constructor(opts = {}) {
@@ -35,6 +35,8 @@ class BundleAnalyzerPlugin {
3535
this.compiler = compiler;
3636

3737
const done = (stats, callback) => {
38+
const isWebpack5 = !!compiler.webpack;
39+
this.fs = isWebpack5 ? compiler.outputFileSystem : require('fs');
3840
callback = callback || (() => {});
3941

4042
const actions = [];
@@ -72,15 +74,18 @@ class BundleAnalyzerPlugin {
7274
};
7375

7476
if (compiler.hooks) {
75-
compiler.hooks.done.tapAsync('webpack-bundle-analyzer', done);
77+
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
78+
this.logger = compilation.getLogger(PLUGIN_NAME);
79+
});
80+
compiler.hooks.done.tapAsync(PLUGIN_NAME, done);
7681
} else {
7782
compiler.plugin('done', done);
7883
}
7984
}
8085

8186
async generateStatsFile(stats) {
8287
const statsFilepath = path.resolve(this.compiler.outputPath, this.opts.statsFilename);
83-
await fs.promises.mkdir(path.dirname(statsFilepath), {recursive: true});
88+
await this.fs.promises.mkdir(path.dirname(statsFilepath), {recursive: true});
8489

8590
try {
8691
await writeStats(stats, statsFilepath);
@@ -117,7 +122,8 @@ class BundleAnalyzerPlugin {
117122
reportFilename: path.resolve(this.compiler.outputPath, this.opts.reportFilename || 'report.json'),
118123
bundleDir: this.getBundleDirFromCompiler(),
119124
logger: this.logger,
120-
excludeAssets: this.opts.excludeAssets
125+
excludeAssets: this.opts.excludeAssets,
126+
fs: this.fs
121127
});
122128
}
123129

@@ -129,7 +135,8 @@ class BundleAnalyzerPlugin {
129135
bundleDir: this.getBundleDirFromCompiler(),
130136
logger: this.logger,
131137
defaultSizes: this.opts.defaultSizes,
132-
excludeAssets: this.opts.excludeAssets
138+
excludeAssets: this.opts.excludeAssets,
139+
fs: this.fs
133140
});
134141
}
135142

src/bin/analyzer.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const {resolve, dirname} = require('path');
44

55
const commander = require('commander');
66
const {magenta} = require('chalk');
7+
const fs = require('fs');
78

89
const analyzer = require('../analyzer');
910
const viewer = require('../viewer');
@@ -138,14 +139,16 @@ if (mode === 'server') {
138139
defaultSizes,
139140
bundleDir,
140141
excludeAssets,
141-
logger: new Logger(logLevel)
142+
logger: new Logger(logLevel),
143+
fs
142144
});
143145
} else if (mode === 'json') {
144146
viewer.generateJSONReport(bundleStats, {
145147
reportFilename: resolve(reportFilename || 'report.json'),
146148
bundleDir,
147149
excludeAssets,
148-
logger: new Logger(logLevel)
150+
logger: new Logger(logLevel),
151+
fs
149152
});
150153
}
151154

src/viewer.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const path = require('path');
2-
const fs = require('fs');
32
const http = require('http');
43

54
const WebSocket = require('ws');
@@ -22,6 +21,14 @@ function resolveTitle(reportTitle) {
2221
}
2322
}
2423

24+
function writeToFs(fs, dest, data) {
25+
// older version webpack uses memory-fs whose mkdirSync does not support {recursive: true}
26+
fs.mkdirpSync
27+
? fs.mkdirpSync(path.dirname(dest))
28+
: fs.mkdirSync(path.dirname(dest), {recursive: true});
29+
fs.writeFileSync(dest, data);
30+
}
31+
2532
module.exports = {
2633
startServer,
2734
generateReport,
@@ -129,7 +136,8 @@ async function generateReport(bundleStats, opts) {
129136
bundleDir = null,
130137
logger = new Logger(),
131138
defaultSizes = 'parsed',
132-
excludeAssets = null
139+
excludeAssets = null,
140+
fs
133141
} = opts || {};
134142

135143
const chartData = getChartData({logger, excludeAssets}, bundleStats, bundleDir);
@@ -145,8 +153,7 @@ async function generateReport(bundleStats, opts) {
145153
});
146154
const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename);
147155

148-
fs.mkdirSync(path.dirname(reportFilepath), {recursive: true});
149-
fs.writeFileSync(reportFilepath, reportHtml);
156+
writeToFs(fs, reportFilepath, reportHtml);
150157

151158
logger.info(`${bold('Webpack Bundle Analyzer')} saved report to ${bold(reportFilepath)}`);
152159

@@ -156,14 +163,13 @@ async function generateReport(bundleStats, opts) {
156163
}
157164

158165
async function generateJSONReport(bundleStats, opts) {
159-
const {reportFilename, bundleDir = null, logger = new Logger(), excludeAssets = null} = opts || {};
166+
const {reportFilename, bundleDir = null, logger = new Logger(), excludeAssets = null, fs} = opts || {};
160167

161168
const chartData = getChartData({logger, excludeAssets}, bundleStats, bundleDir);
162169

163170
if (!chartData) return;
164171

165-
await fs.promises.mkdir(path.dirname(reportFilename), {recursive: true});
166-
await fs.promises.writeFile(reportFilename, JSON.stringify(chartData));
172+
writeToFs(fs, reportFilename, JSON.stringify(chartData));
167173

168174
logger.info(`${bold('Webpack Bundle Analyzer')} saved JSON report to ${bold(reportFilename)}`);
169175
}

test/dev-server.js

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,58 @@
11
const fs = require('fs');
2-
const {spawn} = require('child_process');
3-
4-
const del = require('del');
5-
62
const ROOT = `${__dirname}/dev-server`;
73
const WEBPACK_CONFIG_PATH = `${ROOT}/webpack.config.js`;
84
const webpackConfig = require(WEBPACK_CONFIG_PATH);
5+
const DevServer = require('webpack-dev-server');
6+
const webpack = require('webpack');
97

108
describe('Webpack Dev Server', function () {
11-
beforeAll(deleteOutputDirectory);
12-
afterEach(deleteOutputDirectory);
13-
14-
const timeout = 15000;
15-
jest.setTimeout(timeout);
16-
17-
it('should save report file to the output directory', function (done) {
18-
const startedAt = Date.now();
19-
20-
const devServer = spawn(`${__dirname}/../node_modules/.bin/webpack-dev-server`, ['--config', WEBPACK_CONFIG_PATH], {
21-
cwd: ROOT
9+
it('should save report file to memory file system when writeToDisk is empty', async function () {
10+
expect.assertions(2);
11+
const compiler = webpack(webpackConfig);
12+
const devServer = await new Promise((resolve) => {
13+
const devServerOptions = {host: '127.0.0.1', port: 8080};
14+
const devServer = new DevServer(compiler, devServerOptions);
15+
devServer.listen(devServerOptions.port, devServerOptions.host, () => {
16+
resolve(devServer);
17+
});
18+
});
19+
await new Promise((resolve) => {
20+
compiler.hooks.afterDone.tap('webpack-bundle-analyzer', resolve);
21+
});
22+
const path = `${webpackConfig.output.path}/report.html`;
23+
expect(compiler.outputFileSystem.existsSync(path)).toBeTruthy();
24+
expect(fs.existsSync(path)).toBeFalsy();
25+
compiler.outputFileSystem.unlinkSync(path);
26+
await new Promise((resolve) => {
27+
devServer.close(() => {
28+
resolve();
29+
});
2230
});
2331

24-
const reportCheckIntervalId = setInterval(() => {
25-
if (fs.existsSync(`${webpackConfig.output.path}/report.html`)) {
26-
finish();
27-
} else if (Date.now() - startedAt > timeout - 1000) {
28-
finish(`report file wasn't found in "${webpackConfig.output.path}" directory`);
29-
}
30-
}, 300);
32+
});
3133

32-
function finish(errorMessage) {
33-
clearInterval(reportCheckIntervalId);
34-
devServer.kill();
35-
done(errorMessage ? new Error(errorMessage) : null);
36-
}
34+
it.skip('should save report file to the output directory when writeToDisk is true', async function () {
35+
expect.assertions(2);
36+
const compiler = webpack(webpackConfig);
37+
const devServer = await new Promise((resolve) => {
38+
const devServerOptions = {host: '127.0.0.1', port: 8080, writeToDisk: true};
39+
const devServer = new DevServer(compiler, devServerOptions);
40+
devServer.listen(devServerOptions.port, devServerOptions.host, () => {
41+
resolve(devServer);
42+
});
43+
});
44+
await new Promise((resolve) => {
45+
compiler.hooks.afterDone.tap('webpack-bundle-analyzer', resolve);
46+
});
47+
const path = `${webpackConfig.output.path}/report.html`;
48+
expect(compiler.outputFileSystem.existsSync(path)).toBeTruthy();
49+
expect(fs.existsSync(path)).toBeTruthy();
50+
compiler.outputFileSystem.unlinkSync(path);
51+
return await new Promise((resolve) => {
52+
devServer.close(() => {
53+
resolve();
54+
});
55+
});
3756
});
3857
});
3958

40-
function deleteOutputDirectory() {
41-
del.sync(webpackConfig.output.path);
42-
}

0 commit comments

Comments
 (0)