sprotty icon indicating copy to clipboard operation
sprotty copied to clipboard

sprotty and next.js

Open tunesmith opened this issue 3 years ago • 1 comments

Apologies for the non-standard issue format, but I put together a Next.JS app that includes the standalone circlegraph example and I wanted to record some of the less intuitive parts of the experience, in case they are relevant for your future development. To contrast with the current "examples" installation, I used npm.

You can follow along the commit history at https://github.com/tunesmith/sprotty-nextjs but here's the list:

  • In views.tsx it is unclear whether to import Snode from sprotty or sprotty-protocol. In the example's standalone.ts, Snode was imported from sprotty-protocol, but that causes errors in views.tsx if it isn't imported from sprotty.
  • NextJS does not have "experimentalDecorators": true, in its default tsconfig.json, so that needed to be added for views.tsx to work
  • type 'RenderingContext' collides with a type that appears to already be supplied by default in lib.dom.d.ts
  • views.tsx doesn't like the svg as-is, and importing { svg } didn't do the trick. I didn't figure this one out, I had to // @ts-ignore where it returned the jsx. (This is just an IDE error though, not a runtime error.)
  • The first big challenge is that after importing di.config.ts, NextJS would not run, and had this complaint:
./node_modules/@vscode/codicons/dist/codicon.css
Global CSS cannot be imported from within node_modules.
Read more: https://nextjs.org/docs/messages/css-npm
Location: node_modules/sprotty/lib/features/command-palette/di.config.js

If you google this error and jump into the rabbit hole, it eventually leads to this NextJS RFC: https://github.com/vercel/next.js/discussions/27953

Basically, relying on node_modules css for global css appears frowned upon. I'm also not even using vscode. At any rate, there is currently one workaround for NextJS and it's apparently unstable and not guaranteed to work with future NextJS versions, so I think it would be better if this were fixed on sprotty's end.

  • Also related to imported di.config.ts, NextJS complains about TypeError: Reflect.hasOwnMetadata is not a function - the fix was to add reflect-metadata into package.json dependencies, and then add `import "reflect-metadata";' into the imports for di.config.ts This seemed non-standard since the code in di.config.ts written didn't directly refer to anything in this library - maybe it needs to be added to sprotty's dependencies instead? Also, the import needed to be put on a certain line number - when added later in the imports, I got the same error with no explanation. This took a while to nail down.
  • The next big challenge was when trying to call await modelSource.setModel(graph); Then I got:
TypeError: Cannot add property data, object is not extensible

Which came from getData in vnode-utils.js. This also took a while, as it had to do with views.tsx - turned out I had to import { svg } after all. But then I got an error that said x pragma and pragmaFrag cannot be set when runtime is automatic. The proper fix, which isn't in the example codebase, was to use @jsxRuntime classic as follows:

/** @jsx svg */
/** @jsxRuntime classic */
import { svg } from "sprotty/lib/lib/jsx";

It's something else that seems a bit non-standard, since svg is never actually mentioned in views.tsx and is greyed out as an import in the IDE.

  • The last part that struggles against modern NextJS convention is how the css is loaded. di.config.ts requires some css. I was able to get this working by importing this as global css inside of NextJS's custom "app", but it would be better if this css were available on a component level either through CSS Modules or one of the css-in-js modules. Unfortunately, this currently doesn't seem possible since views.tsx has a nonstandard way of referring to css - at least, I'm not sure how to have the svg in views.tsx refer to css using the normal className= convention that NextJS uses for CSS Modules.

The rest of it was fairly conventional, using button handlers to accomplish the same thing that the eventListeners were doing in the example code.

I hope this is helpful somehow - I've only just started learning sprotty and I'm quite excited about it for some dag animation side projects I'm working on. Thanks!

tunesmith avatar May 11 '22 05:05 tunesmith

Thanks for the feedback! This is certainly valuable, and we should consider it when preparing the final API before we publish v1.0.0.

@planger @tortmayr @ndoschek WDYT about the codicon css issue? Do you see alternative ways to include that so the package could be compatible with a wider range of frameworks?

spoenemann avatar May 13 '22 07:05 spoenemann