antfu-collective / vite-ssg

Static site generation for Vue 3 on Vite
MIT License
1.35k stars 136 forks source link

Module import during build process #263

Closed BenjaminOddou closed 2 years ago

BenjaminOddou commented 2 years ago

Hello πŸ‘‹ ,

I can't use gsap plugin like morphSVG. It throws me an error like this one

[vite-ssg] An internal error occurred.
[vite-ssg] Please report an issue, if none already exists: https://github.com/antfu/vite-ssg/issues
node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);
          ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/username/Documents/vite-project/node_modules/gsap/MorphSVGPlugin' imported from /Users/username/Documents/vite-project/.vite-ssg-temp/main.mjs
Did you mean to import gsap/MorphSVGPlugin.js?
    at new NodeError (node:internal/errors:371:5)
    at finalizeResolution (node:internal/modules/esm/resolve:416:11)
    at moduleResolve (node:internal/modules/esm/resolve:932:10)
    at defaultResolve (node:internal/modules/esm/resolve:1044:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:422:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:222:40)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36) {
  code: 'ERR_MODULE_NOT_FOUND'

I am importing the module like this in my JS file

import gsap from 'gsap';
import MorphSVGPlugin from "gsap/MorphSVGPlugin";
gsap.registerPlugin(MorphSVGPlugin);

of course I have the premium package activated in my package.json and I am running the last version of the plugin:

"dependencies": {
    "gsap": "npm:@gsap/shockingly@^3.10.4",
  },
  "devDependencies": {
    "vite-ssg": "^0.20.1",
  }

if you already encountered the same problem or if you have an idea, please let me know !

Thank you very much in advance!! πŸ™

Benjamin

userquin commented 2 years ago

@BenjaminOddou check this issue on gsap: https://greensock.com/forums/topic/30526-why-needs-it-to-be-a-mix-of-esm-cjs-imports/#comment-152400

EDIT: check also this entry: https://greensock.com/docs/v3/Installation?checked=core,morphSVG#modules => check NPM / Build Tools, you need to include the extension

imagen

sadeghbarati commented 2 years ago

you can also use gsap dist, without transpile gsap modules

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

no need to add .js if you already using vite . resolve extensions

maybe optimizeDeps.include can help you solve this problem (don't tested).

https://greensock.com/forums/topic/28030-vite-and-gsap-private-npm-plugins-issue-on-vite-repo/

BenjaminOddou commented 2 years ago

Hello @userquin, @sadeghbarati !

Thank you both for your responses !! πŸ™‚ Finally I found that the problem came from a plugin I am using vite-svg-loader. In my vite.config.js file, I defined my import config to raw which was causing a massive bug... so I switched back to the component mode (default mode) and I don't have the issue now ! I keep your responses in case of problems !

export default defineConfig({
  plugins: [
    vue(),
    svgLoader({
      defaultImport: 'component', // I was using 'raw'
      svgo: false // I am disabling svgo to keep my path ids, classes...
    })
  ],
  ...
})

Thank you again for your time !! πŸ™

Benjamin

BenjaminOddou commented 2 years ago

Hello @userquin, @sadeghbarati,

I think I claimed victory too soon ... I have the problem right now again ... which honestly I don't understand 😒 I tried your suggestions and I tried some solutions posted on GSAP forum like:

import { gsap, MorphSVGPlugin } from 'gsap/all' // or 'gsap/all.js'
gsap.registerPlugin(MorphSVGPlugin)

If you have some magic trick to propose it would be great 😌

userquin commented 2 years ago

@BenjaminOddou provide a minimal repro on gh or stackblitz

sadeghbarati commented 2 years ago

for codesandbox you can add box keyword like

https://githubbox.com/BenjaminOddou/minimal-repo

BenjaminOddou commented 2 years ago

hello,

I created this repo : https://stackblitz.com/edit/vue-ylbnq5?file=vite.config.js

I also created a public gitrepo : https://github.com/BenjaminOddou/vue-ylbnq5

userquin commented 2 years ago

@BenjaminOddou cannot install dependencies (is it private?, do I need an account on gsap?):

F:\work\projects\quini\GitHub\issue-repro\vite-ssg-263>npm install
npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/@gsap%2fshockingly - Not found
npm ERR! 404
npm ERR! 404  '@gsap/shockingly@^3.10.4' is not in this registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\userquin\AppData\Local\npm-cache\_logs\2022-06-24T20_34_43_833Z-debug.log
sadeghbarati commented 2 years ago

@BenjaminOddou are you gsap club member ?

head into this link https://greensock.com/docs/v3/Installation#NPM and search

Private registry

BenjaminOddou commented 2 years ago

Hello @userquin, @sadeghbarati,

indeed I am a gsap club member. I updated my example with an "open" plugin (ScrolltoPlugin). You can have it with the regular version of GSAP.

You can fork now my gitHub repo : https://github.com/BenjaminOddou/vite-ssg-bug-gsap_modules

πŸ™‚

sadeghbarati commented 2 years ago

gsap package.json main field

import { gsap } from 'gsap' // refers to dist/gsap.js => compiled code file
import { ScrollTrigger } from 'gsap/dist/ScrollTrigger' // it's better not to use gsap/all just import what you need

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

They use a specific transpile config to transfer gsap source code to compiled one. I do not know if this is correct or not, but I believe some npm packages only have a pre-compiled code format.

if package have compiled files better to use compiled files instead of transpile it again

Nuxt 2 Nuxt 3 Nextjs

BenjaminOddou commented 2 years ago

Hello @sadeghbarati,

I tried to alias like this :

resolve: {
  alias: {
    'gsap/MorphSVGPlugin': `${path.resolve(__dirname, 'node_modules/gsap/dist/MorphSVGPlugin.js')}/`,
  },
},

but I still have the same error during the building process :

> vite-project@0.0.0 prod
> vite-ssg build

[vite-ssg] Build for client...
vite v2.9.12 building for production...
βœ“ 60 modules transformed.
dist/index.html                                2.88 KiB
dist/manifest.webmanifest                      0.80 KiB
dist/ssr-manifest.json                         2.20 KiB
dist/assets/virtual_pwa-register.5acef10f.js   5.53 KiB / gzip: 2.31 KiB
dist/assets/app.1b3f18ec.css                   11.07 KiB / gzip: 2.75 KiB
dist/assets/app.e47a34f9.js                    220.08 KiB / gzip: 87.79 KiB

✨ [vite-plugin-compression]:algorithm=brotliCompress - compressed file successfully: 
dist//Users/user/Documents/vite-project/index.html.br                                2.88kb / brotliCompress: 0.78kb
dist//Users/user/Documents/vite-project/assets/virtual_pwa-register.5acef10f.js.br   5.53kb / brotliCompress: 2.04kb
dist//Users/user/Documents/vite-project/ssr-manifest.json.br                         2.20kb / brotliCompress: 0.54kb
dist//Users/user/Documents/vite-project/assets/app.1b3f18ec.css.br                   11.07kb / brotliCompress: 2.39kb
dist//Users/user/Documents/vite-project/assets/app.e47a34f9.js.br                    220.08kb / brotliCompress: 75.88kb

PWA v0.12.0
mode      generateSW
precache  7 entries (239.55 KiB)
files generated
  dist/sw.js.map
  dist/sw.js
  dist/workbox-c1760cce.js.map
  dist/workbox-c1760cce.js

[vite-ssg] Build for server...
vite v2.9.12 building SSR bundle for production...
βœ“ 28 modules transformed.
.vite-ssg-temp/manifest.webmanifest        0.80 KiB
.vite-ssg-temp/main.mjs                    131.06 KiB
.vite-ssg-temp/assets/style.7a19acc0.css   49.63 KiB

✨ [vite-plugin-compression]:algorithm=brotliCompress - compressed file successfully: 
.vite-ssg-temp/assets/style.7a19acc0.css.br   49.63kb / brotliCompress: 3.84kb
.vite-ssg-temp/main.mjs.br                    131.06kb / brotliCompress: 24.60kb

[vite-ssg] An internal error occurred.
[vite-ssg] Please report an issue, if none already exists: https://github.com/antfu/vite-ssg/issues
node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);
          ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/user/Documents/vite-project/node_modules/gsap/MorphSVGPlugin' imported from /Users/user/Documents/vite-project/.vite-ssg-temp/main.mjs
Did you mean to import gsap/MorphSVGPlugin.js?
    at new NodeError (node:internal/errors:371:5)
    at finalizeResolution (node:internal/modules/esm/resolve:416:11)
    at moduleResolve (node:internal/modules/esm/resolve:932:10)
    at defaultResolve (node:internal/modules/esm/resolve:1044:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:422:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:222:40)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Not sure what to do to solve this problem πŸ˜…

userquin commented 2 years ago

@BenjaminOddou Vite will not load the temp main.mjs module, it will be loaded directly from node, so you cannot use the alias, you should use it via the ES Modules from my comment: https://github.com/antfu/vite-ssg/issues/263#issuecomment-1164701957

https://github.com/antfu/vite-ssg/blob/main/src/node/build.ts#L114

EDIT: will work for client build, but when running the Vite SSR build result (the main.mjs module on temp folder), it is failing since the import is not using the extension and cannot be resolved (check the import in the main.mjs module in the temp folder).

BenjaminOddou commented 2 years ago

@userquin, when setting in my vite.config.js :

build: {
    transpile: ['gsap'],
    ...
  },

and importing in my js file :

import gsap from 'gsap'
import MorphSVGPlugin from 'gsap/MorphSVGPlugin.js'
gsap.registerPlugin(MorphSVGPlugin)

and setting in the package.json file :

{
  "type": "module",
}

I have other errors popping. Not sure that this is the good method to import gsap modules. @sadeghbarati commented on https://github.com/antfu/vite-ssg/issues/263#issuecomment-1166506409 and advised not to use the transpile during build.

sadeghbarati commented 2 years ago

transpile option is not exist in normal vite.config

I just explain that only frameworks (Nuxt, Nextjs), I mentioned above have this capability (transpile esm)

sorry for misunderstanding I just wanted to explain what I realized


when you are using (vite-ssg) you have to import like without alias

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

if (typeof window !== "undefined") {
  gsap.registerPlugin(ScrollTrigger);
}
// or register plugin in vue mounted
userquin commented 2 years ago

@sadeghbarati @BenjaminOddou if gsap and/or ScrollTrigger is using window/navigation inside, the static import must be converted into dynamic import, all code in the main module will go to the main SSR build and will fail when loading it to generate the SSG (if not using jsdom, to enable it just add mock: true on ssgOptions):

import { gsap } from 'gsap'
onMounted(async () => {
  const { ScrollTrigger } = await import('gsap/dist/ScrollTrigger')
  gsap.registerPlugin(ScrollTrigger);
})

or just move that logic to a custom module and use it via dynamic import:


// main.ts
if (typeof window !== "undefined") {
  import('gsap-loader')
}
....

// gsap-loader.ts
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/dist/ScrollTrigger'

gsap.registerPlugin(ScrollTrigger);
userquin commented 2 years ago

The logic behind vite-ssg is the following, there will be 2 + N builds:

The code in the app is shared between all 2 + N builds, that's, the code will be the same but with different contexts.

BenjaminOddou commented 2 years ago

@userquin I tried your suggestions without success 🧐. The first suggestion (wait till it's mounted) gives me this error :

[vite-ssg] An internal error occurred.
[vite-ssg] Please report an issue, if none already exists: https://github.com/antfu/vite-ssg/issues
file:///Users/user/Documents/vite-project/.vite-ssg-temp/main.mjs:263
gsap.timeline();
     ^

TypeError: gsap.timeline is not a function
    at file:///Users/user/Documents/vite-project/.vite-ssg-temp/main.mjs:263:6
    at ModuleJob.run (node:internal/modules/esm/module_job:185:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:281:24)
    at async build (file:///Users/user/Documents/vite-project/node_modules/vite-ssg/dist/chunks/build.mjs:171:87)
    at async Object.handler (file:///Users/user/Documents/vite-project/node_modules/vite-ssg/dist/node/cli.mjs:20:3)

this is weird as gsap.timeline() function is defined in the general gsap package πŸ˜…

and the second suggestion (using a module with gsap-loader.ts) throw me the same error I already have : Cannot find module....

Note : I tried with and without the below option in my vite.config.js file :

  ssgOptions: {
    mock: true,
    ...
  },

Did you succeed to make it work on your side ?

userquin commented 2 years ago

@BenjaminOddou about cannot find module, add the relative path ./ prefix:

// main.ts
if (typeof window !== "undefined") {
  import('./gsap-loader')
}
....

EDIT: I'll will try it later, rn too busy...

EDIT 2: if you're using mock: true, just use the original code using the import from the dist: import { ScrollTrigger } from 'gsap/dist/ScrollTrigger'

BenjaminOddou commented 2 years ago

@userquin I tried without success. I still have the Cannot find module ... gsap/MorphSVGPlugin. No problem, thank you for your help πŸ™‚

userquin commented 2 years ago

@BenjaminOddou use static import using the dist folder: import xxxx from 'gsap/dist/MorphSVGPlugin or just try adding extension import xxxx from 'gsap/MorphSVGPlugin.js.

BenjaminOddou commented 2 years ago

Sorry for the late reply. Here's the solution that's working for me πŸ˜„


import gsap from 'gsap'
import SplitText from 'gsap/SplitText'
import ScrollSmoother from 'gsap/ScrollSmoother'
import ScrollTrigger from 'gsap/ScrollTrigger'

if (process.client) {
  gsap.registerPlugin(SplitText, ScrollSmoother, ScrollTrigger)
}