Jump to content
Search Community

import { ... } from 'gsap' vs from 'gsap/all'

Friebel test
Moderator Tag

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

Great news gsap is moving to es6! I like treeshaking and keep everything as small as possible! :)

 

However, what I don't understand is what the difference is between importing modules from 'gsap' vs. importing from 'gsap/all'.

So far I was importing modules from 'gsap', but in the docs I read it's better to import from 'gsap/all' for treeshaking sakes. But when I look at the all.js file inside gsap it's importing the modules, like I would do myself when I import directly from 'gsap', because the project structure is build that way, it seems.

 

Both ways work fine in having the same results onscreen, so I just looked at the output bundle size when I build the same project using imports from 'gsap', vs imports from 'gsap/all', and to my surprise there is a big difference in filesize:

Importing from 'gsap': total project bundle here is 547kB

Importing from 'gsap/all': total project bundle here is 612kB

 

So importing from 'gsap/all' results in a 65kB larger bundle!!

Btw, these import line's I'm using:
 

import { TweenLite, TimelineMax, Linear, Back, Sine } from 'gsap/all';

// vs

import { TweenLite, TimelineMax, Linear, Back, Sine } from 'gsap';

 

I thought that would be the other way around, because 'gsap/all' was adviced in the doc. But with this result I'd say it's better to import from 'gsap'.

 

@GreenSock Am I missing something here? What's the reason there is an extra option to import from 'gsap/all' instead of just 'gsap'?

Thanks in advance!

  • Like 1
Link to comment
Share on other sites

@Friebel you're obviously not doing tree shaking. gsap/all exports everything, so it will be bigger during development. 

 

 

// This will be the same size as all previous versions of gsap
import { TweenMax } from "gsap/TweenMax";

// Same thing here. No difference from previous versions of gsap
import "gsap";

// TweenMax has no dependencies here besides TweenLite, so a huge difference
import { TweenMax } from "gsap/all";

 

  • Like 1
Link to comment
Share on other sites

@OSUblake Thanks for your response. I got the feeling you didn't read my full post.

 

If I get you right you're saying that the last line of code in your examples has tree shaking. But that's exactly what I'm doing and wrote in my post:

import { TweenLite, TimelineMax, Linear, Back, Sine } from 'gsap/all';

// vs

import { TweenLite, TimelineMax, Linear, Back, Sine } from 'gsap';

 

And the strange thing is that not the 'gsap/all'-way is resulting in the smallest bundle file size; but importing from 'gsap' results in a 65kB smaller bundle file.

 

But again, I might be missing something here?

Link to comment
Share on other sites

@Friebel I read your post, but I don't know what you're doing. 

 

Check out this example repo. It will generate a visual comparison of the two bundles.

https://github.com/OSUblake/gsap-treeshaking

 

npm install
npm run build

 

Using "gsap"

Parsed size: 118.73 KB

Gzipped size: 38.19 KB

 

Using "gsap/all"

Parsed size: 55.46 KB

Gzipped size: 16.63 KB

 

It could be even smaller, but the unused eases aren't being dropped. Maybe in the next version.

 

@Gordon Freeman you may want to have a look at that repo too.

 

 

To install bonus plugins like the MorphSVGPlugin, look at the folder you download from your account. The latest version finally has a package.json file, but it's still not ideal. Copy the files in the bonus-files-for-npm-users folder to the esm folder, and then uncomment this in the all.js file.

 

/*
import DrawSVGPlugin from "./DrawSVGPlugin.js";
import MorphSVGPlugin from "./MorphSVGPlugin.js";
import Physics2DPlugin from "./Physics2DPlugin.js";
import PhysicsPropsPlugin from "./PhysicsPropsPlugin.js";
import ScrambleTextPlugin from "./ScrambleTextPlugin.js";
import ThrowPropsPlugin from "./ThrowPropsPlugin.js";
import GSDevTools from "./GSDevTools.js";
import SplitText from "./SplitText.js";
import CustomBounce from "./CustomBounce.js";
import CustomEase from "./CustomEase.js";
import CustomWiggle from "./CustomWiggle.js";

export {
	DrawSVGPlugin,
	MorphSVGPlugin,
	Physics2DPlugin,
	PhysicsPropsPlugin,
	ScrambleTextPlugin,
	ThrowPropsPlugin,
	GSDevTools,
	SplitText,
	CustomBounce,
	CustomEase,
	CustomWiggle
}
*/

 

 

Now install that esm folder in your project.

 

DO NOT INSTALL GSAP FROM NPM!!!

 

How to install from a folder or other location

https://docs.npmjs.com/cli/install

 

Or you can create a symlink, and keep reusing the same folder for other projects.

https://docs.npmjs.com/cli/link

 

 

Now import from there, and you should be good.

 

import { 
    TweenMax,
    TimelineMax,
    AttrPlugin,
    CSSPlugin,
    MorphSVGPlugin
} from "gsap/all";

// Ensure modules don't get dropped by tree-shaking
const activated = [
    TweenMax,
    TimelineMax,
    AttrPlugin,
    CSSPlugin,
    MorphSVGPlugin
];

 

 

  • Like 3
Link to comment
Share on other sites

import { TweenLite, TimelineMax, Linear, Back, Sine } from 'gsap/all';

// vs

import { TweenLite, TimelineMax, Linear, Back, Sine } from 'gsap';

 

 

Here's the result of that. "gsap" is the brown/tan bundle, and "gsap/all" is  the blue bundle.

 

Not only is "gsap/all" smaller in size, but everything it imports will be hoisted, making it load it faster. Notice how "node_modules" only appears once for "gsap/all". It appears several times for "gsap"

 

See the Pen ERPNeL by osublake (@osublake) on CodePen

 

 

You can import like this if you want to, just don't expect the file size to be different. It doesn't matter what you do, the output will always be TweenMax with all it's plugins.

 

// Exports everything in TweenMax
import "gsap";

// Exports everything in TweenMax
import TweenMax from "gsap";

// Exports everything in TweenMax
import { TweenMax } from "gsap";

// Exports everything in TweenMax
import TweenMax from "gsap/TweenMax";

// Exports everything in TweenMax
import { TweenMax } from "gsap/TweenMax";

// Exports everything in TweenMax
import { TweenLite, TimelineMax, Linear, Back, Sine } from 'gsap';

// Exports everything in TweenMax
import { TweenLite, TimelineMax, Linear, Back, Sine } from 'gsap/TweenMax';

 

 

Let's just say that those methods are deprecated. This is now the recommended way to import a la carte. 

 

import { 
    TweenMax,
    TimelineMax,
    AttrPlugin,
    CSSPlugin
} from "gsap/all";

// Ensure modules don't get dropped by tree-shaking
const activated = [
    TweenMax,
    TimelineMax,
    AttrPlugin,
    CSSPlugin
];

 

  • Like 2
Link to comment
Share on other sites

@OSUblake 

Thanks for all your effort to explain people what you mean. I just checked your comparison project on github and I see you are using the exact same way I'm using for imports. Like expected, 'cause you're a great programmer  ;) 

 

Looking at your project it makes very clear where our communication went off though: I want to export ES5 to be used in Internet Explorer and other browsers not compatible with es6, and you don't transpile the files, so keep all constants in the output bundles. Just look for 'const' in your files in the dist-folder, they are still there. And that's exactly why people are complaining that IE or uglifyJs don't like this approach; uglifyJs (at least without configuring and especially if you're using the build in webpack-version) is not accepting es6, so hangs on the const's during builds if we don't transpile to es5 first. Constants are not ES5, but ES6, so they throw errors on browsers like IE not supporing ES6.

 

That's why I use Babel now to transpile the greensock modules into ES5 with a webpack import. I could also switch to the UMD folder instead and skip transpiling, because the UMD-folder contains es5 versions, but I'd like to use treeshaking and keep my files as small as possible, so I'd rather use the es6-stuff and let babel transpile what I use.

 

Now we come to the reason I started this thread in the first place and I will try to get my point across again. Hopefully this time I'll be able to explain myself better and get my point across:

 

* In your project we can see that your imports from 'gsap/all' result in a much smaller bundle than importing from 'gsap'. Exactly as what I would expect and what is advised on the greensock website. So that's fine for modern/future browsers, but like said above: this is not es5, and I want es5.

 

So.. en here comes my point:

* in my project, where I (need to) use Babel to transpile the gs-modules to es5, suddenly the result is the other way around: importing from 'gsap/all' results in a 65k larger file than importing from 'gsap', eventhough I'm using the exact same approach for imports and so this should definitely be treeshaking in practise.

 

To me that is totally the opposite as what I would expect. And that's why I started this thread, 'cause eventhough gsap/all is recommended for imports, why should I do that if the resulting webpack bundle is 65kB larger and does the exact same thing?

 

I see in your project tree-shaking is working fine for a project without transpiling. So it's almost like treeshaking is not working at all with the gsap modules if we use babel-loader... I can't really understand why this is. Everything I write since a year now is in pure ES6 and I use babel-loader in webpack to transpile to ES5 in all my projects and it works as expected as far as I know. So something seems to be different in this case we are missing here... I'll further investigate... 

Link to comment
Share on other sites

mmm... it's starting to look like there is something not right on my babel-loader config.

 

Just letting you know in the meantime I'm googling and just stumbled upon this thread:

https://stackoverflow.com/questions/47663486/webpack-3-babel-and-tree-shaking-not-working

explaining what might be the solution to the problem I'm facing: babel is transpiling everything to ES5, but Webpack only does treeshaking on ES6 modules, so it looks like I need to set { modules: false } on babel-loader in order to output ES6 modules with ES5 content, so Webpack still sees ES6-modules and can use that to shake the trees. If that's the case, so treeshaking isn't working now, probably a lot of my other projects will become a lot smaller too... that would be a nice plus side effect...

But let's first find out if this is really the case... ** to be continued ** :)  

  • Like 1
Link to comment
Share on other sites

I changed my .babelrc to this now and with some little testing I see it's making treeshaking work if I just create a small project and import some functions from a file. So for this it's fixing treeshaking with using Babel.

{
  "presets": [
    ["env", {
      "modules": false
    }]
  ]
}

 

But for some strange reason in my project the bundle output filesize is still larger when I import from 'gsap/all' instead of from 'gsap'. Probably I have another mistake somewhere or something else I don't know about or am aware of. It's getting late now, so that's for another day :)

Link to comment
Share on other sites

Sorry, I guess I should have pointed out that tree shaking is done by webpack or rollup, and will only work with ES6 modules, so Babel should not transform the modules. Maybe @GreenSock can update the docs to explain some of that.

https://webpack.js.org/guides/tree-shaking/

https://webpack.js.org/loaders/babel-loader/

https://rollupjs.org/guide/en#danger-zone

 

Preventing Babel from transforming the modules might not possible for some tools, like create react app, but you could still import each module individually.

 

import TweenMax from "gsap/TweenMaxBase";
import TimelineMax from "gsap/TimelineMax";
import AttrPlugin from "gsap/AttrPlugin";
import CSSPlugin from "gsap/CSSPlugin";

const activated = [
    TweenMax,
    TimelineMax,
    AttrPlugin,
    CSSPlugin
];

 

 

  • Like 1
Link to comment
Share on other sites

Yes! Today I had some minutes to look at it again and with fresh eyes I saw in my code there were still some classes left were I forgot to change 'gsap' into 'gsap/all'. Crazy, I know. Silly me. Now everything is working as expected!

 

Before the bundle was 547kB by importing from 'gsap', now it's 474kB by switching to 'gsap/all'! That is what I like to see! Nice! I like it.

 

So to conclude: adding { modules: false } to the babel config was the only thing needed to make this thing work with treeshaking. 

 

In the meantime I took the time to switch from Webpack 3 to 4, which makes building even faster, and invested some time to really dig through the workings of

webpack, resulting in an even better and smaller conditional config. I can say this was an educational experience! :) 

 

Thanks for your help @OSUblake and others via the other thread,

 

Happy with the new gsap 2.0.1. It was fine to bump against trees without something falling out before, but my new setup gets the coconuts it needs from the trees now!


Case closed! :) 

  • Like 2
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...