Skip to content

Commit

Permalink
fix: issue with caching page results in production mode
Browse files Browse the repository at this point in the history
  • Loading branch information
DylanPiercey committed Oct 19, 2022
1 parent 19c9c61 commit 966bc8e
Show file tree
Hide file tree
Showing 26 changed files with 278 additions and 198 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
Changelog
=========

# 4.0.2
- Fix issue with caching page results in production mode.

# 4.0.1
- Fix regression with the `getImageInfo` api.

Expand Down
28 changes: 9 additions & 19 deletions src/Lasso.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ const resolveFrom = require('resolve-from');
const LassoPrebuildResult = require('./LassoPrebuildResult');
const { buildPrebuildName, buildPrebuildFileName } = require('./util/prebuild.js');
const hashUtil = require('./util/hash');
const stringifyAttrs = require('./util/stringify-attrs');

/**
* Cache of prebuilds by path. If there are multiple slots for the same
Expand Down Expand Up @@ -251,10 +250,10 @@ async function doLassoPage (theLasso, options, lassoContext) {

function buildHtmlSlots (pageBundles) {
pageBundles.forEachBundle(function (bundle) {
let html,
let attrs,
url;

const htmlAttributes = bundle.getHtmlAttributes();
const bundleAttrs = bundle.getHtmlAttributes();

if (bundle.isInline()) {
if (fingerprintInlineCode) {
Expand All @@ -274,20 +273,20 @@ async function doLassoPage (theLasso, options, lassoContext) {
url = bundle.getUrl(lassoContext);

if (bundle.isJavaScript()) {
html = theLasso.getJavaScriptDependencyHtml(url, htmlAttributes);
attrs = Object.assign({ src: url }, bundleAttrs);
} else if (bundle.isStyleSheet()) {
html = theLasso.getCSSDependencyHtml(url, htmlAttributes);
attrs = Object.assign({ href: url }, bundleAttrs);
} else if (!bundle.hasContent()) {
// ignore this bundle because contentType is "none"
return;
} else {
throw new Error('Invalid bundle content type: ' + bundle.getContentType());
}
slotTracker.addContent(bundle.getSlot(), bundle.getContentType(), html);
slotTracker.addContent(bundle.getSlot(), bundle.getContentType(), attrs);
}
});

lassoPageResult.setHtmlBySlot(slotTracker.getHtmlBySlot());
lassoPageResult.setSlotsByName(slotTracker.getSlotsByName());
lassoPageResult.setInlineCodeFingerprints(inlineCodeFingerprints);
}

Expand Down Expand Up @@ -724,14 +723,6 @@ Lasso.prototype = {
return this.config;
},

getJavaScriptDependencyHtml: function(url, attributes) {
return data => `<script${stringifyAttrs(Object.assign({ src: url }, attributes, data.externalScriptAttrs))}></script>`;
},

getCSSDependencyHtml: function(url, attributes) {
return data => `<link${stringifyAttrs(Object.assign({ rel: 'stylesheet', href: url }, attributes, data.externalStyleAttrs))}>`;
},

_resolveflags: function(options) {
const flagSet = flags.createFlagSet();

Expand Down Expand Up @@ -891,10 +882,9 @@ Lasso.prototype = {
throw new Error(`No build could be found using flags: "${flagsStr}" for file at path "${path}"`);
}

lassoPageResult = new LassoPageResult({
htmlBySlot: build.slots,
resources: build.assets
});
lassoPageResult = new LassoPageResult();
lassoPageResult.setSlotsByName(build.slots);
lassoPageResult.resources = build.resources;

prebuildToPath[path] = lassoPageResult;

Expand Down
62 changes: 27 additions & 35 deletions src/LassoPageResult.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
const extend = require('raptor-util/extend');
const toString = require('./util/to-string');
const LassoPrebuild = require('./LassoPrebuild');
const Slot = require('./Slot');
const EMPTY_OBJECT = {};
const hasOwn = Object.prototype.hasOwnProperty;

function LassoPageResult (options = {}) {
const { htmlBySlot, resources } = options;

function LassoPageResult () {
this.urlsBySlot = {};
this.urlsByContentType = {};
this.files = [];
this.infoByBundleName = {};
this.infoByAsyncBundleName = {};
this._htmlBySlot = htmlBySlot || {};
this.resources = resources || [];
this.resources = [];
this._slotsByName = {};

/**
* If Lasso is configured to fingerprint inline code for
Expand All @@ -32,10 +28,7 @@ LassoPageResult.deserialize = function (reader) {
json += data;
})
.on('end', function () {
const o = JSON.parse(json);
const lassoPageResult = new LassoPageResult();
extend(lassoPageResult, o);
resolve(lassoPageResult);
resolve(Object.assign(new LassoPageResult(), JSON.parse(json)));
})
.on('error', function (err) {
reject(err);
Expand Down Expand Up @@ -68,8 +61,8 @@ LassoPageResult.prototype = {
*/
get htmlBySlot() {
const htmlBySlot = {};
for (const slotName in this._htmlBySlot) {
if (hasOwn.call(this._htmlBySlot, slotName)) {
for (const slotName in this._slotsByName) {
if (hasOwn.call(this._slotsByName, slotName)) {
const slotHtml = this.getHtmlForSlot(slotName);
htmlBySlot[slotName] = slotHtml;
}
Expand All @@ -95,7 +88,21 @@ LassoPageResult.prototype = {
* @return {String} The HTML for the slot or an empty string if there is no HTML defined for the slot.
*/
getHtmlForSlot: function(slotName, data) {
return toString(this._htmlBySlot[slotName], data || EMPTY_OBJECT);
const slots = this._slotsByName[slotName];

if (slots) {
const slotData = data || EMPTY_OBJECT;
let html = '';
let sep = '';
for (const slot of slots) {
html += sep + Slot.render(slot, slotData);
sep = '\n';
}

return html;
}

return '';
},

getHeadHtml: function(data) {
Expand All @@ -113,23 +120,8 @@ LassoPageResult.prototype = {
return this.getHtmlForSlot(slotName, data);
},

/**
* Returns the JSON representation of the return value of {@Link #getHtmlBySlot}
* @return {String} The JSON output
*/
htmlSlotsToJSON: function(indentation) {
return JSON.stringify(this.htmlBySlot, null, indentation);
},

toJSON: function() {
const clone = extend({}, this);
// Don't include the loaded templates when generating a JSON string
delete clone._htmlTemplatesBySlot;
return clone;
},

setHtmlBySlot: function(htmlBySlot) {
this._htmlBySlot = htmlBySlot;
setSlotsByName: function(slotsByName) {
this._slotsByName = slotsByName;
},

registerBundle: function(bundle, async, lassoContext) {
Expand Down Expand Up @@ -262,12 +254,12 @@ LassoPageResult.prototype = {
},

toLassoPrebuild (name, flags) {
return new LassoPrebuild({
slots: this.htmlBySlot,
return {
slots: this._slotsByName,
assets: this.resources,
name,
flags
});
};
}
};

Expand Down
10 changes: 0 additions & 10 deletions src/LassoPrebuild.js

This file was deleted.

110 changes: 49 additions & 61 deletions src/Slot.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,5 @@
const ok = require('assert').ok;
const toString = require('./util/to-string');
const stringifyAttrs = require('./util/stringify-attrs');
const inlineBuilders = {
js: (source) => (data) => {
const scriptAttrs = data.externalScriptAttrs;
const code = toString(source, data);
let result = `<script${stringifyAttrs(data.inlineScriptAttrs)}>`;

if (scriptAttrs) {
if (scriptAttrs.async) {
result += wrapInDocumentLoaded(code, true);
} else if (scriptAttrs.defer) {
result += wrapInDocumentLoaded(code);
} else {
result += code;
}
} else {
result += code;
}

return `${result}</script>`;
},
css: (source) => (data) => {
return `<style${stringifyAttrs(data.inlineStyleAttrs)}>${toString(
source,
data
)}</style>`;
}
};

function Slot(contentType) {
ok(contentType, 'contentType is required');
Expand Down Expand Up @@ -57,46 +29,62 @@ Slot.prototype = {
inline: false,
code: content
});
},
}
};

buildHtml: function() {
const output = [];
let isTemplate = false;
for (let i = 0, len = this.content.length; i < len; i++) {
const content = this.content[i];
if (content.inline) {
const builder = inlineBuilders[this.contentType];

if (builder) {
isTemplate = true;
output.push(builder(content.code));
} else {
throw new Error("Invalid inline content type '" + this.contentType + "'.");
}
} else {
isTemplate = isTemplate || typeof content.code === 'function';
output.push(content.code);
}
Slot.render = function(slot, data) {
let html = '';
let sep = '';

for (const content of slot.content) {
html += sep;
sep = '\n';

switch (slot.contentType) {
case 'js':
html += (content.inline ? inlineScript : externalScript)(content.code, data);
break;
case 'css':
html += (content.inline ? inlineStyle : externalStyle)(content.code, data);
break;
default:
throw new Error('Invalid content type: ' + slot.contentType);
}
}

if (isTemplate) {
return data => {
let result = '';
for (let i = 0; i < output.length; i++) {
if (i !== 0) {
result += '\n';
}
return html;
};

result += toString(output[i], data);
}
function inlineScript(content, data) {
const scriptAttrs = data.externalScriptAttrs;
let result = `<script${stringifyAttrs(data.inlineScriptAttrs)}>`;

return result;
};
if (scriptAttrs) {
if (scriptAttrs.async) {
result += wrapInDocumentLoaded(content, true);
} else if (scriptAttrs.defer) {
result += wrapInDocumentLoaded(content);
} else {
result += content;
}

return output.join('\n');
} else {
result += content;
}
};

return `${result}</script>`;
}

function inlineStyle(content, data) {
return `<style${stringifyAttrs(data.inlineStyleAttrs)}>${content}</style>`;
}

function externalScript(attrs, data) {
return `<script${stringifyAttrs(Object.assign({}, attrs, data.externalScriptAttrs))}></script>`;
}

function externalStyle(attrs, data) {
return `<link${stringifyAttrs(Object.assign({ rel: 'stylesheet' }, attrs, data.externalStyleAttrs))}>`;
}

function wrapInDocumentLoaded(code, isAsync) {
return (
Expand Down
Loading

0 comments on commit 966bc8e

Please sign in to comment.