Skip to content

Commit

Permalink
fix: plugin uses infrastructureLogger and outputs the report.html to …
Browse files Browse the repository at this point in the history
…compiler.outputFileSystem
  • Loading branch information
wood1986 committed Oct 13, 2021
1 parent 8dce252 commit e343d8a
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 44 deletions.
17 changes: 12 additions & 5 deletions src/BundleAnalyzerPlugin.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
const fs = require('fs');
const path = require('path');
const {bold} = require('chalk');

const Logger = require('./Logger');
const viewer = require('./viewer');
const utils = require('./utils');
const {writeStats} = require('./statsUtils');
const PLUGIN_NAME = 'webpack-bundle-analyzer';

class BundleAnalyzerPlugin {
constructor(opts = {}) {
Expand Down Expand Up @@ -35,6 +35,8 @@ class BundleAnalyzerPlugin {
this.compiler = compiler;

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

const actions = [];
Expand Down Expand Up @@ -72,15 +74,18 @@ class BundleAnalyzerPlugin {
};

if (compiler.hooks) {
compiler.hooks.done.tapAsync('webpack-bundle-analyzer', done);
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
this.logger = compilation.getLogger(PLUGIN_NAME);
});
compiler.hooks.done.tapAsync(PLUGIN_NAME, done);
} else {
compiler.plugin('done', done);
}
}

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

try {
await writeStats(stats, statsFilepath);
Expand Down Expand Up @@ -117,7 +122,8 @@ class BundleAnalyzerPlugin {
reportFilename: path.resolve(this.compiler.outputPath, this.opts.reportFilename || 'report.json'),
bundleDir: this.getBundleDirFromCompiler(),
logger: this.logger,
excludeAssets: this.opts.excludeAssets
excludeAssets: this.opts.excludeAssets,
fs: this.fs
});
}

Expand All @@ -129,7 +135,8 @@ class BundleAnalyzerPlugin {
bundleDir: this.getBundleDirFromCompiler(),
logger: this.logger,
defaultSizes: this.opts.defaultSizes,
excludeAssets: this.opts.excludeAssets
excludeAssets: this.opts.excludeAssets,
fs: this.fs
});
}

Expand Down
7 changes: 5 additions & 2 deletions src/bin/analyzer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const {resolve, dirname} = require('path');

const commander = require('commander');
const {magenta} = require('chalk');
const fs = require('fs');

const analyzer = require('../analyzer');
const viewer = require('../viewer');
Expand Down Expand Up @@ -138,14 +139,16 @@ if (mode === 'server') {
defaultSizes,
bundleDir,
excludeAssets,
logger: new Logger(logLevel)
logger: new Logger(logLevel),
fs
});
} else if (mode === 'json') {
viewer.generateJSONReport(bundleStats, {
reportFilename: resolve(reportFilename || 'report.json'),
bundleDir,
excludeAssets,
logger: new Logger(logLevel)
logger: new Logger(logLevel),
fs
});
}

Expand Down
20 changes: 13 additions & 7 deletions src/viewer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const path = require('path');
const fs = require('fs');
const http = require('http');

const WebSocket = require('ws');
Expand All @@ -22,6 +21,14 @@ function resolveTitle(reportTitle) {
}
}

function writeToFs(fs, dest, data) {
// older version webpack uses memory-fs whose mkdirSync does not support {recursive: true}
fs.mkdirpSync
? fs.mkdirpSync(path.dirname(dest))
: fs.mkdirSync(path.dirname(dest), {recursive: true});
fs.writeFileSync(dest, data);
}

module.exports = {
startServer,
generateReport,
Expand Down Expand Up @@ -129,7 +136,8 @@ async function generateReport(bundleStats, opts) {
bundleDir = null,
logger = new Logger(),
defaultSizes = 'parsed',
excludeAssets = null
excludeAssets = null,
fs
} = opts || {};

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

fs.mkdirSync(path.dirname(reportFilepath), {recursive: true});
fs.writeFileSync(reportFilepath, reportHtml);
writeToFs(fs, reportFilepath, reportHtml);

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

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

async function generateJSONReport(bundleStats, opts) {
const {reportFilename, bundleDir = null, logger = new Logger(), excludeAssets = null} = opts || {};
const {reportFilename, bundleDir = null, logger = new Logger(), excludeAssets = null, fs} = opts || {};

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

if (!chartData) return;

await fs.promises.mkdir(path.dirname(reportFilename), {recursive: true});
await fs.promises.writeFile(reportFilename, JSON.stringify(chartData));
writeToFs(fs, reportFilename, JSON.stringify(chartData));

logger.info(`${bold('Webpack Bundle Analyzer')} saved JSON report to ${bold(reportFilename)}`);
}
Expand Down
76 changes: 46 additions & 30 deletions test/dev-server.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,58 @@
const fs = require('fs');
const {spawn} = require('child_process');

const del = require('del');

const ROOT = `${__dirname}/dev-server`;
const WEBPACK_CONFIG_PATH = `${ROOT}/webpack.config.js`;
const webpackConfig = require(WEBPACK_CONFIG_PATH);
const DevServer = require('webpack-dev-server');
const webpack = require('webpack');

describe('Webpack Dev Server', function () {
beforeAll(deleteOutputDirectory);
afterEach(deleteOutputDirectory);

const timeout = 15000;
jest.setTimeout(timeout);

it('should save report file to the output directory', function (done) {
const startedAt = Date.now();

const devServer = spawn(`${__dirname}/../node_modules/.bin/webpack-dev-server`, ['--config', WEBPACK_CONFIG_PATH], {
cwd: ROOT
it('should save report file to memory file system when writeToDisk is empty', async function () {
expect.assertions(2);
const compiler = webpack(webpackConfig);
const devServer = await new Promise((resolve) => {
const devServerOptions = {host: '127.0.0.1', port: 8080};
const devServer = new DevServer(compiler, devServerOptions);
devServer.listen(devServerOptions.port, devServerOptions.host, () => {
resolve(devServer);
});
});
await new Promise((resolve) => {
compiler.hooks.afterDone.tap('webpack-bundle-analyzer', resolve);
});
const path = `${webpackConfig.output.path}/report.html`;
expect(compiler.outputFileSystem.existsSync(path)).toBeTruthy();
expect(fs.existsSync(path)).toBeFalsy();
compiler.outputFileSystem.unlinkSync(path);
await new Promise((resolve) => {
devServer.close(() => {
resolve();
});
});

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

function finish(errorMessage) {
clearInterval(reportCheckIntervalId);
devServer.kill();
done(errorMessage ? new Error(errorMessage) : null);
}
it.skip('should save report file to the output directory when writeToDisk is true', async function () {
expect.assertions(2);
const compiler = webpack(webpackConfig);
const devServer = await new Promise((resolve) => {
const devServerOptions = {host: '127.0.0.1', port: 8080, writeToDisk: true};
const devServer = new DevServer(compiler, devServerOptions);
devServer.listen(devServerOptions.port, devServerOptions.host, () => {
resolve(devServer);
});
});
await new Promise((resolve) => {
compiler.hooks.afterDone.tap('webpack-bundle-analyzer', resolve);
});
const path = `${webpackConfig.output.path}/report.html`;
expect(compiler.outputFileSystem.existsSync(path)).toBeTruthy();
expect(fs.existsSync(path)).toBeTruthy();
compiler.outputFileSystem.unlinkSync(path);
return await new Promise((resolve) => {
devServer.close(() => {
resolve();
});
});
});
});

function deleteOutputDirectory() {
del.sync(webpackConfig.output.path);
}

0 comments on commit e343d8a

Please sign in to comment.