Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
gogo125

React, Next.js and GSAP issues - possible fixes for SSR

Recommended Posts

Hi guys,

 

I just want to contribute with my findings in case others ran into this.  I had been struggling getting GSAP's Draggable to work with Next.js and have finally found a solution.  Next.js does Server Side Rendering (SSR) so pages rendered on the server had issues loading the GSAP NPM modules.   Please note that pages worked just fine client-side.

 

ERROR:

import TweenLite, { _gsScope, globals, EventDispatcher } from "./TweenLite.js";
^^^^^^

SyntaxError: Unexpected token import

To resolve the issue with GSAP not being transpiled, I installed next-plugin-transpile-modules

npm install --save  next-plugin-transpile-modules

 

Then I modified/created my next.config.js file according to their instructions on their NPM page.

https://www.npmjs.com/package/next-plugin-transpile-modules

 

Draggable finally worked after that (only if throwProps was set to false and you did not import ThrowPropsPlugin).

 

However, if using a plugin like ThrowPropsPlugin.js it would display an error message like:

TypeError: Cannot read property 'defaultView' of undefined

 

Around line 515 of the ThrowPropsPlugin.js file, I changed it:

//FROM THIS:
_doc = _gsScope.document,


//TO THIS LINE I FOUND IN DRAGGABLE:
_doc = _gsScope.document || {createElement: function() {return _dummyElement;}},

 

After that, I just did "npm run dev" and the pages rendered on the server side were fully functional as expected.  Hopefully this helps somebody out!


Guys at GSAP, is there any harm in changing that line in the ThrowPropsPlugin?  If not, would it be a good idea to update the plugin and other plugins for others who purchased the membership with GSAP so they don't run into this issue that I encountered?

 

  • Like 3
Link to comment
Share on other sites

Thanks for reporting this, @gogo125! And thanks for being a Club GreenSock member. 

 

That line you suggested editing in ThrowPropsPlugin isn't quite right (though it does work), but I've identified a tweak I can make to resolve things in a headless environment. I'll push that out in the next release. Thanks again!

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

Hi Guys,

 

Thanks for the help.

I was able to run the gsap in nextjs dev mode successfully. However in production i am receiving this error

 

Uncaught TypeError: Cannot assign to read only property 'x' of object '#<HTMLImageElement>'

 

 

code..

 

componentDidMount(){
    console.log(this.imgSlider)
    this.myTween.to(this.imgSlider, 1, {x: -600},"+=2")
        .to(this.imgSlider, 1, {x: -1200},"+=2")
        .to(this.imgSlider, 1, {x: -1800},"+=2")
}




<div className="col">
    <div className="testimonials-img-wrapper" >
        {
            this.images.map((data,index) => {
                return(
                    <img key={index} ref={img => this.imgSlider[index] = img} src={data.uri} alt=""/>)
            })
        }


    </div>
</div>

 

i even tried wrapping img tag with div and having the reference shifted to the div.

The error is now gone but the tween is not working.

Link to comment
Share on other sites

It sounds like maybe your environment isn't loading CSSPlugin (that's what applies the transforms to DOM elements in cases like this). Are you enabling tree shaking in your bundler maybe? If so, I bet it's dumping CSSPlugin (and it shouldn't). One solution is to just reference CSSPlugin directly in your code somewhere so that it doesn't get dumped, like:

import CSSPlugin from "gsap/CSSPlugin";

const plugins = [CSSPlugin];

 

Does that resolve things?

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Hi, Thank you for the advice. 

 

But its still a no go. the tween is working perfectly fine in dev mode of nextjs(using custom server hapi). However once build and run in production, the animation stops. I even tried doing the same using REACT TRANSITION.

 

<Transition
        mountOnEnter
        unmountOnExit
        in={true}
        addEndListener={(node, done) => {
            this.myTween.to(node, 1, {x: -600},"+=2")
                .to(node, 1, {x: -1200},"+=2")
                .to(node, 1, {x: -1800},"+=2")
                .to(node, 1, {x: -2400},"+=2")
        }}>
    <div className="d-flex flex-row">
{
    this.images.map((data,index) => {
        return(
                <img key={index} src={data.uri}/>
        )
    })
}
    </div>
    </Transition>

Works fine in dev, but in production no style being added.

 

@gogo125 How did you fix this issue. 

 

Link to comment
Share on other sites

@Anooj Mathew did you follow the directions about protecting CSSPlugin from tree shaking in your bundler? Did you reference it somewhere? 

 

If you still need help, please provide a reduced test case that demonstrates the issue. It's just very difficult to troubleshoot blind. I strongly suspect you've got a tree shaking issue going on.

  • Like 1
Link to comment
Share on other sites

Hi. The issue is due to tree shaking. CSSpulgin is considered as dead code.

 

And there is no option in webpack/next config to disable this (other than changing optimization)

 

What if I import the CSSplugin from gsap/dist file to the code like

Import 'gsap/dist/CSSplugin'

Will this solve it. I am yet to try.

 

Link to comment
Share on other sites

I'm worried that you're not reading my posts. Did you try the solution I offered?

 

To avoid tree shaking, simply reference CSSPlugin DIRECTLY somewhere in your own code, like this: 

 

import CSSPlugin from "gsap/CSSPlugin";

const myPlugins = [CSSPlugin]; //<-- HARD REFERENCE IN YOUR CODE

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Yes. Thank you so much for your help.

 

Learnt something very important here.

Hope this thread help someone in future.

 

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

Hello guys.

I'm using Next.js and React and now I need to add GSAP TweenLite to my project but I have a couple of errors!

This is my code:

import React from 'react';
import { TweenLite } from "gsap/all";


class Navbar extends React.Component {
    constructor(){
        super();

        this.state = {
            isFixed: false
        };

        this.navbar = null;
        this.navbarAnim = null;
    }

    componentDidMount(){
        this.navbarAnim = TweenLite.to(this.navbar, 2, { top: 100 });
    }

    render(){

        return (
            <nav className="navbar" ref={nav => this.navbar = nav}>
                <div className="navbar-container">
                    <img src={'/static/images/logo-sm.png'} className="logo" alt="هیناوا" />
                    <ul className="navbar-list">
                        <li><a href="#">چرا خانه هوشمند؟</a></li>
                        <li><a href="#">چرا هیناوا</a></li>
                        <li><a href="#">محصولات</a></li>
                        <li><a href="#">اپلیکیشن</a></li>
                        <li><a href="#">ارتباط با ما</a></li>
                    </ul>
                </div>
            </nav>
        );

    }
}

export default Navbar;

 

I also installed next-plugin-transpile-modules and this is  next.js config file:

const withSass = require('@zeit/next-sass');
const withCSS = require('@zeit/next-css');
const withImages = require('next-images');
const withTM = require('next-plugin-transpile-modules');
module.exports = withCSS(withSass(), withImages(), withTM());

 

But there are errors yet on my screen. I attached the screenshot.

Please help me solve my problem. I'm not so familiar with Next.js.

Regards.

Capture.PNG

Capture2.PNG

 

Link to comment
Share on other sites

I'm no expert in troubleshooting bundler issues or Webpack/React/Next stuff (we really try to keep these forums focused on GSAP-specific questions), but here are some thoughts:

  1. If you want to animate a CSS-related property (like "top" in your case), make sure you import CSSPlugin too. TweenLite on its own cannot do it. 
  2. To avoid tree shaking issues, make sure you reference CSSPlugin directly in your code somewhere (even if it's just in a local variable somewhere). 
  3. It almost sounds like that error is indicating that your build system isn't set up to handle ES6 modules or something. If you need to use the older ES5 stuff, you can just change the path to gsap/umd/... See https://greensock.com/docs/NPMUsage
  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...
On 10/9/2018 at 10:19 PM, GreenSock said:

Thanks for reporting this, @gogo125! And thanks for being a Club GreenSock member. 

 

That line you suggested editing in ThrowPropsPlugin isn't quite right (though it does work), but I've identified a tweak I can make to resolve things in a headless environment. I'll push that out in the next release. Thanks again!

 

@GreenSock Any help with this? I've just updated to the latest version and I'm getting the following error.

This is my next.config.js
 

const withSass = require('@zeit/next-sass')
//module.exports = withSass();

const withTM = require('next-plugin-transpile-modules');
module.exports = withTM(withSass({
	transpileModules: ['gsap', 'TweenLite', 'ThrowPropsPlugin', 'VelocityTracker', 'ThrowPropsPlugin', 'CSSPlugin'],
	cssModules: false
}));


ERROR:

Function.<anonymous>
./utils/ThrowPropsPlugin.js:512
  509 | */
  510 | _gsScope._gsDefine("utils.VelocityTracker", ["TweenLite"], function() {
  511 | 
> 512 | 	var _first,	_initted, _time1, _time2,
  513 | 		_capsExp = /([A-Z])/g,
  514 | 		_empty = {},
  515 | 		_doc = _gsScope.document,
View compiled
 3 stack frames were collapsed.
Module../utils/ThrowPropsPlugin.js
./utils/ThrowPropsPlugin.js:510
  507 | * VelocityTracker
  508 | * ----------------------------------------------------------------
  509 | */
> 510 | _gsScope._gsDefine("utils.VelocityTracker", ["TweenLite"], function() {
  511 | 
  512 | 	var _first,	_initted, _time1, _time2,
  513 | 		_capsExp = /([A-Z])/g,

 

Screenshot 2019-01-01 at 17.23.13.png

Link to comment
Share on other sites

That's pretty odd indeed - it's throwing an error on a simple variable declaration line? Hm. I did change something in the upcoming release that addresses the defaultView error (which only happens because that code isn't being run in a browser, but the plugin kinda needs the browser). I just emailed it to you - would you mind giving that a shot and letting me know if it resolves things for you? 

 

And thanks for being a Club GreenSock member!

Link to comment
Share on other sites

I found a way to use GSAP to React with Next.js without a problem.

You can load GSAP components in componentDidMount() method of your React Class.

Like this:

componentDidMount(){
        const GSAP = require('gsap');
        const { TweenMax, TimelineLite, Power4 } = GSAP;
        TweenMax.to(el, 1, { top: -100 });
    }

 

There is an easy reason for problems like this in Next.js.

Next.js is an SSR library and GSAP is a Client Side library. When You import GSAP in the top of your project, it throws an error because GSAP can't access to Window object in JS.

 

But, when you require it in your componentDidMount(), it will require after the page loaded and it will access to Window object in js.

Hope it will help you all.

  • Like 2
Link to comment
Share on other sites

@Hossein Rahimi that works like a charm , thanks for the explanation.

Also, using the first hack, changing line 515 did the trick too:

_doc = _gsScope.document || {createElement: function() {return _dummyElement;}},

 

  • Like 1
Link to comment
Share on other sites

  • 5 weeks later...

Just wanted to chime in here, I have the same problem with the defaultView, using next-plugin-transpile-modules. I also have been using @Hossein Rahimis solution, but it's not perfect because it introduces issues with scoping. With next.js you can also dynamically import the plugin with something like

 

const SplitTextPromise = import("gsap/SplitText");

 

and then in componentDidMount, wait for the promise to resolve

 

    SplitTextPromise.then(SplitText => {
      const split = new SplitText();
    });

 

It has the same issues as the other method, but I find it slightly cleaner because you're not mixing require and import. Anyway, @GreenSock it would be really awesome if you could fix this so we can import the modules like every other module, this is the only headache that GSAP has been giving us for a long time now, otherwise excellent product!

  • Like 1
Link to comment
Share on other sites

@rag would you mind if I sent you that updated version of SplitText to have you kick the tires and verify that it works well for you? 

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

We'd love to know if this have been solved and how to implement the solution on our projects as well.

 

We are using Draggable and ThrowPropsPlugin and it generates the same issue.

 

This is interesting, though we used the `require` method  in ComponentDidMount so far.

 

    // Require libraries here so ServerSideRendering won't complain
    require("gsap/ThrowPropsPlugin");
    this.Draggable = require("gsap/Draggable");

 

Link to comment
Share on other sites

1 hour ago, La Colonia said:

We'd love to know if this have been solved and how to implement the solution on our projects as well.

 

We are using Draggable and ThrowPropsPlugin and it generates the same issue.

 

Can you be more specific? What issue exactly? This is a pretty long thread with many different things mentioned. Is it the lack of a window/document object being defined? 

Link to comment
Share on other sites

Yes, it's the window/document which generates the defaultView error.

I guess @Hossein Rahimi answer is the way to go, but I just wanted to have a final ok from GSAP team.

Link to comment
Share on other sites

Ah, okay. Yeah, and make sure you're using the latest version of all the files (we made some tweaks in the last release to help avoid those issues, but I don't think it's feasible to completely avoid them in every case).

Link to comment
Share on other sites

  • 3 months later...
On 1/2/2019 at 9:55 AM, Hossein Rahimi said:

I found a way to use GSAP to React with Next.js without a problem.

You can load GSAP components in componentDidMount() method of your React Class.

Like this:


componentDidMount(){
        const GSAP = require('gsap');
        const { TweenMax, TimelineLite, Power4 } = GSAP;
        TweenMax.to(el, 1, { top: -100 });
    }

 

There is an easy reason for problems like this in Next.js.

Next.js is an SSR library and GSAP is a Client Side library. When You import GSAP in the top of your project, it throws an error because GSAP can't access to Window object in JS.

 

But, when you require it in your componentDidMount(), it will require after the page loaded and it will access to Window object in js.

Hope it will help you all.

 

The new way to get around this problem is to use dynamic component with disabled SSR for the component that's using GSAP https://nextjs.org/docs#with-no-ssr

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.
×