skip to Main Content

The Environment

Next.js v13 (stable, no ./app folder) is running with Node v18 in Ubuntu WSL.

As per de docs , the Crypto API has been around since Node v14~ish.

This has been indeed tested in Node, in my environment:
Node 18 importing and running crypto.randomUUID()
I also printed the whole object and it looks as the docs says it should.

The Problem

Imagine this simple component:

import crypto from 'crypto';

export default function Crypto() {
  console.log(crypto);

  return (
    <p>
      {crypto.randomUUID()}
    </p>
  );
}

Next.js says it "compiled client and server successfully in 397 ms". But after the UUID renders in the browser for a couple of milliseconds, Next.js throws a couple of errors revolving around randomUUID not being a function.

Next Runtime Error with crypto.randomUUID()

I see that Webpack is somewhat mingling in there; haven’t tried Turbopack. It’s beyond the scope of this issue.

After commenting out the method invocation within the paragraph, the console.log(crypto) runs and prints twice, as usual, in the devtools as follows:
crypto method printed

Notice how one comes from "react devetools backend" and the other one from webkpack. That leads me to believe the error gets thrown server-side as the console.loglog is invoked before the UUID method.

Server-side, despite the errors thrown in the browser, the object gets printed by the Next CLI and it contains the method: Next CLI prints crypto object and randomUUID is listed

Client-side, within the printed object, the method randomUUID() is nowhere to be found:
Inside printed crypto object in devtools
This confirms the error message. My code is not getting access to the method. Also, a couple of methods are missing, when compared to the Node docs.

And yet if one console.log(crypto) directly from the devTools, it has indeed the method within its prototype:

randomUUID directly from devtools

Furthermore, because of the structure, I’m inclined to believe the crypto object being printed is somehow coming from Node, as the structure of the Chrome V8 crypto object is completely different. But why in the hell are those methods missing?

I tried console.loging the object server-side, client-side, and in-between. Somehow the method gets lost in-between. Webpack might be the culprit. Worst of all, albeit being for the blink of an eye, I can see the string rendered before the errors get thrown; and dismissing the error cards throws a blank body. The string disappears.

EDIT
The reason one imports/requires crypto is so it can run in Node. Next is a SSR framework; in a nutshell it is intended to run first on the server, get rendered and delivered as HTML as much as it can to the client. If not imported, Node throws an error when Next tries to invoke Crypto server-side.

Now then, I tell that piece of code to only run if the Window object is available (i.e. I’m in the Browser) and it runs with the native chromium V8 Crypto object.

// import crypto from 'crypto';

export default function Crypto() {
  if (typeof window !== 'undefined') {
    console.log('CLIENT: ', crypto.randomUUID());

    return (
      <p>
        {crypto.randomUUID()}
      </p>
    );
  }

  return (
    <h1>SERVER SIDE</h1>
  );
}

The only downside is that is somehow still runs twice bc of Next magic, once server side and one client-side, which means it’s not bc of React 18. It tells me accurately that The client text did not match the server which is to be expected as an UUID function always returns a different result.

2

Answers


  1. Browsers restrict access to some crypto APIs when not running in a secure context (as defined here).

    Login or Signup to reply.
  2. Set it to state in a useEffect hook when page initially loads so it persist and then render it from state.

    const Crypto = () => {
     const [randomUUID, setRandomUUID] = useState();
    
     useEffect((
      if (typeof window !== 'undefined' && !randomUUID) {
       setRandomUUID(crypto.randomUUID());
      }
     ),[]);
    
     if(!randomUUID) <>No UUID</>;
     return <>{randomUUID}</>
    }
    
    export default Crypto;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search