Hello. I am trying to implement AMP with Nuxt.
When I run official with-amp example, it doesn't load images component. And the page loads very slow.
/cc @Atinux
I think you are running with SPA mode since surge.sh is static website hosting, with-amp example depends on render:route hook which is not triggering on nuxt generate command.
You can check your webpage's source code, there is no <script async src="https://cdn.ampproject.org/v0.js"></script> which should be added the hook I mentioned above.
If you want same behaviour on spa page, you should modify your nuxt.config.js file and change hooks like below.
hooks: {
'generate:page': (page) => {
let html = page.html
// Add amp-custom tag to added CSS
html = html.replace(/<style data-vue-ssr/g, '<style amp-custom data-vue-ssr')
// Remove every script tag from generated HTML
html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
// Add AMP script before </head>
const ampScript = '<script async src="https://cdn.ampproject.org/v0.js"></script>'
html = html.replace('</head>', ampScript + '</head>')
// Update page html
page.html = html
}
}
Yes, but how can I have both AMP and non-AMP app in one place? I should create separate project for AMP version? How this config from with-amp will work along with regular Nuxt app? Am I misundestand AMP somehow maybe?
@iamdubx
app.htmlmodifyHtml function with the following codeconst modifyHtml = (html) => {
// Add amp-custom tag to added CSS
html = html.replace(/<style data-vue-ssr/g, '<style amp-custom data-vue-ssr')
// Remove every script tag from generated HTML
html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
// Add AMP script before </head>
const ampScript = '<script async src="https://cdn.ampproject.org/v0.js"></script>'
html = html.replace('</head>', ampScript + '</head>')
// Add AMP boilerplate
const ampBoilerplate = `<style amp-boilerplate>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}}</style>
<noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>`;
html = html.replace('</head>', ampBoilerplate + '</head>')
// Make it âš¡
html = html.replace('<html', '<html âš¡');
return html
}
/amp/.. page.url is contains that route prefix (in this case /amp) like below.'render:route': (url, page, { req, res }) => {
if (url.startsWith('/amp/')) {
page.html = modifyHtml(page.html)
}
}
And also don't forget to tell Google your amp url on your regular pages with adding necessary meta header like below
<link rel="amphtml" href="CURRENT_PAGES_AMP_VERSION">
How do you dynamically load the amp css and the non amp css globally?
I get this AMP error:
The parent tag of tag 'amp-sidebar' is 'main', but it can only be 'body'
How can I render a component directly in the body?
Any idea how to generate amp pages on specific route (ex. '/amp') with ssr mode (universal app) ?
The code above wont work for me.
Any idea how to generate amp pages on specific route (ex. '/amp') with ssr mode (universal app) ?
The code above wont work for me.
in your nuxt.config.js
import { modifyHtml } from './modules/configs/amp.js'
module.exports = {
...
hooks: {
// This hook is called before generatic static html files for SPA mode
'generate:page': (page) => {
page.html = modifyHtml(page.html)
},
// This hook is called before rendering the html to the browser
'render:route': (url, page, {
req,
res
}) => {
if (url.startsWith('/amp/')) {
page.html = modifyHtml(page.html)
}
}
},
My ./modules/configs/amp.js
It is custom to my needs, look at // Add AMP script before to add the AMP components you want to use.
const cleanStyleTags = (html) => {
html = html.replace(/<style data-vue-ssr/g, '<style amp-custom data-vue-ssr')
let styles = html.match(/<style amp-custom\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi)
html = html.replace(/<style amp-custom\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, '')
let oneStyle = ''
if (styles) {
for (let i = 0; i < styles.length; i++) {
styles[i] = styles[i].replace(/<style amp-custom .*>/gi, '')
styles[i] = styles[i].replace(/<\/style>/gi, '')
oneStyle += styles[i] + '\n'
}
}
return html.replace('</head>', `\n<style amp-custom data-vue-ssr>${oneStyle}</style>\n` + '\n</head>')
}
const moveBase = (html) => {
let base = html.match(/<base href="\/">/gi)
if (!base) {
return
}
base = base[0]
html = html.replace(/<base href="\/">/gi, '')
return html.replace('<head>', '<head>\n' + base + '\n\n')
}
export const modifyHtml = (html) => {
// Remove every script tag from generated HTML
html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
// Add AMP script before </head>
const ampScript = ` <script async src="https://cdn.ampproject.org/v0.js"></script>
<script custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js" async=""></script>
<script custom-element="amp-sidebar" src="https://cdn.ampproject.org/v0/amp-sidebar-0.1.js" async=""></script>
<script custom-element="amp-accordion" src="https://cdn.ampproject.org/v0/amp-accordion-0.1.js" async=""></script>
<script custom-element="amp-instagram" src="https://cdn.ampproject.org/v0/amp-instagram-0.1.js" async=""></script>
<script custom-element="amp-social-share" src="https://cdn.ampproject.org/v0/amp-social-share-0.1.js" async=""></script>
<script custom-element="amp-fx-collection" src="https://cdn.ampproject.org/v0/amp-fx-collection-0.1.js" async=""></script>`
html = html.replace('</head>', ampScript + '\n</head>')
// Add AMP boilerplate
const ampBoilerplate = `<style amp-boilerplate>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}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>`
html = html.replace('</head>', ampBoilerplate + '\n</head>')
html = cleanStyleTags(html)
html = moveBase(html)
// Make it âš¡
html = html.replace('<html', '<html âš¡')
return html
}
randyhoulahan, your way 'const cleanStyleTags' is long. Because nuxt generate tags 'style' one after another. that's easier
html = html.replace(/<style data-vue-ssr-id\W[^>]*/g, '<style amp-custom');
html = html.replace(/<\/style><style amp-custom>/gi, '');
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
@iamdubx
app.htmlmodifyHtmlfunction with the following code/amp/..page.urlis contains that route prefix (in this case/amp) like below.And also don't forget to tell Google your amp url on your regular pages with adding necessary meta header like below