Skip to content

Commit

Permalink
fix(prerender): hash assets in page.state static content
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdbradley committed Oct 19, 2020
1 parent d762c6d commit baeb842
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 25 deletions.
8 changes: 5 additions & 3 deletions src/compiler/optimize/minify-css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ const resolveStylesheetUrl = async (nodes: CssNode[], resolveUrl: (url: string)
for (let i = 0; i < urlSplt.length; i++) {
const r = /url\((.*?)\)/.exec(urlSplt[i]);
if (r) {
const orgUrl = r[1].replace(/(\'|\")/g, '');
const newUrl = await resolveUrl(orgUrl);
urlSplt[i] = urlSplt[i].replace(orgUrl, newUrl);
try {
const orgUrl = r[1].replace(/(\'|\")/g, '');
const newUrl = await resolveUrl(orgUrl);
urlSplt[i] = urlSplt[i].replace(orgUrl, newUrl);
} catch (e) {}
}
}
node.value = urlSplt.join(',');
Expand Down
81 changes: 61 additions & 20 deletions src/compiler/prerender/prerender-optimize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,21 @@ export const hashAssets = async (sys: d.CompilerSystem, diagnostics: d.Diagnosti
await hashAsset(sys, hydrateOpts, appDir, doc, currentUrl, 'script', ['src']);
await hashAsset(sys, hydrateOpts, appDir, doc, currentUrl, 'img', ['src', 'srcset']);
await hashAsset(sys, hydrateOpts, appDir, doc, currentUrl, 'picture > source', ['srcset']);

const pageStates = Array.from(doc.querySelectorAll('script[data-stencil-static="page.state"][type="application/json"]')) as HTMLScriptElement[];
if (pageStates.length > 0) {
await Promise.all(pageStates.map(async pageStateScript => {
const pageState = JSON.parse(pageStateScript.textContent);
if (pageState && Array.isArray(pageState.ast)) {
for (const node of pageState.ast) {
if (Array.isArray(node)) {
await hashPageStateAstAssets(sys, hydrateOpts, appDir, currentUrl, pageStateScript, node);
}
}
pageStateScript.textContent = JSON.stringify(pageState);
}
}));
}
}

const hashAsset = async (sys: d.CompilerSystem, hydrateOpts: d.PrerenderHydrateOptions, appDir: string, doc: Document, currentUrl: URL, selector: string, srcAttrs: string[]) => {
Expand All @@ -251,18 +266,56 @@ const hashAsset = async (sys: d.CompilerSystem, hydrateOpts: d.PrerenderHydrateO
const assetUrl = new URL(srcValue.src, currentUrl);
if (assetUrl.hostname === currentUrl.hostname) {
if (hydrateOpts.hashAssets === 'querystring' && !assetUrl.searchParams.has('v')) {
const hash = await getAssetFileHash(sys, appDir, assetUrl);
if (isString(hash)) {
assetUrl.searchParams.append('v', hash);
const attrValue = setAttrUrls(assetUrl, srcValue.descriptor);
elm.setAttribute(attrName, attrValue);
try {
const hash = await getAssetFileHash(sys, appDir, assetUrl);
if (isString(hash)) {
assetUrl.searchParams.append('v', hash);
const attrValue = setAttrUrls(assetUrl, srcValue.descriptor);
elm.setAttribute(attrName, attrValue);
}
} catch (e) {}
}
}
}
}
}
};

const hashPageStateAstAssets = async (sys: d.CompilerSystem, hydrateOpts: d.PrerenderHydrateOptions, appDir: string, currentUrl: URL, pageStateScript: HTMLScriptElement, node: any[]) => {
const tagName = node[0];
const attrs = node[1];

if (isString(tagName)) {
if (attrs) {
if (tagName === 'img' || tagName === 'source') {
for (const attrName of ['src', 'srcset']) {
const srcValues = getAttrUrls(attrName, attrs[attrName]);
for (const srcValue of srcValues) {
const assetUrl = new URL(srcValue.src, currentUrl);
if (assetUrl.hostname === currentUrl.hostname) {
if (hydrateOpts.hashAssets === 'querystring' && !assetUrl.searchParams.has('v')) {
try {
const hash = await getAssetFileHash(sys, appDir, assetUrl);
if (isString(hash)) {
assetUrl.searchParams.append('v', hash);
const attrValue = setAttrUrls(assetUrl, srcValue.descriptor);
attrs[attrName] = attrValue;
}
} catch (e) {}
}
}
}
}
}
}

for (let i = 2, l = node.length; i < l; i++) {
if (Array.isArray(node[i])) {
await hashPageStateAstAssets(sys, hydrateOpts, appDir, currentUrl, pageStateScript, node[i]);
}
}
}
}
};

export const getAttrUrls = (attrName: string, attrValue: string) => {
const srcValues: { src: string, descriptor?: string }[] = [];
Expand Down Expand Up @@ -294,20 +347,8 @@ const hashedAssets = new Map<string, Promise<string | null>>();
const getAssetFileHash = async (sys: d.CompilerSystem, appDir: string, assetUrl: URL) => {
let p = hashedAssets.get(assetUrl.pathname);
if (!p) {
p = new Promise<string | null>(async resolve => {
const assetFilePath = join(appDir, assetUrl.pathname);
try {
const data = await sys.readFile(assetFilePath, 'binary');
if (data != null) {
const hash = await sys.generateContentHash(data, 10);
resolve(hash);
return;
}
} catch (e) {
console.error(e);
}
resolve(null);
});
const assetFilePath = join(appDir, assetUrl.pathname);
p = sys.generateFileHash(assetFilePath, 10);
hashedAssets.set(assetUrl.pathname, p);
}
return p;
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/prerender/test/prerender-optimize.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ describe('prerender optimize', () => {
});

it('setAttrUrls src w/ descriptor', () => {
const url = new URL('https://stenciljs.com/assets/image.png?s-cache=123');
const url = new URL('https://stenciljs.com/assets/image.png?v=123');
const s1 = setAttrUrls(url, '640w');
expect(s1).toEqual('/assets/image.png?s-cache=123 640w');
expect(s1).toEqual('/assets/image.png?v=123 640w');
});

});

0 comments on commit baeb842

Please sign in to comment.