New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace ejs templates with a simple js file #397
Changes from 3 commits
d44be8f
67e79b8
2b41272
4c948e9
11e4db1
084cc02
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,65 @@ | ||
<!DOCTYPE html> | ||
/* 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 `<script>` tag. | ||
*/ | ||
function escapeJson(json) { | ||
return JSON.stringify(json).replace(/</gu, '\\u003c'); | ||
} | ||
|
||
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'); | ||
} | ||
|
||
function html(strings, ...values) { | ||
return strings.map((string, index) => `${string}${values[index] || ''}`).join(''); | ||
} | ||
|
||
function getScript(filename, mode) { | ||
if (mode === 'static') { | ||
return `<!-- ${_.escape(filename)} --> | ||
<script>${getAssetContent(filename)}</script>`; | ||
} else { | ||
return `<script src="${_.escape(filename)}"></script>`; | ||
} | ||
} | ||
|
||
function renderViewer({title, enableWebSocket, chartData, defaultSizes, mode} = {}) { | ||
return html`<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="UTF-8"/> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"/> | ||
<title><%= title %></title> | ||
<title>${_.escape(title)}</title> | ||
<link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAABrVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+O1foceMD///+J0/qK1Pr7/v8Xdr/9///W8P4UdL7L7P0Scr2r4Pyj3vwad8D5/f/2/f+55f3E6f34+/2H0/ojfMKpzOd0rNgQcb3F3O/j9f7c8v6g3Pz0/P/w+v/q+P7n9v6T1/uQ1vuE0vqLut/y+v+Z2fvt+f+15Pzv9fuc2/vR7v2V2Pvd6/bg9P7I6/285/2y4/yp3/zp8vk8i8kqgMT7/P31+fyv4vxGkcz6/P6/6P3j7vfS5PNnpNUxhcbO7f7F6v3O4vHK3/DA2u631Ouy0eqXweKJud5wqthfoNMMbLvY8f73+v2dxeR8sNtTmdDx9/zX6PSjyeaCtd1YnNGX2PuQveCGt95Nls42h8dLlM3F4vBtAAAAM3RSTlMAAyOx0/sKBvik8opWGBMOAe3l1snDm2E9LSb06eHcu5JpHbarfHZCN9CBb08zzkdNS0kYaptYAAAFV0lEQVRYw92X51/aYBDHHS2O2qqttVbrqNq9m+TJIAYIShBkWwqIiCgoWvfeq7Z2/s29hyQNyUcR7LveGwVyXy6XH8/9rqxglLfUPLxVduUor3h0rfp2TYvpivk37929TkG037hffoX0+peVtZQc1589rigVUdXS/ABSAyEmGIO/1XfvldSK8vs3OqB6u3m0nxmIrvgB0dj7rr7Y9IbuF68hnfFaiHA/sxqm0wciIG43P60qKv9WXWc1RXGh/mFESFABTSBi0sNAKzqet17eCtOb3kZIDwxEEU0oAIJGYxNBDhBND29e0rtXXbcpuPmED9IhEAAQ/AXEaF8EPmnrrKsv0LvWR3fg5sWDNAFZOgAgaKvZDogHNU9MFwnnYROkc56RD5CjAbQX9Ow4g7upCsvYu55aSI/Nj0H1akgKQEUM94dwK65hYRmFU9MIcH/fqJYOZYcnuJSU/waKDgTOEVaVKhwrTRP5XzgSpAITYzom7UvkhFX5VutmxeNnWDjjswTKTyfgluNDGbUpWissXhF3s7mlSml+czWkg3D0l1nNjGNjz3myOQOa1KM/jOS6ebdbAVTCi4gljHSFrviza7tOgRWcS0MOUX9zdNgag5w7rRqA44Lzw0hr1WqES36dFliSJFlh2rXIae3FFcDDgKdxrUIDePr8jGcSClV1u7A9xeN0ModY/pHMxmR1EzRh8TJiwqsHmKW0l4FCEZI+jHio+JdPPE9qwQtTRxku2D8sIeRL2LnxWSllANCQGOIiqVHAz2ye2JR0DcH+HoxDkaADLjgxjKQ+AwCX/g0+DNgdG0ukYCONAe+dbc2IAc6fwt1ARoDSezNHxV2Cmzwv3O6lDMV55edBGwGK9n1+x2F8EDfAGCxug8MhpsMEcTEAWf3rx2vZhe/LAmtIn/6apE6PN0ULKgywD9mmdxbmFl3OvD5AS5fW5zLbv/YHmcsBTjf/afDz3MaZTVCfAP9z6/Bw6ycv8EUBWJIn9zYcoAWWlW9+OzO3vkTy8H+RANLmdrpOuYWdZYEXpo+TlCJrW5EARb7fF+bWdqf3hhyZI1nWJQHgznErZhbjoEsWqi8dQNoE294aldzFurwSABL2XXMf9+H1VQGke9exw5P/AnA5Pv5ngMul7LOvO922iwACu8WkCwLCafvM4CeWPxfA8lNHcWZSoi8EwMAIciKX2Z4SWCMAa3snCZ/G4EA8D6CMLNFsGQhkkz/gQNEBbPCbWsxGUpYVu3z8IyNAknwJkfPMEhLyrdi5RTyUVACkw4GSFRNWJNEW+fgPGwHD8/JxnRuLabN4CGNRkAE23na2+VmEAUmrYymSGjMAYqH84YUIyzgzs3XC7gNgH36Vcc4zKY9o9fgPBXUAiHHwVboBHGLiX6Zcjp1f2wu4tvzZKo0ecPnDtQYDQvJXaBeNzce45Fp28ZQLrEZVuFqgBwOalArKXnW1UzlnSusQKJqKYNuz4tOnI6sZG4zanpemv+7ySU2jbA9h6uhcgpfy6G2PahirDZ6zvq6zDduMVFTKvzw8wgyEdelwY9in3XkEPs3osJuwRQ4qTkfzifndg9Gfc4pdsu82+tTnHZTBa2EAMrqr2t43pguc8tNm7JQVQ2S0ukj2d22dhXYP0/veWtwKrCkNoNimAN5+Xr/oLrxswKbVJjteWrX7eR63o4j9q0GxnaBdWgGA5VStpanIjQmEhV0/nVt5VOFUvix6awJhPcAaTEShgrG+iGyvb5a0Ndb1YGHFPEwoqAinoaykaID1o1pdPNu7XsnCKQ3R+hwWIIhGvORcJUBYXe3Xa3vq/mF/N9V13ugufMkfXn+KHsRD0B8AAAAASUVORK5CYII=" type="image/x-icon" /> | ||
|
||
<script> | ||
window.enableWebSocket = <%- escapeJson(enableWebSocket) %>; | ||
window.enableWebSocket = ${escapeJson(enableWebSocket)}; | ||
</script> | ||
<%- include('script', { filename: 'viewer.js' }) %> | ||
${getScript('viewer.js', mode)} | ||
</head> | ||
|
||
<body> | ||
<div id="app"></div> | ||
<script> | ||
window.chartData = <%- escapeJson(chartData) %>; | ||
window.defaultSizes = <%- escapeJson(defaultSizes) %>; | ||
window.chartData = ${escapeJson(chartData)}; | ||
window.defaultSizes = ${escapeJson(defaultSizes)}; | ||
</script> | ||
</body> | ||
</html> | ||
</html>`; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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); | ||
} | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this line should not be here I think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right. I wonder how the tests worked with this line present 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They didn't. Travis hangs. |
||
} | ||
|
||
|
@@ -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 `<script>` tag. | ||
*/ | ||
function escapeJson(json) { | ||
return JSON.stringify(json).replace(/</gu, '\\u003c'); | ||
} | ||
|
||
function getChartData(analyzerOpts, ...args) { | ||
let chartData; | ||
const {logger} = analyzerOpts; | ||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like there is no need in promise here anymore. The code is sync
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will be a breaking change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean the function can be still async but promise wrapper around sync code is not necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yep, agree. @realityking could you change it please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed a commit to do this :)