webpack-bundle-analyzer-sunburst
Version:
Webpack plugin and CLI utility that represents bundle content either as an interactive zoomable treemap or a sunburst chart
137 lines (107 loc) • 3.4 kB
JavaScript
const path = require('path');
const fs = require('fs');
const _ = require('lodash');
const express = require('express');
const ejs = require('ejs');
const opener = require('opener');
const mkdir = require('mkdirp');
const { bold } = require('chalk');
const Logger = require('./Logger');
const analyzer = require('./analyzer');
const projectRoot = path.resolve(__dirname, '..');
module.exports = {
startServer,
generateReport,
// deprecated
start: startServer
};
function startServer(bundleStats, opts) {
const {
port = 8888,
openBrowser = true,
bundleDir = null,
logger = new Logger()
} = opts || {};
const chartData = getChartData(logger, bundleStats, bundleDir);
if (!chartData) return;
const app = express();
// Explicitly using our `ejs` dependency to render templates
// Fixes #17
app.engine('ejs', require('ejs').renderFile);
app.set('view engine', 'ejs');
app.set('views', `${projectRoot}/views`);
app.use(express.static(`${projectRoot}/public`));
app.use('/', (req, res) => {
res.render('viewer', {
mode: 'server',
reportType: opts.reportType,
chartData: JSON.stringify(chartData)
});
});
return app.listen(port, () => {
const url = `http://localhost:${port}`;
logger.info(
`${bold('Webpack Bundle Analyzer')} is started at ${bold(url)}\n` +
`Use ${bold('Ctrl+C')} to close it`
);
if (openBrowser) {
opener(url);
}
});
}
function generateReport(bundleStats, opts) {
const {
openBrowser = true,
reportFilename = 'report.html',
bundleDir = null,
logger = new Logger()
} = opts || {};
const chartData = getChartData(logger, bundleStats, bundleDir);
if (!chartData) return;
chartData.forEach((data, index) => {
const bundleFilename = data && data.label && data.label.split('/').slice(-1)[0];
const bundleName = (bundleFilename && bundleFilename.split(/\.js$/)[0]) || `bundle-${index}`;
const filename = chartData.length > 1 ? `${reportFilename.split(/\.html$/)[0]}-${bundleName}.html` : reportFilename;
ejs.renderFile(
`${projectRoot}/views/viewer.ejs`,
{
mode: 'static',
chartData: JSON.stringify([ data ]),
assetContent: getAssetContent,
reportType: opts.reportType
},
(err, reportHtml) => {
if (err) return logger.error(err);
let reportFilepath = filename;
if (!path.isAbsolute(reportFilepath)) {
reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilepath);
}
mkdir.sync(path.dirname(reportFilepath));
fs.writeFileSync(reportFilepath, reportHtml);
logger.info(
`${bold('Webpack Bundle Analyzer')} saved report to ${bold(reportFilepath)}`
);
if (openBrowser) {
opener(`file://${reportFilepath}`);
}
}
);
});
}
function getAssetContent(filename) {
return fs.readFileSync(`${projectRoot}/public/${filename}`, 'utf8');
}
function getChartData(logger, ...args) {
let chartData;
try {
chartData = analyzer.getViewerData(...args, { logger });
} catch (err) {
logger.error(`Could't analyze webpack bundle:\n${err}`);
chartData = null;
}
if (_.isEmpty(chartData)) {
logger.error("Could't find any javascript bundles in provided stats file");
chartData = null;
}
return chartData;
}