diff --git a/errors/amp-bind-jsx-alt.md b/errors/amp-bind-jsx-alt.md
new file mode 100644
index 0000000000000..4bd9e2d294fba
--- /dev/null
+++ b/errors/amp-bind-jsx-alt.md
@@ -0,0 +1,14 @@
+# AMP Bind JSX Error
+
+#### Why This Error Occurred
+
+Somewhere you used `[prop]='something'` syntax which is not allowed in JSX.
+
+#### Possible Ways to Fix It
+
+Instead you can use `data-amp-bind-prop='something'` which is a valid AMP alternative
+
+### Useful Links
+
+- [AMP HTML Specification](https://www.ampproject.org/docs/fundamentals/spec)
+- [Possible future syntax](https://github.com/ampproject/amphtml/issues/21600)
diff --git a/packages/next-server/server/render.tsx b/packages/next-server/server/render.tsx
index 9c6aff7614c3d..261f1508b7e6e 100644
--- a/packages/next-server/server/render.tsx
+++ b/packages/next-server/server/render.tsx
@@ -287,21 +287,27 @@ export async function renderToHTML(
? renderToStaticMarkup
: renderToString
+ const renderPageError = (): {html: string, head: any} | void => {
+ if (ctx.err && ErrorDebug) {
+ return render(renderElementToString, )
+ }
+
+ if (dev && (props.router || props.Component)) {
+ throw new Error(
+ `'router' and 'Component' can not be returned in getInitialProps from _app.js https://err.sh/zeit/next.js/cant-override-next-props.md`,
+ )
+ }
+ }
+
let renderPage: (options: ComponentsEnhancer) => { html: string, head: any } | Promise<{ html: string; head: any }>
if (ampBindInitData) {
renderPage = async (
options: ComponentsEnhancer = {},
): Promise<{ html: string; head: any }> => {
- if (ctx.err && ErrorDebug) {
- return render(renderElementToString, )
- }
+ const renderError = renderPageError()
+ if (renderError) return renderError
- if (dev && (props.router || props.Component)) {
- throw new Error(
- `'router' and 'Component' can not be returned in getInitialProps from _app.js https://err.sh/zeit/next.js/cant-override-next-props.md`,
- )
- }
const {
App: EnhancedApp,
Component: EnhancedComponent,
@@ -348,40 +354,33 @@ export async function renderToHTML(
}
} else {
renderPage = (
- options: ComponentsEnhancer = {},
- ): { html: string; head: any } => {
- if (ctx.err && ErrorDebug) {
- return render(renderElementToString, )
- }
+ options: ComponentsEnhancer = {},
+ ): { html: string; head: any } => {
+ const renderError = renderPageError()
+ if (renderError) return renderError
- if (dev && (props.router || props.Component)) {
- throw new Error(
- `'router' and 'Component' can not be returned in getInitialProps from _app.js https://err.sh/zeit/next.js/cant-override-next-props.md`,
+ const {
+ App: EnhancedApp,
+ Component: EnhancedComponent,
+ } = enhanceComponents(options, App, Component)
+
+ return render(
+ renderElementToString,
+
+
+ reactLoadableModules.push(moduleName)}
+ >
+
+
+
+ ,
)
}
-
- const {
- App: EnhancedApp,
- Component: EnhancedComponent,
- } = enhanceComponents(options, App, Component)
-
- return render(
- renderElementToString,
-
-
- reactLoadableModules.push(moduleName)}
- >
-
-
-
- ,
- )
- }
}
const docProps = await loadGetInitialProps(Document, { ...ctx, renderPage })
@@ -418,7 +417,7 @@ export async function renderToHTML(
devFiles,
})
- if (amphtml && html) {
+ if (!dev && amphtml && html) {
html = await optimizeAmp(html, { amphtml, noDirtyAmp, query })
}
return html
diff --git a/packages/next/build/output/store.ts b/packages/next/build/output/store.ts
index ca9cc78eca229..f688da62c950f 100644
--- a/packages/next/build/output/store.ts
+++ b/packages/next/build/output/store.ts
@@ -2,6 +2,7 @@ import chalk from 'chalk'
import createStore from 'next/dist/compiled/unistore'
import readline from 'readline'
import { onExit } from './exit'
+import stripAnsi from 'strip-ansi'
export type OutputState =
| { bootstrap: true; appUrl: string | null }
@@ -39,10 +40,22 @@ store.subscribe(state => {
console.log('Compiling ...')
return
}
-
+
if (state.errors) {
console.log(chalk.red('Failed to compile.'))
console.log()
+ const cleanError = stripAnsi(state.errors[0])
+ if (cleanError.indexOf('SyntaxError') > -1) {
+ const matches = cleanError.match(/\[.*\]=/)
+ if (matches) {
+ for (const match of matches) {
+ const prop = (match.split(']').shift() || '').substr(1)
+ console.log(`AMP bind syntax [${prop}]='' is not supported in JSX, use 'data-amp-bind-${prop}' instead. https://err.sh/zeit/next.js/amp-bind-jsx-alt`)
+ }
+ console.log()
+ return
+ }
+ }
console.log(state.errors[0])
return
}
diff --git a/packages/next/package.json b/packages/next/package.json
index 7e29b3188ecf6..5ebb9da775cff 100644
--- a/packages/next/package.json
+++ b/packages/next/package.json
@@ -14,6 +14,7 @@
"client.js",
"config.js",
"constants.js",
+ "data.js",
"document.js",
"dynamic.js",
"error.js",
diff --git a/packages/next/pages/_document.js b/packages/next/pages/_document.js
index 3073df4507cd9..9cf545559429f 100644
--- a/packages/next/pages/_document.js
+++ b/packages/next/pages/_document.js
@@ -187,7 +187,7 @@ export class Head extends Component {
badProp = 'name="viewport"'
} else if (type === 'link' && props.rel === 'canonical') {
badProp = 'rel="canonical"'
- } else if (type === 'script') {
+ } else if (type === 'script' && !(props.src && props.src.indexOf('ampproject') > -1)) {
badProp = '