greensock / GSAP

GSAP (GreenSock Animation Platform), a JavaScript animation library for the modern web
https://gsap.com
19.85k stars 1.72k forks source link

Wish: Require/Import in NodeJS way. #114

Closed tcw165 closed 8 years ago

tcw165 commented 9 years ago

Hi guys,

I import it in NodeJS way and use webpack (instead of bower, cause webpack is more powerful) to compile. It will show error like following.

error given was: ReferenceError: document is not defined
  at Function.<anonymous> (/.../node_modules/gsap/src/minified/TweenMax.min.js:15:5081)
  at [object Object].check (/.../node_modules/gsap/src/minified/TweenLite.min.js:12:817)
  at new p (/.../node_modules/gsap/src/minified/TweenLite.min.js:12:1104)
  at t._gsDefine (/.../node_modules/gsap/src/minified/TweenLite.min.js:12:1154)

I've read the article thread talking about this.

The current workaround for me is tell webpack (by adding rules in its configuration file) where to find the TweenMax, TimelineMax, and so, instead of requiring gsap cause it doesn't work for this moment.

e.g. webpack.config.js

  resolve: {
    alias: {
      'TweenLite': path.resolve(MODULE_DIR, 'gsap/src/minified/TweenLite.min.js'),
      'TweenMax': path.resolve(MODULE_DIR, 'gsap/src/minified/TweenMax.min.js'),
      'TimelineLite': path.resolve(MODULE_DIR, 'gsap/src/minified/TimelineLite.min.js'),
      'TimelineMax': path.resolve(MODULE_DIR, 'gsap/src/minified/TimelineMax.min.js'),
      'EasePack': path.resolve(MODULE_DIR, 'gsap/src/minified/easing/EasePack.min.js')
    }
  }

Actually I think it would be nice to use gsap like this:

import {TweenMax, TimelineMax, Back, Quad} from 'gsap';
danehansen commented 8 years ago

@boyw165 Hey I am battling a problem similar to your own right now. Its a private repo so I dont have a github link to show, and I didn't set up the build system (at a new job) but I am wondering how to get different gsap modules to all play nicely here. In our wepback.config.babel.js I've got:

  resolve: {
    alias: {
      'TweenLite': 'gsap/src/uncompressed/TweenLite.js',
      'TimelineLite': 'gsap/src/uncompressed/TimelineLite.js',
      'CSSPlugin': 'gsap/src/uncompressed/plugins/CSSPlugin.js',
    },
    root: path.join(__dirname, 'static/src'),
    modulesDirectories: ['node_modules', ...subProjects.map(prefixProject)],
    extensions: ['', '.json', '.js', '.jsx']
  },

Then my import statements in my component looking like:

import TweenLite from 'TweenLite'
import TimelineLite from 'TimelineLite'
import CSSPlugin from 'CSSPlugin'

Logging out out TweenLite so far just gives me an empty object, and then it just doesn't work of course. I realize i'm probably not providing enough information to be helpful, because I don't know what else to include, but if you think you would have any insights, I can provide you with whatever information you would need. Thank you.

runspired commented 8 years ago

It appears the module definition is globals only:

It should be something more like this:

// this prevents errors when TweenLite is loaded in the presence of an AMD
//  style loader but by script tag, not by the loader.
var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line
freeGlobal.TweenLite = TweenLite

if (typeof define === 'function' && define.amd) {
    define(function() {
        return TweenLite;
    });
} else if (typeof module != 'undefined' && module.exports) {
    module.exports = TweenLite;
} else {
    window[exportName] = TweenLite;
}
salzhrani commented 8 years ago

I have started es6-ification of greensock... you can find it here feedback/help is appreciated. since tests are probably located outside this repo, It is difficult to tell if regressions were introduced.

vedmant commented 8 years ago

+1 I use it with React JS!

akbr commented 8 years ago

+1 Would be really nice to have modern require/import without global variables.

arthurmchr commented 8 years ago

+1

lostpebble commented 8 years ago

With Webpack's new Tree Shaking configuration this would be an amazing addition to the library. Basically having everything at your disposal but importing just what you need from the ES6 module, with webpack doing the work of cutting out the unused fat.

Kerumen commented 8 years ago

+1

timdoes commented 8 years ago

+1

JoostKiens commented 8 years ago

+1

praneybehl commented 8 years ago

+1

dahannes commented 8 years ago

+1

glebmachine commented 8 years ago

+1

dwilt commented 8 years ago

+1

Iuriy-Budnikov commented 8 years ago

+1

EugeneHlushko commented 8 years ago

+1

byzyk commented 8 years ago

+1

osilviotti commented 8 years ago

+1 - having to go back to Velocity as I can't have the gsap module polluting the global scope

jackdoyle commented 8 years ago

Thanks for all the votes, guys. We're definitely exploring this and hear you loud and clear. Thanks for your patience. @ollie101, I'm curious - why the fear of the global scope so much that it'd make you revert to an entirely different engine and miss out on all the unique GSAP features & performance? Not criticizing at all - just trying to understand the reasoning.

krzysztofpniak commented 8 years ago

@jackdoyle Is there any milestone for modern imports scheduled?

jackdoyle commented 8 years ago

@krzysztofpniak I can't commit to a schedule yet, no - it's an ambitious undertaking for a library like this (much more complex than for a library like Velocity) but rest assured that we're moving that direction. It's very difficult to predict exactly how long it's going to take. We prefer to under-promise and over-deliver :) I've got all sorts of ideas for new tools and improvements.

kmpkt commented 8 years ago

+1

krzysztofpniak commented 8 years ago

Is it really a big deal? It looks like 1h of work or lets say 1 day if you really want to make it carefully: http://ifandelse.com/its-not-hard-making-your-library-support-amd-and-commonjs/

jackdoyle commented 8 years ago

@krzysztofpniak oh, yes, that has been implemented for quite some time. Are you not seeing it in there?Or do you have a specific suggestion for improvement in that regard? Plenty of people have been using GSAP in node, RequireJS, Browserify, etc.

I was talking about a much bigger overhaul that involves shifting a lot of code around and rewriting entire portions. That'll take weeks if not months.

dwilt commented 8 years ago

@jackdoyle I had a lot of trouble just importing pieces of the GSAP plugin. Have you tried it yourself with something like Webpack and the following?:

import {TweenMax, TimelineMax, Back, Quad} from 'gsap';
Iuriy-Budnikov commented 8 years ago

Unfortunately import doesn't work.

jackdoyle commented 8 years ago

This should be largely resolved in the latest version, 1.18.5 (released today). Let me know if you run into any issues.

glebmachine commented 8 years ago

Great news guys! Thank you)

kmpkt commented 8 years ago

Awesome. Thank you.

salzhrani commented 8 years ago

Anyone got it working using import { TweenLite } from 'gsap' with webpack? not sure if I have bad config

jackdoyle commented 8 years ago

Yep, I got it to work fine. @salzhrani, are you sure you're using the latest (1.18.5)?

salzhrani commented 8 years ago

I am using webpack beta ... calls here before ns == 'TweenMax' skip this line because _exports[moduleName] is undefined. once ns == 'TweenMax' happens _exports[moduleName] becomes truthy and the following calls do reach this line and get registered. In my setup classes like Power0 and TweenLite are missing from module.exports

jackdoyle commented 8 years ago

I see what you mean, yes. Is this any better?: https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/TweenMax-latest-beta.js

salzhrani commented 8 years ago

@jackdoyle sorry for the late response ... I tried the build and it exhibits the same issue.

jackdoyle commented 8 years ago

@salzhrani hm, are you sure you weren't using some cached version or something? I just triple-checked, even in someone else's project and it worked exactly as expected. Do you have a reduced test case that shows it broken even with that new version that I linked to above?

kmpkt commented 8 years ago

Works like a charm. Thank you.

kluplau commented 8 years ago

@jackdoyle It works fine with TweenMax and TimelineMax, but importing utils like Draggable, then you get an error about TweenLite module not found. ERROR in ./src/vendor/gsap/utils/Draggable.js Module not found: Error: Cannot resolve module 'TweenLite' in /Users/kennethbrogger/Projects/temp/Crashtestjimmy/src/vendor/gsap/utils @ ./src/vendor/gsap/utils/Draggable.js 13:57486-57517

jackdoyle commented 8 years ago

Seems to work fine if you tweak your Webpack config, like:

resolve: {
  root: path.resolve(__dirname),
  extensions: ['', '.js'],
  alias: {
    "TweenLite": "src/libs/gsap/TweenLite",
    "CSSPlugin": "src/libs/gsap/plugins/CSSPlugin"
  }
}

Then, I just import Draggable like:

import Draggable from "./libs/gsap/utils/Draggable";

(obviously tweak the paths to whatever is appropriate for your setup)

kluplau commented 8 years ago

I don't get the buid issues any longer, but I can't get it to work in the browser. The Draggable variable is undefined, so I get

Cannot read property 'create' of undefined

glebmachine commented 8 years ago

Check my alias part of webpack config:

alias: {
      TweenMax: 'gsap/src/uncompressed/TweenMax.js',
      TweenLite: 'gsap/src/uncompressed/TweenLite.js',
      TimelineLite: 'gsap/src/uncompressed/TimelineLite.js',
      TimelineMax: 'gsap/src/uncompressed/TimelineMax.js',
      EasePack: 'gsap/src/uncompressed/easing/EasePack.js',
      CSSPlugin: 'gsap/src/uncompressed/plugins/CSSPlugin.js',
    },
jackdoyle commented 8 years ago

@Blueblau tough to troubleshoot blind, but how exactly are you importing Draggable? I just verified that it worked great for me using Webpack. The element was indeed draggable. No errors. [scratching head]

kluplau commented 8 years ago

@jackdoyle Still no luck. Draggable remains undefined... 😞

Webpack config:

    alias: {
      'src': path.resolve(__dirname, '../src'),
      'assets': path.resolve(__dirname, '../src/assets'),
      'components': path.resolve(__dirname, '../src/components'),
      TweenMax: path.resolve(__dirname, '../node_modules/gsap/src/uncompressed/TweenMax.js'),
      TweenLite: path.resolve(__dirname, '../node_modules/gsap/src/uncompressed/TweenLite.js'),
      TimelineLite: path.resolve(__dirname, '../node_modules/gsap/src/uncompressed/TimelineLite.js'),
      TimelineMax: path.resolve(__dirname, '../node_modules/gsap/src/uncompressed/TimelineMax.js'),
      EasePack: path.resolve(__dirname, '../node_modules/gsap/src/uncompressed/easing/EasePack.js'),
      CSSPlugin: path.resolve(__dirname, '../node_modules/gsap/src/uncompressed/plugins/CSSPlugin.js')
    }

Hello.vue

  import { TweenMax, TimelineMax, Power3 } from "gsap";
  import { Draggable } from "../vendor/gsap/utils/Draggable.js";

I also tried with only from node_modules, and only from my local vendor folder - both unsuccessfully.

jackdoyle commented 8 years ago

Ah, I think the problem is that you're using { Draggable } instead of just Draggable in your import statement.

//BAD:
import { Draggable } from "../vendor/gsap/utils/Draggable.js";
//GOOD: 
import Draggable from "../vendor/gsap/utils/Draggable.js";
glebmachine commented 8 years ago

@Blueblau Yes, you have used Object destructuring https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring

This is the same like:

var _obj = require('Draggable');
var Draggable = _obj.Draggable;
kluplau commented 8 years ago

@jackdoyle Oh... Thanks... 👍 Still new to ES6... 😆

jackdoyle commented 8 years ago

No problem. Me too!

Iuriy-Budnikov commented 8 years ago

awesome 👍

cgarnier commented 8 years ago

Why do you close it ? gsap is still not working in a standard way with imports. Alias is just a crappy workarround. Just fix your lib. TY

jackdoyle commented 8 years ago

@cgarnier We're not aware of any issues here. Everyone we've spoken to who originally had issues as described above got it working (sometimes they just needed to define an alias in their config file). There isn't really a universal way that works flawlessly in every single build system, but we've done several things to make it workable in the vast majority (if not all) of them while also staying fully compatible with ES5 and "regular" browsers.

Furthermore, it's not as simple as just rebuilding everything in ES6 because there are plenty of caveats with that as well. For example, we're hyper-focused on performance but we've read that ES6 transpilers often introduce nasty slowdowns and bloat the ES5 code. We're still looking into that, but unfortunately it's just not as simple and clean as you might expect ("crappy workaround...just fix your lib"). If you have a specific solution that'd address these concerns, we'd certainly love to see it. In the mean time, we'll keep moving forward and looking for a good ES6-and-ES5-solution-that-doesn't-slow-things-down-or-break-stuff :)

cgarnier commented 8 years ago

Ok, thanks for this explanation