emit events for unused data, and only in dev/export mode

This commit is contained in:
Rich Harris
2018-08-03 01:14:08 -04:00
parent b20e15721c
commit 18d15c0120

View File

@@ -293,6 +293,8 @@ function get_page_handler(manifest: Manifest, store_getter: (req: Req) => Store)
const { server_routes, pages } = manifest; const { server_routes, pages } = manifest;
const error_route = manifest.error; const error_route = manifest.error;
const should_wrap_data = dev() || process.env.SAPPER_EXPORT;
function handle_error(req: Req, res: ServerResponse, statusCode: number, error: Error | string) { function handle_error(req: Req, res: ServerResponse, statusCode: number, error: Error | string) {
handle_page({ handle_page({
pattern: null, pattern: null,
@@ -452,10 +454,14 @@ function get_page_handler(manifest: Manifest, store_getter: (req: Req) => Store)
} }
}); });
let { data: preloaded_proxies, unwrap } = wrap_data(preloaded); // in dev and export modes, we wrap data in proxies to see
// how much of it is used in the initial render
const wrapped = should_wrap_data && wrap_data(preloaded);
// this is an easy way to 'reify' top-level values // this is an easy way to 'reify' top-level values
const reified = preloaded_proxies.map((x: any) => x); const _preloaded = should_wrap_data
? wrapped.data.map((x: any) => x)
: preloaded;
let level = data.child; let level = data.child;
for (let i = 0; i < page.parts.length; i += 1) { for (let i = 0; i < page.parts.length; i += 1) {
@@ -468,7 +474,7 @@ function get_page_handler(manifest: Manifest, store_getter: (req: Req) => Store)
component: part.component, component: part.component,
props: Object.assign({}, props, { props: Object.assign({}, props, {
params: get_params(match) params: get_params(match)
}, reified[i + 1]) }, _preloaded[i + 1])
}); });
level.props.child = <Props["child"]>{ level.props.child = <Props["child"]>{
@@ -487,41 +493,47 @@ function get_page_handler(manifest: Manifest, store_getter: (req: Req) => Store)
.map(file => `<script src='${req.baseUrl}/client/${file}'></script>`) .map(file => `<script src='${req.baseUrl}/client/${file}'></script>`)
.join(''); .join('');
const unwrapped = unwrap(); const unwrapped = should_wrap_data && wrapped.unwrap();
const preloaded_serialized = preloaded.map((data, i) => { const preloaded_serialized = preloaded.map(try_serialize);
const all = try_serialize(data);
const used = try_serialize(unwrapped[i]);
if (all !== used) { if (should_wrap_data && process.send) {
const props = list_unused_properties(data, unwrapped[i]); const discrepancies = [];
const part = page.parts[i - 1] || { file: 'routes/_layout.html' }; unwrapped.forEach((clone, i) => {
console.log(`${part.file} is preloading more data (${prettyBytes(all.length)}) than is initially rendered (${prettyBytes(used.length)}). The following properties are unused...`); const loaded = preloaded_serialized[i];
if (!loaded) return;
const slice = props.length > 22 const rendered = try_serialize(clone);
? props.slice(0, 20)
: props;
console.log(slice.join('\n')); if (rendered !== loaded) {
const part = page.parts[i - 1];
const file = part ? part.file : '_layout.html';
if (props.length > slice.length) { discrepancies.push({
console.log(`...and ${props.length - slice.length} more`); file,
preloaded: loaded.length,
rendered: rendered.length,
props: list_unused_properties(preloaded[i], clone)
});
} }
} });
return all; if (discrepancies.length) {
}); process.send({
__sapper__: true,
event: 'unused_data',
url: req.url,
discrepancies
});
}
}
const serialized = { const serialized = {
preloaded: `[${preloaded_serialized.join(',')}]`, preloaded: `[${preloaded_serialized.join(',')}]`,
store: store && try_serialize(store.get()) store: store && try_serialize(store.get())
}; };
if (serialized.preloaded.length > 10000) {
console.log(`preloaded data is ${prettyBytes(serialized.preloaded.length)}. that's too much!`)
}
let inline_script = `__SAPPER__={${[ let inline_script = `__SAPPER__={${[
error && `error:1`, error && `error:1`,
`baseUrl:"${req.baseUrl}"`, `baseUrl:"${req.baseUrl}"`,
@@ -545,6 +557,13 @@ function get_page_handler(manifest: Manifest, store_getter: (req: Req) => Store)
res.end(body); res.end(body);
if (process.send) { if (process.send) {
process.send({
__sapper__: true,
event: 'preload',
url: req.url,
size: serialized.preloaded.length
});
process.send({ process.send({
__sapper__: true, __sapper__: true,
event: 'file', event: 'file',