Skip to content
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

amp optimizer to support ampjs.org (not enabled as default) #1358

Merged
merged 1 commit into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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