Jump to content
Search Community

Build issue with ScrollSmoother, ScrollTrigger and Next.JS (13)

Alan Brown test
Moderator Tag

Go to solution Solved by Rodrigo,

Recommended Posts

Hello. This is my first proper project with GSAP, been enjoying learning and animating with it. 🙂

 

I have this example on codesandbox. It uses ScrollSmoother, ScrollTrigger and some timeline animations on text.

 

Everything works perfectly in the dev preview with npm run dev. But when I build the project with npm run build then npm run start, many of the animations just dont run. Especially when using nested timelines.

 

All of the calls are inside a useIsomorphicLayoutEffect hook and I've used context and refs everywhere. Here are some findings:

 

  • The animations run when I take out ScrollSmoother (But I want to keep it)
  • When I take the ScrollTrigger out, the animation will run
  • All runs fine on the dev preview

I wonder if anyone has had similar issues or can shine a light on what might be causing it? 

 

Preview:
https://yu9mle-3000.preview.csb.app/
dev-preview.gif.7fbc65f9e3ceef7b9664de6b0a435669.gif

 


Build:
https://modernage-web-git-main-modern-age-digital.vercel.app/

build.gif.ed21dc80bac1f51c5882e3d419f7f61d.gif

 

Thanks!

 

Link to comment
Share on other sites

Hi @Alan Brown and welcome to the GreenSock forums!

 

First thanks for being a Club GreenSock member and supporting GreenSock!

 

I removed the link for your example since you pushed your .npmrc file with your private npm token in it. Please remove that and instead use the gsap-trial package in Codesandbox and Stackblitz. When you updated the example add another post in this thread with the new URL.

 

This is happening only in the intro.tsx file or in every component you have? 

Where exactly are you creating your ScrollSmoother instance? I couldn't find that anywhere in your code.

 

Can you please narrow this down to the component(s) that are actually giving you problems? Is really hard to fish issues in such a large app and we don't have the time resources to comb through a large code base like yours. If possible isolate the section(s) where this is happening and create a codepen example just for that. It would be good to isolate just the methods you're using for creating the text animations. You can use this Codepen template:

See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen

 

The only thing I can tell you right now is that you should create your ScrollSmoother instance first and then create the ScrollTrigger instances. Is also worth noticing that React render child components first and then the parent. Since is most likely that a parent is holding the ScrollSmoother instance you should be able to communicate to the child elements that the ScrollSmoother instance is ready.

 

If you prefer you can use this starter template for using Next with ScrollSmoother and just add the component and methods that are giving you problems:

https://stackblitz.com/edit/nextjs-efumgr

 

Happy Tweening!

  • Like 2
Link to comment
Share on other sites

Thanks @Rodrigo and @elegantseagulls

 

I've gone and removed my private token from the sandbox (oops), here is the link again

 

But to make things simpler, I've spun up another smaller codesandbox here, where I've tried to replicate the issue with a couple of nested timelines. You can see the text is not animating in. If I remove gsap.context from the scrollsmoother, it works. But then wont work when it builds.

Link to comment
Share on other sites

Ok, so we've used Smoother on our site, which is built on Next.js.

 

We setup our Smoother in _app.js (not sure this matters)

This is what that code looks like:

 

const useIsomorphicLayoutEffect =
    typeof window !== 'undefined' ? useLayoutEffect : useEffect;

  useIsomorphicLayoutEffect(() => {
    if (!ScrollTrigger.isTouch) {
      scroller.current = ScrollSmoother.create({
        normalizeScroll: true,
        smooth: 2,
      });
    } else {
      ScrollTrigger.config({ ignoreMobileResize: true });
    }
  }, []);

Everywhere else we are using regular useEffects(() => {}, []), just making sure to check if the element/ref is available.

  • Like 1
Link to comment
Share on other sites

@elegantseagulls Thanks for this! I moved the smoother code to _app but no luck.. Are you using Next 13? And do you also have scrolltriggers/timelines set up elsewhere that work fine? I'm wondering if Next 13 + GSAP are just not playing nice at the moment, since Next13 is all server side by default.

 

Admittedly, I've gone big here! First time GSAP with Smoother, ScrollTriggers and Nested Timelines :D. If I need to take smoother out, it's not the end of the world. But I want to keep it because it's cool. And it works in dev preview, so there must be a way.. 

Link to comment
Share on other sites

  • Solution

Hi,

 

As I mentioned before this seems more related to when the ScrollTrigger instances are created more than anything else. As soon as I wrapped the method you're using to create the animations inside a timeout it works:

https://stackblitz.com/edit/nextjs-fkstzp?file=pages%2F_app.js,pages%2Findex.js,components%2FIntro.js,components%2FOverview.js

 

What you need is a way to communicate to the child components that the ScrollSmoother instance is created. Another option could be, seeing that you have everything in just one page, to conditionally render the components after the ScrollSmoother instance is done.

 

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

@Rodrigo I think this might have worked! I added a useState to the _app file, passed it to the component and conditionally rendered the other components based on the state. It fixed my demo at least. I'm sure this is the issue, my solution might not be very elegant but if it works 🤷‍♂️

 

Thanks for this! 

Link to comment
Share on other sites

Update: Conditional rendering actually broke the ScrollSmoother effects, so it's perhaps a bit too nuclear for this. 

 

What I eventually did was pass an isRendered state from _app down into the page components then wrapped the useLayoutEffect and all the GSAP code inside a conditional statement, passing isRendered into the dependancy array. I'm sure there's a cleaner way, but It seems to have fixed it. 

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...