Next.js: Can't add html comments in _document.js

Created on 27 Feb 2018  路  9Comments  路  Source: vercel/next.js

Can't add html comments in _document.js, I believe this is just a something that isn't possible with jsx, but wondering if there may be a workaround.

The reason I need to do this is because google is trying to index urls that are in the __NEXT_DATA__ object and I'd like to wrap the whole script tag in <!--googleoff: all-->.

Most helpful comment

Have you tied this in your own _document.js?

export default class MyDocument extends Document {
    render() {
        return (
            <html lang="en">
                <Head />
                <body>
                    <div className="root">{"you main app"}</div>
                    <script dangerouslySetInnerHTML={{ __html: `<!--googleoff: all-->` }} />
                    <NextScript />
                    <script dangerouslySetInnerHTML={{ __html: `<!--googleon: all-->` }} />
                </body>
            </html>
        );
    }
}

So later in DOM, it would be like

<script><!--googleoff: all--></script>
<script> __NEXT_DATA__  = xxxx</script>
<script><!--googleon: all--></script>

Since google would crawl the document as a plain text, feels like this would work.

All 9 comments

You can write comments in JSX by wrapping them in curly braces. But keep in mind you have to return a single element from React components.

This works:

const MyComponent = (props) => {
  return (
    <div>
      {/*This is a comment*/}
      Some Text
    </div>
  )
}

This will cause an error:

const MyComponent = (props) => {
  return (
      {/*This is a comment*/}
    <div>
      Some Text
    </div>
  )
}

Hey @dbrodie122 dbrodie122 thanks for the input but I need an html comment to appear in the dom / server side rendered html. Jsx comments don't make it into the dom.

Example: <!--googleoff: all-->

I think it's the ! that causes issues.

Have you tied this in your own _document.js?

export default class MyDocument extends Document {
    render() {
        return (
            <html lang="en">
                <Head />
                <body>
                    <div className="root">{"you main app"}</div>
                    <script dangerouslySetInnerHTML={{ __html: `<!--googleoff: all-->` }} />
                    <NextScript />
                    <script dangerouslySetInnerHTML={{ __html: `<!--googleon: all-->` }} />
                </body>
            </html>
        );
    }
}

So later in DOM, it would be like

<script><!--googleoff: all--></script>
<script> __NEXT_DATA__  = xxxx</script>
<script><!--googleon: all--></script>

Since google would crawl the document as a plain text, feels like this would work.

Pretty clever @haohcraft . That does the trick. Thanks 馃檹

I also need to do this, but unfortunately can't be inside a script tag. Its something that needs to be injected right into the header. I'm using nginx to do virtual includes so it needs to look like

<!--# include virtual="<thing to include>" -->

any thoughts?

I also need what miwialex is saying too... Not inside a script tag... Can't figure out a way.

@miwialex I figured out a way to do this, hackily tonight.. I had a huge issue with JSS and Emotion conflicting and needed to add a comment which JSS references to change the insertion order of the CSS... Anyways long story short what worked for me is this, in my _document.js

Basically above my (the Next.js HEAD component), I added this:

      <head dangerouslySetInnerHTML={{ __html: '<!-- jss-insertion-point -->' }}>
      </head>

Then everything in the HEAD component got appended after that, which worked for my use case, at least in chrome, I haven't tested other browsers...

So for me it looks like this:

class MyDocument extends Document {
  constructor(props) {
    super(props);
    const { __NEXT_DATA__, ids } = props;
    if (ids) {
      __NEXT_DATA__.ids = ids;
    }
  }

  render() {
    const { pageContext } = this.props;

    return (
      <html lang="en" dir="ltr">
      <head dangerouslySetInnerHTML={{ __html: '<!-- jss-insertion-point -->' }}>
      </head>
        <Head>
          <meta charSet="utf-8" />
          {/* Use minimum-scale=1 to enable GPU rasterization */}
          <meta
            name="viewport"
            content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"
          />
          .... other crap removed to shorten this.

        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    );
  }
}

@craigcbrunner @haohcraft You both deserve a medal, spent so much time trying to figure this out. Thank you.

@craigcbrunner To change the CSS injection order, I followed this steps:

  • add a noscript tag inside Head component (_document.js)
return (
  <html lang="en" dir="ltr">
    <Head>
        .
        .
        .
      <noscript id="jss-insertion-point"></noscript>
      .
      .
      .
    </Head>
    <body>
      <Main />
      <NextScript />
    </body>
  </html>
);
  • specify in JSS create method the element created (_app.js)
const jss = create({
  insertionPoint: process.browser ? document.getElementById('jss-insertion-point') : null,
});
Was this page helpful?
0 / 5 - 0 ratings

Related issues

olifante picture olifante  路  3Comments

pie6k picture pie6k  路  3Comments

swrdfish picture swrdfish  路  3Comments

irrigator picture irrigator  路  3Comments

havefive picture havefive  路  3Comments