As I understand from my SO question , I can use next/head to embed a script tag within a ponent of my React / Next JS app. So, I went about it as such:
import React, { Component } from "react";
...
import Head from "next/head";
export const Lead = props => {
return (
...
<Head>
<script
class="3758abc"
type="text/javascript"
src=".min.js"
data-encoded="1234sdkljfeiASD9A"
></script>
</Head>
...
);
};
Unfortunately, nothing rendered. I don't know if I'm missing something obvious here... I'm using Next 9.1.7.
My _app.js looks like this:
import App, { Container } from "next/app";
import Page from "../ponents/Page";
import { ApolloProvider } from "react-apollo";
import withData from "../lib/withData";
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
// this exposes the query to the user
pageProps.query = ctx.query;
return { pageProps };
}
render() {
const { Component, apollo, pageProps } = this.props;
return (
// <Container>
<ApolloProvider client={apollo}>
<Page>
<Component {...pageProps} />
</Page>
</ApolloProvider>
// </Container>
);
}
}
export default withData(MyApp);
And my _document looks like this:
import Document from "next/document";
import { ServerStyleSheet } from "styled-ponents";
export default class MyDocument extends Document {
static getInitialProps = async ctx => {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => props => sheet.collectStyles(<App {...props} />)
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
};
} finally {
sheet.seal();
}
};
}
As I understand from my SO question , I can use next/head to embed a script tag within a ponent of my React / Next JS app. So, I went about it as such:
import React, { Component } from "react";
...
import Head from "next/head";
export const Lead = props => {
return (
...
<Head>
<script
class="3758abc"
type="text/javascript"
src="https://cdn2.fake./Scripts/embed-button.min.js"
data-encoded="1234sdkljfeiASD9A"
></script>
</Head>
...
);
};
Unfortunately, nothing rendered. I don't know if I'm missing something obvious here... I'm using Next 9.1.7.
My _app.js looks like this:
import App, { Container } from "next/app";
import Page from "../ponents/Page";
import { ApolloProvider } from "react-apollo";
import withData from "../lib/withData";
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
// this exposes the query to the user
pageProps.query = ctx.query;
return { pageProps };
}
render() {
const { Component, apollo, pageProps } = this.props;
return (
// <Container>
<ApolloProvider client={apollo}>
<Page>
<Component {...pageProps} />
</Page>
</ApolloProvider>
// </Container>
);
}
}
export default withData(MyApp);
And my _document looks like this:
import Document from "next/document";
import { ServerStyleSheet } from "styled-ponents";
export default class MyDocument extends Document {
static getInitialProps = async ctx => {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => props => sheet.collectStyles(<App {...props} />)
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
};
} finally {
sheet.seal();
}
};
}
Share
Improve this question
asked Mar 29, 2020 at 18:57
realhatrealhat
1771 gold badge1 silver badge10 bronze badges
1
- might be related to github./vercel/next.js/issues/11012, there was a PR which solved? it, one week ago, not yet released, except in canary build. – einSelbst Commented Sep 15, 2020 at 12:17
2 Answers
Reset to default 2in your _document.js
, try to add script below <NextScript />
tag
<body>
<Main />
<NextScript />
<script
class="3758abc"
type="text/javascript"
src="https://cdn2.fake./Scripts/embed-button.min.js"
data-encoded="1234sdkljfeiASD9A"></script>
</body>
I've been working on a similar issue.
I tried the answer above that places the <script>
tag within the <body>
, but unfortunately it also rendered the contents generated by the <script>
tag to the DOM (as in, it ran the script correctly but also stored all the extra data from it at the bottom of the <body>
tag).
I also tried wrapping the script within a <Head>
ponent from next/head
(still inside the body), which prevented the DOM rendering, but that fix didn't run the script at all.
In the end, what worked for my use case was moving the script loading into the _app.js
file: it runs the script correctly without rendering extra stuff to the DOM. It looks like this:
import Head from "next/head";
function MyApp({ Component, pageProps }) {
return (
<React.Fragment>
<Head>
<script
id="my-script"
src="https://scriptsource./script"
type="text/javascript"
></script>
</Head>
<LayoutComponent {...pageProps}>
<Component {...pageProps} />
</LayoutComponent>
</React.Fragment>
);
}
export default MyApp;
I don't know if this solution causes any undesirable effects that I don't know about, but so far it has fixed my issue.
UPDATE (June 2021)
As Ahmed noted below, there are some side effects to the solution I wrote above. What I noticed was that the image loading was being blocked by the script executing.
I saw that Next 11 had just been released, which included the new <Script>
tag for this purpose.
I moved all the props into the tag, set strategy="beforeInteractive"
and then put this tag into the Page ponent directly; now everything is running exactly as expected.
Here are the docs for the Next 11 Script tag: https://nextjs/docs/basic-features/script