Jump to content
GreenSock

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

Animation doesn't trigger in production (webpack bundle)

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hello The People of Greensock,

 

I've been working with a static site generator for react lately - Gatsby.js. One of the components has a menu animation attached. In development the animation works just fine, but when deployed it just doesn't trigger.

 

Code is bundled and minified with webpack.

 

The weird thing is, GSAP loads up properly, the console is clear, no errors.  It's hard to investigate more since code after minification and bundling is hard to read in chrome dev tools. :/

 

I'm not sure if this is related to my GSAP setup, but if anyone could take a look at the code, it would be awesome.

 

This is the navAnimation itself:

import { TimelineLite, CSSPlugin, Power2, Power3 } from 'gsap';
import * as CSSRulePlugin from 'gsap/CSSRulePlugin';

const slideDownTl = new TimelineLite({ paused: true, initialRender: true });
const slideUpTl = new TimelineLite({ paused: true, initialRender: true });
// Document-object-aware variables
let menuBtn, menuList, shutter, shutterBf, shutterAft, menuSpans, menuSpansAfts;

if (typeof window !== 'undefined' && typeof document !== 'undefined') {
  document.addEventListener('DOMContentLoaded', function() {
    // Menu Button
    menuBtn = document.querySelector('.menu-btn');
    // Menu List
    menuList = document.querySelector('.list-nav');
    // Shutter Variables
    shutter = document.querySelector('.shutter');
    shutterBf = CSSRulePlugin.getRule('.shutter:before');
    shutterAft = CSSRulePlugin.getRule('.shutter:after');
    // Menu Span Variables
    menuSpans = document.querySelectorAll('.menu-span');
    menuSpansAfts = CSSRulePlugin.getRule(
      '.list-nav ul li .menu-link a .menu-span:after'
    );
    console.log('we passed window+document check!');

    // slideDown Animation Timeline
    slideDownTl
      .set([shutterBf, shutterAft], {
        cssRule: { y: '-120%' }
      })
      .set(menuBtn, { pointerEvents: `none` })
      .set([menuList, shutter], {
        visibility: 'visible'
      })
      .set(menuSpans, { y: '-200%' })
      .timeScale(1.2)
      .staggerTo(
        [shutterBf, shutterAft],
        1,
        {
          cssRule: { y: '0%' },
          force3D: true,
          rotation: 0.01,
          ease: Power3.easeOut
        },
        0.3
      )
      .staggerTo(
        menuSpans,
        0.5,
        { y: '0%', ease: Power2.easeInOut },
        0.1,
        '-=0.7'
      )
      .set(menuBtn, { pointerEvents: `all` });
    // slideUp Animation Timeline
    slideUpTl
      .set(menuBtn, { pointerEvents: `none` })
      .staggerTo(menuSpans, 0.5, { y: '-200%', ease: Power2.easeIn }, 0.1)
      .staggerTo(
        [shutterAft, shutterBf],
        0.75,
        {
          cssRule: { y: '-120%' },
          force3D: true,
          rotation: 0.01,
          ease: Power2.easeIn
        },
        0.25,
        '-=0.4'
      )
      .set([menuList, shutter], {
        visibility: 'hidden'
      })
      .set(menuBtn, { pointerEvents: `all` });
  }); //  end DOMContentLoaded
} // end if window !== undefined

export const slideDown = () => {
  slideDownTl.play(0);
};

export const slideUp = () => {
  slideUpTl.play(0);
};

I check for window and document !== undefined, because Gatsby requires it on build.

 

This is Header component which has navAnimation included:

import React from 'react';
import Link from 'gatsby-link';
import './navigation.scss';
import * as navAnimation from '../../static/navAnimation.js';

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isOpened: false
    };

    this.menuToggle = this.menuToggle.bind(this);
    this.handleClickOutside = this.handleClickOutside.bind(this);
  }

  handleClickOutside(e) {
    let clickInHeader = false;
    if (e.path) {
      clickInHeader = e.path.find(node => node.localName === 'header');
    }
    !clickInHeader && this.menuToggle();
  }

  menuToggle(e) {
    if (this.state.isOpened) {
      navAnimation.slideUp();
      document.removeEventListener('click', this.handleClickOutside, true);
    } else {
      navAnimation.slideDown();
      document.addEventListener('click', this.handleClickOutside, true);
    }
    this.setState(prevState => {
      return { isOpened: !prevState.isOpened };
    });
  }

  render() {
    return (
      <header>
        <h1>
          <div className="logo">
            <Link to="/" onClick={this.state.isOpened && this.menuToggle}>
              <span>Seba</span>
              <span>Hewelt</span>
            </Link>
          </div>
        </h1>
        <div id="menu-btn-wrapper">
          <button
            className={this.state.isOpened ? 'menu-btn open' : 'menu-btn'}
            onClick={this.menuToggle}>
            <svg className="stick" viewBox="0 0 70 32">
              <path d="M 5 5 H70 L 5 21" />
              <path d="M 5 15 H70 L 5 31" />
            </svg>
          </button>
        </div>

        <div className="shutter" />

        <nav className="list-nav">
          <ul>
            <li>
              <div className="menu-link" onClick={this.menuToggle}>
                <Link to="/my-work">
                  <span className="menu-span">my work</span>
                </Link>
              </div>
            </li>
            <li>
              <div className="menu-link">
                <Link to="/blog" onClick={this.menuToggle}>
                  <span className="menu-span">blog</span>
                </Link>
              </div>
            </li>
            <li>
              <div className="menu-link">
                <Link to="/#contact" onClick={this.menuToggle}>
                  <span className="menu-span">contact</span>
                </Link>
              </div>
            </li>
          </ul>
        </nav>
      </header>
    );
  }
}

export default Header;

 

Link to comment
Share on other sites

Hm, it certainly sounds like some kind of build process problem, especially because you said it works fine locally. Very difficult to troubleshoot by just looking at 2 chunks of the code. Can you reproduce the problem in a codepen or something? That'd give you a much better chance of getting a solid answer. 

 

I did notice that some of your quotes were non-standard, like:

//BAD:
`all`

//GOOD:
'all'

 

Also, I'd recommend that whenever you're animating x or y to a percentage-based value, use xPercent and yPercent because it eliminates some potential confusion. You can actually have BOTH an x/y AND an xPercent/yPercent which can be extremely useful. But as a convenience, GSAP automatically checks and if you define x/y with a "%", it'll funnel that over to xPercent/yPercent. So it wasn't breaking anything - I just wanted to point out a "best practice" :)

  • Like 2
Link to comment
Share on other sites

4 hours ago, GreenSock said:

I did notice that some of your quotes were non-standard, like:


//BAD:
`all`

//GOOD:
'all'

 

 

That's valid. It's a template literal. That's probably the ES6 feature you would appreciate the most because it can cleanup all those nasty matrix and SVG path strings you have to write. ;)

 

@sebHewelt

 

It's pretty hard to troubleshoot somebody's build. If you're not using TypeScript, I would import the CSSRulePlugin like this.

import CSSRulePlugin from 'gsap/CSSRulePlugin';

 

When your animation doesn't work, try logging some stuff out to make sure it's there and what you are expecting. That might help narrow down the source of the problem.

console.log("TimelineLite", TimelineLite);
console.log("CSSRulePlugin", CSSRulePlugin);

 

And check what's loaded globally.

console.log("GSAP Globals", window.com.greensock);

 

 

  • Like 2
Link to comment
Share on other sites

This just came to me. Is your CSS being minified/altered in anyway? I'm wondering if that might be the problem.

  • Like 1
Link to comment
Share on other sites

I managed to make it work by extracting the animation into a function.

As I am using React, I imported that function with the rest of the animation and called it in componentDidMount method.

 

 

But, in the meantime I logged gsap globals, as you @OSUblake advised:

 

console.log("GSAP Globals", window.com.greensock);

 

and although I import only those:

 

import { TimelineLite, CSSPlugin, Power2, Power3 } from 'gsap';

 

in the console, it logs everything! Whaaat? What is TweenMax and others  not imported partials doing here?

 

gsap-globals.PNG.bc6e283724e7fe2aea8c3c702cad18f5.PNG

 

I guess this is not what should be available right? Especially that I do not import any of these in any other files.

 

Link to comment
Share on other sites

Yep, that's totally normal. TweenMax (the default export) includes all of those classes. GSAP was built with a pretty robust mechanism for instantiating and sharing classes internally, regardless of what order files are loaded in. 

 

In the 2.0.0 release (future), we plan to rewrite everything in standard ES6, so it'll probably look a little more "normal" ;) It's a big task, though. We're about to release 1.20.3 which is likely the last one before the total rewrite. 

  • Like 1
Link to comment
Share on other sites

21 hours ago, sebHewelt said:

and although I import only those:

 


import { TimelineLite, CSSPlugin, Power2, Power3 } from 'gsap';

 

in the console, it logs everything! Whaaat? What is TweenMax and others  not imported partials doing here?

 

I think you're expecting it to do some tree shaking, which it won't. At least not until GSAP is written as ES6 modules. Your import statement is the same as writing this. The entire gsap module is being imported.

const gsap = require("gsap");
const TimelineLite = gsap.TimelineLite;
const CSSPlugin = gsap.CSSPlugin;
const Power2 = gsap.Power2;
const Power3 = gsap.Power3;

 

 

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