o1js: Can't use `PrivateKey` on server in a NextJS 14 app
I am having trouble using o1js
in a simple NextJS 14 app.
You can find my repo here: https://github.com/sam-goodwin/private-wallet
Check out the repo and run:
pnpm i
pnpm next build
It will just hang:
next build
▲ Next.js 14.1.4
- Environments: .env
Creating an optimized production build ...
✓ Compiled successfully
✓ Linting and checking validity of types
⚠ Sending SIGTERM signal to static worker due to timeout of 60 seconds. Subsequent errors may be a result of the worker exiting.
⚠ Restarted collecting page data for undefined because it took more than 60 seconds
⚠ See more info here https://nextjs.org/docs/messages/static-page-generation-timeout
Collecting page data .
Comment out the PrivateKey.random()
and the error goes away.
When looking at the tutorials I spotted this bizarre code:
export default function Home() {
useEffect(() => {
(async () => {
const { Mina, PrivateKey } = await import('o1js');
const { Add } = await import('../../../contracts/build/src/');
})();
}, []);
This raises some red flags. Is o1js
not designed to work as a normal module that can be imported?
About this issue
- Original URL
- State: open
- Created 3 months ago
- Comments: 25 (13 by maintainers)
I got most of the way towards removing TLA here: https://github.com/o1-labs/o1js/pull/1583 will finish tomorrow
Managed to get the node version of
o1js
used in NextJS by removing themain
frompackage.json
.Still hanging but at least running the right version now I think (not getting
navigator
error.Hi @sam-goodwin! Thanks for all your feedback and clear descriptions of the problems you are facing. I agree that there are opportunities to remove the friction to create an app. The current NextJS scaffold in the
zkApp-CLI
was originally developed with versions that utilized thepages
folder structure and an older version of webpack. We will update the scaffold to utilize Next14 as well the app router and turboPack. With these updates, we can simplify configurations like this.Opened a PR to update the
node-backend.js
andweb-backend.js
: https://github.com/o1-labs/o1js-bindings/pull/267I believe this is required as a first step.
Is there a reason why that code warrants a separate repo vs just being in this repo for simplicity? How can I make changes to both repos in 1 PR? Or is that not possible?
Nice catch!! 😮
Is this what you mean?
And the plan to get rid of it is to:
Thanks for the responses, @mitschabaude.
Bundlers will optimize the bundled code and if there’s expensive initialization code, we can move that out of the module import path and put it in a function. Give control to the user through explicit functions instead of through the
await import
mechanism.Sticking to ordinary practices is going to have far less bugs and also scare less people off. I don’t think I’ve ever seen an
await import
inside auseEffect
.Is this the only place where top-level await is required? For the bindings?
https://github.com/o1-labs/o1js/blob/main/src/snarky.js
Could we instead defer this evaluation by placing it in an
init
function:Avoiding global state and expensive async processing when importing a module is generally good practice.
I think this is fine. Seems unavoidable.
This bit scares me:
Anything we can do to remove that would be a win.
I appreciate that top-level await has been supported by browsers, but for Mina to succeed, I think prioritizing smooth integration with the popular web frameworks is more important than using a less supported, modern feature.
RE: https://github.com/o1-labs/o1js/issues/1205 - glad to see there is a plan to remove top-level await. Anything I can do to help? I’d very much like to be able to use
o1js
just like any other library in my NextJS’s client and server side code.