Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage with latest Next.js (9.3) #2

Closed
vieko opened this issue Apr 27, 2020 · 15 comments
Closed

Usage with latest Next.js (9.3) #2

vieko opened this issue Apr 27, 2020 · 15 comments

Comments

@vieko
Copy link

vieko commented Apr 27, 2020

FWIW: Next.js kept complaining with cannot use import statement outside a module. I had to include three and drei in the transpile modules array to get OrbitControls to work:

next.config.js
const withTM = require('next-transpile-modules')(['three', 'drei'])
module.exports =withTM()

Hope this helps someone else.

@drcmda
Copy link
Member

drcmda commented Apr 27, 2020

that's odd, don't even know what that means. the published /dist/index.js is a module, no?

@vieko
Copy link
Author

vieko commented Apr 27, 2020

I'm still trying to understand the message myself :)

My guess at this point: Next.js tries to run server-side and fails somehow. I'm sure there's an explanation / actual solution for this.

@talentlessguy
Copy link
Member

@vieko I had exactly the same problem and made a question on spectrum and twitter. The problem is that Next.js uses CommonJS modules on server, so it cannot understand ESM modules.

Another solution is importing dynamically, like

import dynamic from 'next/dynamic'

const Cube = dynamic(() => import('../components/Cube'))

@vieko
Copy link
Author

vieko commented Apr 28, 2020

@talentlessguy I could not get it to work with a dynamic import (saw your post on spectrum). I think this is because the OrbitControls component included in drei, references bits in three.

@lostfictions
Copy link

hey, just got bit by this as well. looks like the issue isn't occurring in drei proper -- the cjs version has correctly been transpiled to require calls -- but rather results from the fact that it's still using the jsm versions of some three stuff.

so for example, when i try to use <MapControls />, i get an import error coming from /node_modules/three/examples/jsm/controls/OrbitControls.js:10 -- which, sure enough, is an untranspiled import statement.

imo this is... kind of three's fault for having a really janky build configuration. it's not ideal for tree-shaking, but short of having a rollup plugin rewrite import statement paths based on whether the output target is cjs or esm, maybe a good rule of thumb would be for library code like drei to use the cjs versions of three modules?

@lostfictions
Copy link

oh wait -- i'm looking a bit more closely at three and i guess there's no cjs version of the examples code... your options are es modules or a version that patches the THREE global. i guess i'll uhhh copy and paste both the drei code and the three example code into my own project and install any missing dependencies myself

@drcmda
Copy link
Member

drcmda commented May 5, 2020

imo this is... kind of three's fault for having a really janky build configuration. it's not ideal for tree-shaking, but short of having a rollup plugin rewrite import statement paths based on whether the output target is cjs or esm, maybe a good rule of thumb would be for library code like drei to use the cjs versions of three modules?

ahh, that makes sense now. yes it's kind of sad. i have made an issue for this once and it got shot down. examples/jsm breaks node resolution by digging directly into the three source with relative ../../../ paths. even crazier, in a cjs env it loads two threejs versions side-by-side because of it, they're overlapping, and it breaks some of their controls and primitives, rectAreaLights for instance.

i think someone should open an issue there to make them aware that their build breaks node and ssr.

@MichaelWheldon
Copy link

MichaelWheldon commented May 9, 2020

I got this working using withTM. The next/dynamic solution kind of worked for me, but only after the second render. Sample next.config:

const withPlugins = require('next-compose-plugins');
const withTM = require('next-transpile-modules')(['three', 'drei']);

module.exports = withPlugins([...otherPlugins, withTM], {
  webpack: (config) => {
     ...
  }
}

@epleaner
Copy link

Hey, @MichaelWheldon 's solution works for me for the most part, but I'm running into that "only after the second render" issue while using First Person Controls. I guess this isn't really a drei issue specifically, but I'd figure I'd ask here. It seems the Controls are being loaded but are extremely choppy / unresponsive until the second render. Disabling SSR with next/dynamic doesn't have an impact. Anyone seen this?

@lostfictions
Copy link

lostfictions commented Jun 10, 2020

fwiw something like dynamic(() => import('../components/Cube')) doesn't actually disable ssr -- in next dynamic imports can be used for bundle-splitting/lazy-loading for conditional renders, but it actually still supports ssr despite that (which is great in most circumstances but can indeed cause problems with browser-only stuff).

you have to explicitly disable ssr for a dynamic import, ie.
dynamic(() => import('../components/Cube'), { ssr: false })

i haven't come back to drei/three specifically, but i'm currently working with a different canvas application where this fixed all my issues. for three, i think a combination of transpiling modules with next-transpile-modules as suggested above AND explicitly disabling ssr via dynamic import for any browser-only react subtrees should work.

as i've noted in this issue comment, one simple technique is just to move your entire application root into a dynamic import. (this also saves you from having to write any conditional if (process.browser) or if (typeof window !== 'undefined') stuff anywhere in your code.)

@epleaner
Copy link

Thanks for that, @lostfictions . Doesn't fix this unresponsive FirstPersonControls issue unfortunately, but this is useful in general.

@gsimone
Copy link
Member

gsimone commented Jul 5, 2020

I opened a PR to improve the next.js with-three example, please refer to that and if you can contribute 👍

vercel/next.js#14864

@gsimone gsimone closed this as completed Aug 1, 2020
@MehediH
Copy link

MehediH commented Jan 18, 2021

Hey everyone! I am running into this issue and can't seem to figure out a fix. I have followed @gsimone's approach to use drei in Next.js but I am still getting the following error:

image

If I import drei components as such, the issue disappears:

const OrbitControls = dynamic(() => import('drei').then((mod) => mod.OrbitControls), { ssr: false })

...which is not the cleanest way to import the components, especially as I am using a couple of other components from drei.

For reference, I am using drei v2.2.13, next-transpile-modules v6.0.0, and next v10.0.5.

Any ideas what I am doing wrong? You can see the code here https://github.com/MehediH/m3tamorphosis

@joshuaellis
Copy link
Member

This is a known error currently & we're working on a fix, you can track it here #233

@MehediH
Copy link

MehediH commented Jan 18, 2021

Aha! Apologies should have looked at the drei repo first. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants