Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

It seems that dynamic import is not working properly #8196

Closed
doinki opened this issue Dec 2, 2023 · 4 comments
Closed

It seems that dynamic import is not working properly #8196

doinki opened this issue Dec 2, 2023 · 4 comments

Comments

@doinki
Copy link

doinki commented Dec 2, 2023

Reproduction

https://github.com/doinki/remix-dynamic-import

I am using framer motion's LazyMotion to reduce the bundle size.
However, it seems that dynamic import is not applied properly when building remix.

1 2
// components/LazyMotion.tsx
import { LazyMotion as FramerLazyMotion } from 'framer-motion';

const loadFeatures = () => import('./features').then((mod) => mod.default);

export function LazyMotion({ children }: { children: React.ReactNode }) {
  return (
    <FramerLazyMotion features={loadFeatures}>{children}</FramerLazyMotion>
  );
}

// app/root.tsx
<LazyMotion>
  <Outlet />
</LazyMotion>;

System Info

System:
    OS: macOS 14.1.2
    CPU: (10) arm64 Apple M1 Pro
    Memory: 5.15 GB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.10.0 - ~/Library/Caches/fnm_multishells/50799_1701486996760/bin/node
    Yarn: 1.22.19 - ~/Library/Caches/fnm_multishells/50799_1701486996760/bin/yarn
    npm: 10.2.3 - ~/Library/Caches/fnm_multishells/50799_1701486996760/bin/npm
    pnpm: 8.11.0 - ~/Library/Caches/fnm_multishells/50799_1701486996760/bin/pnpm
  Browsers:
    Chrome: 119.0.6045.199
    Edge: 119.0.2151.97
    Safari: 17.1.2
  npmPackages:
    @remix-run/css-bundle: ^2.3.1 => 2.3.1 
    @remix-run/dev: ^2.3.1 => 2.3.1 
    @remix-run/eslint-config: ^2.3.1 => 2.3.1 
    @remix-run/node: ^2.3.1 => 2.3.1 
    @remix-run/react: ^2.3.1 => 2.3.1 
    @remix-run/serve: ^2.3.1 => 2.3.1

Used Package Manager

pnpm

Expected Behavior

A dynamically imported JavaScript files should not be included in the html.

Actual Behavior

A dynamically impored js file is included in the html.
If built using vite, it works properly.

@hi-ogawa
Copy link
Contributor

hi-ogawa commented Dec 3, 2023

Hmm, interesting example.
I initially thought it might be a bug, but this may be a desired (optimized) behavior considering that you have following import chain:

root.tsx -> components/LazyMotion.tsx --> framer-motion (FramerLazyMotion)
                                      \-> components/features.ts --(dynamic)--> framer-motion (domMax)

Since framer-motion (at least a part of it for FramerLazyMotion) is required to render root.tsx, Remix includes such js chunk into modulepreload of initial html response, so I'm not totally surprised if Remix (esbuild?) decides to put FramerLazyMotion and domMax into the same chunk and both are loaded together at initial preload.

If built using vite, it works properly.

I'm wondering what Vite (rollup) would actually do for this scenario. Could you create a demo project to explain the difference and expected behavior?

@doinki
Copy link
Author

doinki commented Dec 4, 2023

https://github.com/doinki/remix-unstable-vite

This is a repository that builds the same using https://remix.run/docs/en/main/future/vite.

1

@hi-ogawa
Copy link
Contributor

hi-ogawa commented Dec 4, 2023

I thought you're were talking about non-Remix project, but you were comparing with Remix's unstable vite, which is even better. Thanks for the quick repro!

Now I see that Vite/Rollup seems smart about this code splitting and unfortunately this might be a known issue/limitation of esbuild-based code splitting evanw/esbuild#2227.

For your use case, I'm not sure any workaround exists either. I was thinking to directly import files like below, but probably framer-motion doesn't allows this since it has strict exports map in the package.json.

// in components/LazyMotion.tsx
import { LazyMotion as FramerLazyMotion } from "framer-motion/dist/es/components/LazyMotion/index.mjs";

// in component/features.ts
import { domMax } from "framer-motion/dist/es/render/dom/features-max.mjs"

@doinki
Copy link
Author

doinki commented Dec 4, 2023

@hi-ogawa
thank you. I tried building with the code you wrote and it seems to be working correctly.
It seems to be an esbuild issue. I will close this post.

@doinki doinki closed this as completed Dec 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants