Fix AMP HTML content emit (#9468)

* Add failing test

* Escape dollar signs in AMP HTML

* Update to not use replace for updating AMP_RENDER_TARGET
This commit is contained in:
JJ Kasper 2019-11-25 14:05:52 -06:00 committed by GitHub
parent 2cbe4d3560
commit 409f20a9ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 6 deletions

View file

@ -15,6 +15,7 @@ export const BLOCKED_PAGES = ['/_document', '/_app']
export const CLIENT_PUBLIC_FILES_PATH = 'public'
export const CLIENT_STATIC_FILES_PATH = 'static'
export const CLIENT_STATIC_FILES_RUNTIME = 'runtime'
export const AMP_RENDER_TARGET = '__NEXT_AMP_RENDER_TARGET__'
export const CLIENT_STATIC_FILES_RUNTIME_PATH = `${CLIENT_STATIC_FILES_PATH}/${CLIENT_STATIC_FILES_RUNTIME}`
// static/runtime/main.js
export const CLIENT_STATIC_FILES_RUNTIME_MAIN = `${CLIENT_STATIC_FILES_RUNTIME_PATH}/main.js`

View file

@ -31,6 +31,7 @@ import { isInAmpMode } from '../lib/amp'
import { PageConfig } from 'next/types'
import { isDynamicRoute } from '../lib/router/utils/is-dynamic'
import { SPR_GET_INITIAL_PROPS_CONFLICT } from '../../lib/constants'
import { AMP_RENDER_TARGET } from '../lib/constants'
export type ManifestItem = {
id: number | string
@ -648,11 +649,13 @@ export async function renderToHTML(
})
if (inAmpMode && html) {
// use replace to allow rendering directly to body in AMP mode
html = html.replace(
'__NEXT_AMP_RENDER_TARGET__',
`<!-- __NEXT_DATA__ -->${docProps.html}`
)
// inject HTML to AMP_RENDER_TARGET to allow rendering
// directly to body in AMP mode
const ampRenderIndex = html.indexOf(AMP_RENDER_TARGET)
html =
html.substring(0, ampRenderIndex) +
`<!-- __NEXT_DATA__ -->${docProps.html}` +
html.substring(ampRenderIndex + AMP_RENDER_TARGET.length)
html = await optimizeAmp(html)
if (renderOpts.ampValidator) {

View file

@ -5,6 +5,7 @@ import flush from 'styled-jsx/server'
import {
CLIENT_STATIC_FILES_RUNTIME_AMP,
CLIENT_STATIC_FILES_RUNTIME_WEBPACK,
AMP_RENDER_TARGET,
} from '../next-server/lib/constants'
import { DocumentContext as DocumentComponentContext } from '../next-server/lib/document-context'
import {
@ -530,7 +531,7 @@ export class Main extends Component {
render() {
const { inAmpMode, html } = this.context._documentProps
if (inAmpMode) return '__NEXT_AMP_RENDER_TARGET__'
if (inAmpMode) return AMP_RENDER_TARGET
return <div id="__next" dangerouslySetInnerHTML={{ __html: html }} />
}
}

View file

@ -0,0 +1,7 @@
export const config = { amp: true }
export default () => (
<div data-amp-bind-text="fields_maxPrice_live < 801 ? '$' + round(fields_maxPrice_live) : '$800+'">
$800+
</div>
)

View file

@ -58,6 +58,12 @@ describe('AMP Usage', () => {
expect($('.abc').length === 1)
})
it('should render the page without leaving render target', async () => {
const html = await renderViaHTTP(appPort, '/special-chars')
await validateAMP(html)
expect(html).not.toContain('__NEXT_AMP_RENDER_TARGET__')
})
it('should not output client pages for AMP only', async () => {
const buildId = readFileSync(join(appDir, '.next/BUILD_ID'), 'utf8')
const ampOnly = ['only-amp', 'root-hmr']