最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to use NextHead to render a script - Stack Overflow

programmeradmin4浏览0评论

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
Add a ment  | 

2 Answers 2

Reset to default 2

in 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

发布评论

评论列表(0)

  1. 暂无评论