/
viewer.js
138 lines (111 loc) · 3.05 KB
/
viewer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
const path = require('path');
const fs = require('fs');
const http = require('http');
const WebSocket = require('ws');
const express = require('express');
const ejs = require('ejs');
const opener = require('opener');
const mkdir = require('mkdirp');
const { bold } = require('chalk');
const reporterRoot = path.resolve(__dirname, '..', 'reporter');
module.exports = {
startServer,
generateReport
};
async function startServer(chartData, opts) {
const {
port = 8888,
host = '127.0.0.1',
openBrowser = true,
// bundleDir = null,
logger,
defaultSizes = 'parsed'
} = opts || {};
if (!logger) {
throw new Error('opts.logger is missing');
}
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', `${reporterRoot}/views`);
app.use(express.static(`${reporterRoot}/public`));
app.use('/', (req, res) => {
res.render('viewer', {
mode: 'server',
get chartData() { return JSON.stringify(chartData) },
defaultSizes: JSON.stringify(defaultSizes)
});
});
const server = http.createServer(app);
await new Promise(resolve => {
server.listen(port, host, () => {
resolve();
const url = `http://${host}:${port}`;
logger.info(
`${bold('Webpack Bundle Analyzer')} is started at ${bold(url)}\n` +
`Use ${bold('Ctrl+C')} to close it`
);
if (openBrowser) {
opener(url);
}
});
});
const wss = new WebSocket.Server({ server });
return {
ws: wss,
http: server,
updateChartData
};
function updateChartData(newChartData) {
if (!newChartData) return;
chartData = newChartData;
wss.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
event: 'chartDataUpdated',
data: newChartData
}));
}
});
}
}
function generateReport(chartData, opts) {
const {
openBrowser = true,
reportFilename = 'report.html',
bundleDir = null,
logger,
defaultSizes = 'parsed'
} = opts || {};
if (!logger) {
throw new Error('opts.logger is missing');
}
if (!chartData) return;
ejs.renderFile(
`${reporterRoot}/views/viewer.ejs`,
{
mode: 'static',
chartData: JSON.stringify(chartData),
assetContent: getAssetContent,
defaultSizes: JSON.stringify(defaultSizes)
},
(err, reportHtml) => {
if (err) return logger.error(err);
const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename);
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(`${reporterRoot}/public/${filename}`, 'utf8');
}