Jump to content
Search Community

GSAP + ScrollTrigger not working with Inertia.js / SSR

marcbelletre test
Moderator Tag

Go to solution Solved by marcbelletre,

Recommended Posts

Hello there,

 

I'm working on a Laravel/Inertia.js app that uses GSAP and ScrollTrigger for multiple components. Everything works perfectly fine until I start the SSR server. 

Inertia.js comes with a command that launches a ssr.js script on the server to render the pages server-side.

php artisan inertia:start-ssr

Right after running this command the SSR server starts and shows the following:

Starting SSR server on port 13714...
Inertia SSR server started.

The problem is that as soon as the SSR server is running I'm starting to get errors from GSAP.

 

Here is what I tried so far:

 

1. Using ES modules

<script>
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'

gsap.registerPlugin(ScrollTrigger)

export default {
  mounted() {
    gsap.to(...)
  }
}
</script>

This works fine in the browser but the SSR server shows the following error:

import { ScrollTrigger } from "gsap/ScrollTrigger.js";
         ^^^^^^^^^^^^^
SyntaxError: Named export 'ScrollTrigger' not found. The requested module 'gsap/ScrollTrigger.js' is a CommonJS module, which may not support all module.exports as named exports.

 

2. Using CommonJS modules

import { gsap } from 'gsap/dist/gsap'
import { ScrollTrigger } from 'gsap/dist/ScrollTrigger'

gsap.registerPlugin(ScrollTrigger)

The SSR server doesn't show any errors but the animations don't work anymore on the page and the browser's console shows the following error:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'registerPlugin')

 

3. Using a slightly different syntax (removing the curly braces from the GSAP import

import gsap from 'gsap/dist/gsap'
import { ScrollTrigger } from 'gsap/dist/ScrollTrigger'

gsap.registerPlugin(ScrollTrigger)

Now the animations work in the browser but the SSR server shows the following error:

TypeError: gsap.registerPlugin is not a function

 

4. Importing GSAP using ES module and ScrollTrigger using CommonJS (yes I tried everything)

import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/dist/ScrollTrigger'

gsap.registerPlugin(ScrollTrigger)

No error from the SSR server but not working from client side with the following error:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'name')
    at Ap (app-5bcb6a14.js:95:11885)
    at app-5bcb6a14.js:95:46479
    at Array.forEach (<anonymous>)
    at Object.registerPlugin (app-5bcb6a14.js:95:46452)
    at Durabilite-74610e63.js:1:143

 

I can't find a way to make it work on both sides (client and server) at the same time. Any idea?

 

I can create a repository with a minimal demo if needed.

 

Thanks!

  • Like 1
Link to comment
Share on other sites

Hey there!

 

I'm afraid I'm not all too clued up on laravel

My guess would be that you'll have to do something similar to next.js where the import looks like this?

import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

if (typeof window !== "undefined") {
  gsap.registerPlugin(ScrollTrigger);
}


If this doesn't help I'd suggest asking some laravel experts over here -  https://laracasts.com/discuss

  • Like 1
Link to comment
Share on other sites

Hi Cassie!

 

Thank you for taking the time to propose a solution.

 

Unfortunately I also tried this but it does not fix the import issue.

import { ScrollTrigger } from "gsap/ScrollTrigger.js";
         ^^^^^^^^^^^^^
SyntaxError: Named export 'ScrollTrigger' not found. The requested module 'gsap/ScrollTrigger.js' is a CommonJS module, which may not support all module.exports as named exports


The problem seems to be related to the import rather than the registerPlugin function. 

I'm using Vite by the way.

 

I'm going to try posting this on the Laracasts forum.

 

Thanks!

Link to comment
Share on other sites

Hi,

 

Are you using Vite's SSR plugin?

https://vite-plugin-ssr.com/

 

Also you could give this a try:

https://vitejs.dev/guide/features.html#dynamic-import

https://vitejs.dev/guide/features.html#glob-import

 

Finally following Cassie's advice to check for the window object you can wrap your code in a dynamic import promise (yeah a bit clunky but it should work):

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

  • Solution

Hi Rodrigo,

 

Thank you for your answer.

 

I'm not using vite-plugin-ssr as Inertia.js already comes with an SSR feature.

 

I ended up moving my GSAP/ScrollTrigger imports to the main app.js file and injecting them using the Vue provide() function.

import { createSSRApp, h } from 'vue'
import { createInertiaApp } from '@inertiajs/vue3'
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'

gsap.registerPlugin(ScrollTrigger)

createInertiaApp({
  setup({ el, App, props, plugin }) {
    const app = createSSRApp({ render: () => h(App, props) })
      .use(plugin)
      .provide('gsap', gsap)
      .provide('ScrollTrigger', ScrollTrigger)

    app.mount(el)
  },
})

 

In the ssr.js file I only imported GSAP without ScrollTrigger.

import { createSSRApp, h } from 'vue'
import { createInertiaApp, Link, Head } from '@inertiajs/vue3'
import createServer from '@inertiajs/vue3/server'
import { gsap } from 'gsap'

createServer(page =>
  createInertiaApp({
    setup({ App, props, plugin }) {
      return createSSRApp({ render: () => h(App, props) })
        .use(plugin)
        .provide('gsap', gsap)
    },
  }),
)

 

Then everytime I need to use GSAP I just inject it inside my component.

<script setup>
import { inject, nextTick, onMounted } from 'vue'

const gsap = inject('gsap')

onMounted(() => {
  nextTick(() => {
    gsap.to(...)
  })
})
</script>

 

Whenever I need to use a standalone ScrollTrigger instance I inject it with a default value set to null and check if it exists before using it. This way it works in the browser but it is ignored by the server.

<script setup>
import { inject, nextTick, onMounted } from 'vue'

const gsap = inject('gsap')
const ScrollTrigger = inject('ScrollTrigger', null)

onMounted(() => {
  nextTick(() => {
    if (ScrollTrigger) {
      ScrollTrigger.create(...)
    }
  })
})
</script>

 

Again thank you for your time :)

Cheers!

  • Thanks 3
Link to comment
Share on other sites

  • 1 month later...

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