Skip to content

Commit

Permalink
amp optimizer to support ampjs.org (not enabled as default)
Browse files Browse the repository at this point in the history
  • Loading branch information
powerivq committed May 28, 2024
1 parent 19405f5 commit 9cbf6e0
Show file tree
Hide file tree
Showing 16 changed files with 215 additions and 130 deletions.
3 changes: 2 additions & 1 deletion packages/optimizer/lib/AmpConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const AMP_STORY_DVH_POLYFILL_ATTR = 'amp-story-dvh-polyfill';

module.exports = {
AMP_TAGS: ['amp', '⚡', '⚡4ads', 'amp4ads', '⚡4email', 'amp4email'],
AMP_CACHE_HOST: 'https://cdn.ampproject.org',
AMP_CACHE_HOSTS: ['https://cdn.ampproject.org', 'https://ampjs.org'],
DEFAULT_AMP_CACHE_HOST: 'https://cdn.ampproject.org',
AMP_VALIDATION_RULES_URL: 'https://cdn.ampproject.org/v0/validator.json',
AMP_FORMATS: ['AMP', 'AMP4EMAIL', 'AMP4ADS'],
AMP_RUNTIME_CSS_PATH: '/v0.css',
Expand Down
4 changes: 2 additions & 2 deletions packages/optimizer/lib/RuntimeHostHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
*/
'use strict';

const {AMP_CACHE_HOST, appendRuntimeVersion} = require('./AmpConstants.js');
const {DEFAULT_AMP_CACHE_HOST, appendRuntimeVersion} = require('./AmpConstants.js');

function calculateHost({
ampUrlPrefix = AMP_CACHE_HOST,
ampUrlPrefix = DEFAULT_AMP_CACHE_HOST,
ampRuntimeVersion,
lts = false,
rtv = false,
Expand Down
18 changes: 10 additions & 8 deletions packages/optimizer/lib/fetchRuntimeParameters.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ try {
}

const {
AMP_CACHE_HOST,
AMP_CACHE_HOSTS,
AMP_RUNTIME_CSS_PATH,
AMP_VALIDATION_RULES_URL,
appendRuntimeVersion,
DEFAULT_AMP_CACHE_HOST,
} = require('./AmpConstants.js');

const KEY_VALIDATOR_RULES = 'validator-rules';
Expand Down Expand Up @@ -214,12 +215,12 @@ async function fetchLatestRuntimeData_({config, ampUrlPrefix, lts}, versionKey =
version: await config.runtimeVersion.currentVersion({ampUrlPrefix, lts}),
maxAge: MaxAge.create(AMP_RUNTIME_MAX_AGE).toObject(),
};
if (!ampRuntimeData.version && ampUrlPrefix && ampUrlPrefix !== AMP_CACHE_HOST) {
if (!ampRuntimeData.version && ampUrlPrefix && !AMP_CACHE_HOSTS.includes(ampUrlPrefix)) {
config.log.error(
`Could not download runtime version from ${ampUrlPrefix}. Falling back to ${AMP_CACHE_HOST}`
`Could not download runtime version from ${ampUrlPrefix}. Falling back to ${DEFAULT_AMP_CACHE_HOST}`
);
ampRuntimeData = await fetchLatestRuntimeData_(
{config, ampUrlPrefix: AMP_CACHE_HOST, lts},
{config, ampUrlPrefix: DEFAULT_AMP_CACHE_HOST, lts},
versionKey
);
} else if (!ampRuntimeData.version) {
Expand All @@ -240,15 +241,16 @@ async function fetchLatestRuntimeData_({config, ampUrlPrefix, lts}, versionKey =
async function fetchAmpRuntimeStyles_(config, ampUrlPrefix, ampRuntimeVersion) {
if (ampUrlPrefix && !isAbsoluteUrl_(ampUrlPrefix)) {
config.log.warn(
`AMP runtime styles cannot be fetched from relative ampUrlPrefix, please use the 'ampRuntimeStyles' parameter to provide the correct runtime style. Falling back to latest v0.css on ${AMP_CACHE_HOST}`
`AMP runtime styles cannot be fetched from relative ampUrlPrefix, please use the 'ampRuntimeStyles' parameter to provide the correct runtime style. Falling back to latest v0.css on ${DEFAULT_AMP_CACHE_HOST}`
);
// Gracefully fallback to latest runtime version
ampUrlPrefix = AMP_CACHE_HOST;
ampUrlPrefix = DEFAULT_AMP_CACHE_HOST;
ampRuntimeVersion = ampRuntimeVersion || (await config.runtimeVersion.currentVersion());
}
// Construct the AMP runtime CSS download URL, the default is: https://cdn.ampproject.org/rtv/${ampRuntimeVersion}/v0.css
const runtimeCssUrl =
appendRuntimeVersion(ampUrlPrefix || AMP_CACHE_HOST, ampRuntimeVersion) + AMP_RUNTIME_CSS_PATH;
appendRuntimeVersion(ampUrlPrefix || DEFAULT_AMP_CACHE_HOST, ampRuntimeVersion) +
AMP_RUNTIME_CSS_PATH;
// Fetch runtime styles
const styles = await downloadAmpRuntimeStyles_(config, runtimeCssUrl);
if (!styles) {
Expand All @@ -257,7 +259,7 @@ async function fetchAmpRuntimeStyles_(config, ampUrlPrefix, ampRuntimeVersion) {
// Try to download latest from cdn.ampproject.org instead
return fetchAmpRuntimeStyles_(
config,
AMP_CACHE_HOST,
DEFAULT_AMP_CACHE_HOST,
await config.runtimeVersion.currentVersion()
);
} else {
Expand Down
216 changes: 108 additions & 108 deletions packages/optimizer/lib/transformers/AddMandatoryTags.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,117 +24,11 @@ const {
createElement,
firstChildByTag,
} = require('../NodeUtils');
const {AMP_FORMATS, AMP_TAGS} = require('../AmpConstants');
const {AMP_FORMATS, AMP_TAGS, DEFAULT_AMP_CACHE_HOST} = require('../AmpConstants');

const DEFAULT_FORMAT = 'AMP';
const AUTO_GENERATED_MARKER = 'data-auto';

const BOILERPLATES = {
AMP: [
{
matcher: {
tagName: 'meta',
attribs: {
charset: 'utf-8',
},
},
node: {
tagName: 'meta',
attribs: {
charset: 'utf-8',
},
},
},
{
matcher: {
tagName: 'meta',
attribs: {
name: 'viewport',
},
},
node: {
tagName: 'meta',
attribs: {
name: 'viewport',
content: 'width=device-width,minimum-scale=1,initial-scale=1',
},
},
},
{
matcher: {
tagName: 'noscript',
},
node: {
tagName: 'noscript',
children: [
{
tagName: 'style',
attribs: {
'amp-boilerplate': '',
},
// eslint-disable-next-line max-len
text:
'body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}',
},
],
},
},
{
matcher: {
tagName: 'style',
attribs: {
'amp-boilerplate': '',
},
},
node: {
tagName: 'style',
attribs: {
'amp-boilerplate': '',
},
// eslint-disable-next-line max-len
text:
'body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}',
},
},
{
matcher: {
tagName: 'script',
attribs: {
src: /^https:\/\/.+\/v0\.js$/,
},
},
node: {
tagName: 'script',
attribs: {
async: '',
src: 'https://cdn.ampproject.org/v0.js',
},
},
},
{
matcher: {
tagName: 'link',
attribs: {
rel: 'canonical',
},
},
node: {
tagName: 'link',
attribs: {
rel: 'canonical',
href: (params, log) => {
if (!params.canonical) {
log.warn('No canonical param is given. Setting canonical href to `.`');
params.canonical = '.';
}
return params.canonical;
},
},
},
},
],
};

/**
* AddMandatoryTags - this transformer will automatically add all missing tags required by a valid AMP document.
*
Expand Down Expand Up @@ -164,8 +58,114 @@ class AddMandatoryTags {
return;
}

const boilerplates = {
AMP: [
{
matcher: {
tagName: 'meta',
attribs: {
charset: 'utf-8',
},
},
node: {
tagName: 'meta',
attribs: {
charset: 'utf-8',
},
},
},
{
matcher: {
tagName: 'meta',
attribs: {
name: 'viewport',
},
},
node: {
tagName: 'meta',
attribs: {
name: 'viewport',
content: 'width=device-width,minimum-scale=1,initial-scale=1',
},
},
},
{
matcher: {
tagName: 'noscript',
},
node: {
tagName: 'noscript',
children: [
{
tagName: 'style',
attribs: {
'amp-boilerplate': '',
},
// eslint-disable-next-line max-len
text:
'body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}',
},
],
},
},
{
matcher: {
tagName: 'style',
attribs: {
'amp-boilerplate': '',
},
},
node: {
tagName: 'style',
attribs: {
'amp-boilerplate': '',
},
// eslint-disable-next-line max-len
text:
'body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}',
},
},
{
matcher: {
tagName: 'script',
attribs: {
src: /^https:\/\/.+\/v0\.js$/,
},
},
node: {
tagName: 'script',
attribs: {
async: '',
src: (params.ampUrlPrefix || DEFAULT_AMP_CACHE_HOST) + '/v0.js',
},
},
},
{
matcher: {
tagName: 'link',
attribs: {
rel: 'canonical',
},
},
node: {
tagName: 'link',
attribs: {
rel: 'canonical',
href: (params, log) => {
if (!params.canonical) {
log.warn('No canonical param is given. Setting canonical href to `.`');
params.canonical = '.';
}
return params.canonical;
},
},
},
},
],
};

// Only supports AMP for websites
const boilerplateSpec = BOILERPLATES[this.format];
const boilerplateSpec = boilerplates[this.format];
if (!boilerplateSpec) {
this.log_.info('Unsupported AMP format', this.format);
return;
Expand Down
4 changes: 2 additions & 2 deletions packages/optimizer/lib/transformers/AmpStoryCssTransformer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const {
firstChildByTag,
appendChild,
} = require('../NodeUtils');
const {AMP_CACHE_HOST} = require('../AmpConstants.js');
const {DEFAULT_AMP_CACHE_HOST} = require('../AmpConstants.js');

// This string should not be modified, even slightly. This string is strictly
// checked by the validator.
Expand Down Expand Up @@ -139,7 +139,7 @@ function appendAmpStoryCssLink(head) {
'amp-extension': 'amp-story',
// We rely on the `RewriteAmpUrls` transformer to modify this to
// the correct LTS or correct rtv path.
'href': `${AMP_CACHE_HOST}/v0/amp-story-1.0.css`,
'href': `${DEFAULT_AMP_CACHE_HOST}/v0/amp-story-1.0.css`,
});
appendChild(head, ampStoryCssLink);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/optimizer/lib/transformers/AutoExtensionImporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const {
hasAttribute,
} = require('../NodeUtils');
const {findMetaViewport, findRuntimeScript} = require('../HtmlDomHelper');
const {AMP_FORMATS, AMP_CACHE_HOST} = require('../AmpConstants');
const {AMP_FORMATS, DEFAULT_AMP_CACHE_HOST} = require('../AmpConstants');

const BIND_SHORT_FORM_PREFIX = 'bind';
const AMP_BIND_DATA_ATTRIBUTE_PREFIX = 'data-amp-bind-';
Expand Down Expand Up @@ -188,7 +188,7 @@ class AutoExtensionImporter {
}

// Use cdn.ampproject.org as default, RewriteUrlTransformer will change this in case of self-hosting
const host = AMP_CACHE_HOST;
const host = DEFAULT_AMP_CACHE_HOST;
for (const extensionName of extensionsToImport) {
if (existingImports.has(extensionName)) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class HeadNodes {
rel === 'prefetch' ||
rel === 'dns-prefetch' ||
rel === 'preconnect' ||
rel == 'modulepreload'
rel === 'modulepreload'
) {
this._resourceHintLinks.push(node);
return;
Expand Down
10 changes: 6 additions & 4 deletions packages/optimizer/lib/transformers/RewriteAmpUrls.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const {
insertBefore,
remove,
} = require('../NodeUtils');
const {AMP_CACHE_HOST} = require('../AmpConstants.js');
const {AMP_CACHE_HOSTS} = require('../AmpConstants.js');
const {findMetaViewport} = require('../HtmlDomHelper');
const {calculateHost} = require('../RuntimeHostHelper');

Expand Down Expand Up @@ -141,13 +141,15 @@ class RewriteAmpUrls {

_usesAmpCacheUrl(url) {
if (!url) {
return;
return false;
}
return url.startsWith(AMP_CACHE_HOST);
// check if url starts with one of string array
return AMP_CACHE_HOSTS.some((host) => url.startsWith(host));
}

_replaceUrl(url, host) {
return host + url.substring(AMP_CACHE_HOST.length);
const existingHost = AMP_CACHE_HOSTS.find((ampCacheHost) => url.startsWith(ampCacheHost));
return host + url.substring(existingHost.length);
}

_addEsm(scriptNode, preloadEnabled) {
Expand Down
1 change: 1 addition & 0 deletions packages/optimizer/spec/helpers/validatorInstance.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ let instance = null;
module.exports = {
get: () => {
if (!instance) {
console.error('Validator instance created: ' + path.join(__dirname, 'validator.js'));
instance = validator.getInstance(path.join(__dirname, 'validator.js'));
}
return instance;
Expand Down
Loading

0 comments on commit 9cbf6e0

Please sign in to comment.