From d44be8f8e14a5c535da90b95b14be3a7a68919ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rouven=20We=C3=9Fling?= Date: Tue, 24 Nov 2020 01:35:30 +0100 Subject: [PATCH 1/6] Replace ejs templates with a simple js file --- package-lock.json | 89 +++-------------------------- package.json | 4 +- views/viewer.ejs => src/template.js | 53 ++++++++++++++--- src/viewer.js | 86 ++++++++-------------------- views/script.ejs | 8 --- 5 files changed, 79 insertions(+), 161 deletions(-) rename views/viewer.ejs => src/template.js (69%) delete mode 100644 views/script.ejs diff --git a/package-lock.json b/package-lock.json index 036a5717..4fb435f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1985,11 +1985,6 @@ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" - }, "async-done": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", @@ -2141,7 +2136,8 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "base": { "version": "0.11.2", @@ -2290,6 +2286,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2970,7 +2967,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.2", @@ -4022,14 +4020,6 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, - "ejs": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz", - "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==", - "requires": { - "jake": "^10.6.1" - } - }, "electron": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/electron/-/electron-2.0.18.tgz", @@ -4246,7 +4236,8 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "eslint": { "version": "5.16.0", @@ -4936,14 +4927,6 @@ "dev": true, "optional": true }, - "filelist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz", - "integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==", - "requires": { - "minimatch": "^3.0.4" - } - }, "filesize": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz", @@ -6524,63 +6507,6 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, - "jake": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", - "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", - "requires": { - "async": "0.9.x", - "chalk": "^2.4.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "jest-worker": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", @@ -7228,6 +7154,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } diff --git a/package.json b/package.json index 8d53f010..59ac45f9 100644 --- a/package.json +++ b/package.json @@ -30,15 +30,13 @@ "files": [ "public", "lib", - "src", - "views" + "src" ], "dependencies": { "acorn": "^8.0.4", "acorn-walk": "^8.0.0", "chalk": "^4.1.0", "commander": "^6.2.0", - "ejs": "^3.1.5", "express": "^4.17.1", "filesize": "^6.1.0", "gzip-size": "^6.0.0", diff --git a/views/viewer.ejs b/src/template.js similarity index 69% rename from views/viewer.ejs rename to src/template.js index e9f455f1..d3981032 100644 --- a/views/viewer.ejs +++ b/src/template.js @@ -1,22 +1,61 @@ - +/* eslint-disable max-len */ +const path = require('path'); +const fs = require('fs'); + +const _ = require('lodash'); + +const projectRoot = path.resolve(__dirname, '..'); +const assetsRoot = path.join(projectRoot, 'public'); + +exports.renderViewer = renderViewer; + +/** + * Escapes `<` characters in JSON to safely use it in ``; + } else { + return ``; + } +} + +function renderViewer({title, enableWebSocket, chartData, defaultSizes, mode} = {}) { + return ` - <%= title %> + ${_.escape(title)} - <%- include('script', { filename: 'viewer.js' }) %> + ${getScript('viewer.js', mode)}
- +`; +} diff --git a/src/viewer.js b/src/viewer.js index c259eede..65af6be8 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -5,15 +5,14 @@ const http = require('http'); const WebSocket = require('ws'); const _ = require('lodash'); const express = require('express'); -const ejs = require('ejs'); const {bold} = require('chalk'); const Logger = require('./Logger'); const analyzer = require('./analyzer'); const {open} = require('./utils'); +const {renderViewer} = require('./template'); const projectRoot = path.resolve(__dirname, '..'); -const assetsRoot = path.join(projectRoot, 'public'); function resolveTitle(reportTitle) { if (typeof reportTitle === 'function') { @@ -50,24 +49,18 @@ async function startServer(bundleStats, opts) { 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', { + app.get('/', (req, res) => { + res.writeHead(200, {'Content-Type': 'text/html'}); + const html = renderViewer({ mode: 'server', title: resolveTitle(reportTitle), - get chartData() { return chartData }, + chartData, defaultSizes, - enableWebSocket: true, - // Helpers - escapeJson + enableWebSocket: true }); + return res.end(html); }); const server = http.createServer(app); @@ -140,42 +133,28 @@ async function generateReport(bundleStats, opts) { if (!chartData) return; await new Promise((resolve, reject) => { - ejs.renderFile( - `${projectRoot}/views/viewer.ejs`, - { + try { + const reportHtml = renderViewer({ mode: 'static', title: resolveTitle(reportTitle), chartData, defaultSizes, - enableWebSocket: false, - // Helpers - assetContent: getAssetContent, - escapeJson - }, - (err, reportHtml) => { - try { - if (err) { - logger.error(err); - reject(err); - return; - } - - const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename); - - fs.mkdirSync(path.dirname(reportFilepath), {recursive: true}); - fs.writeFileSync(reportFilepath, reportHtml); - - logger.info(`${bold('Webpack Bundle Analyzer')} saved report to ${bold(reportFilepath)}`); - - if (openBrowser) { - open(`file://${reportFilepath}`, logger); - } - resolve(); - } catch (e) { - reject(e); - } + enableWebSocket: false + }); + const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename); + + fs.mkdirSync(path.dirname(reportFilepath), {recursive: true}); + fs.writeFileSync(reportFilepath, reportHtml); + + logger.info(`${bold('Webpack Bundle Analyzer')} saved report to ${bold(reportFilepath)}`); + + if (openBrowser) { + open(`file://${reportFilepath}`, logger); } - ); + resolve(); + } catch (e) { + reject(e); + } }); } @@ -192,23 +171,6 @@ async function generateJSONReport(bundleStats, opts) { logger.info(`${bold('Webpack Bundle Analyzer')} saved JSON report to ${bold(reportFilename)}`); } -function getAssetContent(filename) { - const assetPath = path.join(assetsRoot, filename); - - if (!assetPath.startsWith(assetsRoot)) { - throw new Error(`"${filename}" is outside of the assets root`); - } - - return fs.readFileSync(assetPath, 'utf8'); -} - -/** - * Escapes `<` characters in JSON to safely use it in ` -<% } else { %> - -<% } %> From 67e79b85b8acccc191b84caecc91e55bc46b325b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rouven=20We=C3=9Fling?= Date: Tue, 24 Nov 2020 11:18:16 +0100 Subject: [PATCH 2/6] Add template tag for HTML to enable syntax highlighting --- src/template.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/template.js b/src/template.js index d3981032..83641b79 100644 --- a/src/template.js +++ b/src/template.js @@ -26,6 +26,10 @@ function getAssetContent(filename) { return fs.readFileSync(assetPath, 'utf8'); } +function html(strings, ...values) { + return strings.map((string, index) => `${string}${values[index] || ''}`).join('') +} + function getScript(filename, mode) { if (mode === 'static') { return ` @@ -36,7 +40,7 @@ function getScript(filename, mode) { } function renderViewer({title, enableWebSocket, chartData, defaultSizes, mode} = {}) { - return ` + return html` From 2b4127240d8efff8969636cf544e29413cb9af88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rouven=20We=C3=9Fling?= Date: Tue, 24 Nov 2020 14:27:23 +0100 Subject: [PATCH 3/6] Fix missing semicolon --- src/template.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/template.js b/src/template.js index 83641b79..4ef02634 100644 --- a/src/template.js +++ b/src/template.js @@ -27,7 +27,7 @@ function getAssetContent(filename) { } function html(strings, ...values) { - return strings.map((string, index) => `${string}${values[index] || ''}`).join('') + return strings.map((string, index) => `${string}${values[index] || ''}`).join(''); } function getScript(filename, mode) { From 4c948e996463b70180720fbc81622cdb39f15f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rouven=20We=C3=9Fling?= Date: Mon, 30 Nov 2020 12:03:46 +0100 Subject: [PATCH 4/6] Remove an unecessary promise wrapper --- src/viewer.js | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/viewer.js b/src/viewer.js index 65af6be8..2e4346e2 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -132,29 +132,23 @@ async function generateReport(bundleStats, opts) { if (!chartData) return; - await new Promise((resolve, reject) => { - try { - const reportHtml = renderViewer({ - mode: 'static', - title: resolveTitle(reportTitle), - chartData, - defaultSizes, - enableWebSocket: false - }); - const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename); - - fs.mkdirSync(path.dirname(reportFilepath), {recursive: true}); - fs.writeFileSync(reportFilepath, reportHtml); - - logger.info(`${bold('Webpack Bundle Analyzer')} saved report to ${bold(reportFilepath)}`); + const reportHtml = renderViewer({ + mode: 'static', + title: resolveTitle(reportTitle), + chartData, + defaultSizes, + enableWebSocket: false + }); + const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename); - if (openBrowser) { - open(`file://${reportFilepath}`, logger); - } - resolve(); - } catch (e) { - reject(e); - } + fs.mkdirSync(path.dirname(reportFilepath), {recursive: true}); + fs.writeFileSync(reportFilepath, reportHtml); + + logger.info(`${bold('Webpack Bundle Analyzer')} saved report to ${bold(reportFilepath)}`); + + if (openBrowser) { + open(`file://${reportFilepath}`, logger); + } }); } From 11e4db140a5364d611a15e161a484d7748acc2b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rouven=20We=C3=9Fling?= Date: Mon, 30 Nov 2020 12:16:42 +0100 Subject: [PATCH 5/6] fix syntax error --- src/viewer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/viewer.js b/src/viewer.js index 2e4346e2..82f8adad 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -149,7 +149,6 @@ async function generateReport(bundleStats, opts) { if (openBrowser) { open(`file://${reportFilepath}`, logger); } - }); } async function generateJSONReport(bundleStats, opts) { From 084cc022e0607f2713c461d6f84787b4140a3a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rouven=20We=C3=9Fling?= Date: Mon, 30 Nov 2020 14:21:36 +0100 Subject: [PATCH 6/6] Add changelog entry --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 216bf910..6d314e82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ _Note: Gaps between patch versions are faulty, broken or test releases._ ## UNRELEASED + * **Improvement** + * A number of improvements to reduce the number of dependencies ([#391](https://github.com/webpack-contrib/webpack-bundle-analyzer/pull/391), [#396](https://github.com/webpack-contrib/webpack-bundle-analyzer/pull/396), [#397](https://github.com/webpack-contrib/webpack-bundle-analyzer/pull/397)) + * **Bug Fix** * Prevent crashes for bundles generated from webpack array configs. ([#394](https://github.com/webpack-contrib/webpack-bundle-analyzer/pull/394) by [@ctavan](https://github.com/ctavan)) * Fix `non-asset` assets causing analyze failure. ([#385](https://github.com/webpack-contrib/webpack-bundle-analyzer/issues/385) by [@ZKHelloworld](https://github.com/ZKHelloworld))