UNPKG

4.75 kBJavaScriptView Raw
1"use strict";
2
3const path = require('path');
4
5const fs = require('fs');
6
7const http = require('http');
8
9const WebSocket = require('ws');
10
11const sirv = require('sirv');
12
13const _ = require('lodash');
14
15const {
16 bold
17} = require('chalk');
18
19const Logger = require('./Logger');
20
21const analyzer = require('./analyzer');
22
23const {
24 open
25} = require('./utils');
26
27const {
28 renderViewer
29} = require('./template');
30
31const projectRoot = path.resolve(__dirname, '..');
32
33function resolveTitle(reportTitle) {
34 if (typeof reportTitle === 'function') {
35 return reportTitle();
36 } else {
37 return reportTitle;
38 }
39}
40
41module.exports = {
42 startServer,
43 generateReport,
44 generateJSONReport,
45 // deprecated
46 start: startServer
47};
48
49async function startServer(bundleStats, opts) {
50 const {
51 port = 8888,
52 host = '127.0.0.1',
53 openBrowser = true,
54 bundleDir = null,
55 logger = new Logger(),
56 defaultSizes = 'parsed',
57 excludeAssets = null,
58 reportTitle
59 } = opts || {};
60 const analyzerOpts = {
61 logger,
62 excludeAssets
63 };
64 let chartData = getChartData(analyzerOpts, bundleStats, bundleDir);
65 if (!chartData) return;
66 const sirvMiddleware = sirv(`${projectRoot}/public`, {
67 // disables caching and traverse the file system on every request
68 dev: true
69 });
70 const server = http.createServer((req, res) => {
71 if (req.method === 'GET' && req.url === '/') {
72 const html = renderViewer({
73 mode: 'server',
74 title: resolveTitle(reportTitle),
75 chartData,
76 defaultSizes,
77 enableWebSocket: true
78 });
79 res.writeHead(200, {
80 'Content-Type': 'text/html'
81 });
82 res.end(html);
83 } else {
84 sirvMiddleware(req, res);
85 }
86 });
87 await new Promise(resolve => {
88 server.listen(port, host, () => {
89 resolve();
90 const url = `http://${host}:${server.address().port}`;
91 logger.info(`${bold('Webpack Bundle Analyzer')} is started at ${bold(url)}\n` + `Use ${bold('Ctrl+C')} to close it`);
92
93 if (openBrowser) {
94 open(url, logger);
95 }
96 });
97 });
98 const wss = new WebSocket.Server({
99 server
100 });
101 wss.on('connection', ws => {
102 ws.on('error', err => {
103 // Ignore network errors like `ECONNRESET`, `EPIPE`, etc.
104 if (err.errno) return;
105 logger.info(err.message);
106 });
107 });
108 return {
109 ws: wss,
110 http: server,
111 updateChartData
112 };
113
114 function updateChartData(bundleStats) {
115 const newChartData = getChartData(analyzerOpts, bundleStats, bundleDir);
116 if (!newChartData) return;
117 chartData = newChartData;
118 wss.clients.forEach(client => {
119 if (client.readyState === WebSocket.OPEN) {
120 client.send(JSON.stringify({
121 event: 'chartDataUpdated',
122 data: newChartData
123 }));
124 }
125 });
126 }
127}
128
129async function generateReport(bundleStats, opts) {
130 const {
131 openBrowser = true,
132 reportFilename,
133 reportTitle,
134 bundleDir = null,
135 logger = new Logger(),
136 defaultSizes = 'parsed',
137 excludeAssets = null
138 } = opts || {};
139 const chartData = getChartData({
140 logger,
141 excludeAssets
142 }, bundleStats, bundleDir);
143 if (!chartData) return;
144 const reportHtml = renderViewer({
145 mode: 'static',
146 title: resolveTitle(reportTitle),
147 chartData,
148 defaultSizes,
149 enableWebSocket: false
150 });
151 const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename);
152 fs.mkdirSync(path.dirname(reportFilepath), {
153 recursive: true
154 });
155 fs.writeFileSync(reportFilepath, reportHtml);
156 logger.info(`${bold('Webpack Bundle Analyzer')} saved report to ${bold(reportFilepath)}`);
157
158 if (openBrowser) {
159 open(`file://${reportFilepath}`, logger);
160 }
161}
162
163async function generateJSONReport(bundleStats, opts) {
164 const {
165 reportFilename,
166 bundleDir = null,
167 logger = new Logger(),
168 excludeAssets = null
169 } = opts || {};
170 const chartData = getChartData({
171 logger,
172 excludeAssets
173 }, bundleStats, bundleDir);
174 if (!chartData) return;
175 await fs.promises.mkdir(path.dirname(reportFilename), {
176 recursive: true
177 });
178 await fs.promises.writeFile(reportFilename, JSON.stringify(chartData));
179 logger.info(`${bold('Webpack Bundle Analyzer')} saved JSON report to ${bold(reportFilename)}`);
180}
181
182function getChartData(analyzerOpts, ...args) {
183 let chartData;
184 const {
185 logger
186 } = analyzerOpts;
187
188 try {
189 chartData = analyzer.getViewerData(...args, analyzerOpts);
190 } catch (err) {
191 logger.error(`Could't analyze webpack bundle:\n${err}`);
192 logger.debug(err.stack);
193 chartData = null;
194 }
195
196 if (_.isPlainObject(chartData) && _.isEmpty(chartData)) {
197 logger.error("Could't find any javascript bundles in provided stats file");
198 chartData = null;
199 }
200
201 return chartData;
202}
\No newline at end of file