evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
38k stars 1.14k forks source link

Define variable with slash throws must be a valid identifier #1979

Closed Speedy1991 closed 2 years ago

Speedy1991 commented 2 years ago

Hi! I try to define a variable to fix an import

 define: {
        ...
        'swiper/react/swiper-react': 'swiper/react',
      },

But it throws

error: The define key "swiper/react/swiper-react" must be a valid identifier error: Invalid define value (must be valid JSON syntax or a single identifier): swiper/react

I already tried to wrap it in additional " like this: '"swiper/react/swiper-react"': '"swiper/react"', but it's also throwing:

error: The define key "\"swiper/react/swiper-react\"" must be a valid identifier

The usecase: We use craco for our dev build and esbuild only for our prod build

We have this import in our file: import {Swiper, SwiperSlide} from 'swiper/react/swiper-react';

Swiper wants this import for create-react-app apps docs but this will obviously not work with esbuild

So the right import for esbuild would be swiper/react and I tried to solve this with a define.

Do you have any hint for me to get this working?

hyrious commented 2 years ago
  1. Swiper has "exports" > "./react": "./react/swiper-react.js" in its package.json, which means the correct way to import that file should be import "swiper/react". (I can't understand why people keep using CRA and trying to fix the webpack4 in it.)
  2. The define option can only swap expressions like X, X.Y. It is designed to replace global variables like process.env.NODE_ENV to support packages like react.
  3. If you can not change your code, you can write a plugin to redirect this import path:
name: 'fix-swiper-path',
setup({ onResolve }) {
  onResolve({ filter: /^swiper\/react\/swiper-react\.js$/ }, args => {
    return { path: require.resolve(args.path) }
  })
}
Speedy1991 commented 2 years ago

Thanks for the response! I really appreciate it!

I already thought I would need a plugin and came up with these lines of code

replacePlugin({
          'swiper/react/swiper-react': 'swiper/react',
          'swiper/swiper.min.css': 'swiper/css',
          include: /ScrollSnap.tsx/,
}),

with a slightly patched esbuild-replace-plugin and it's working as expected now.

I can't understand why people keep using CRA and trying to fix the webpack4 in it.

I fully agree with you ;D It was such a pain to build our prod app in CRA (craco makes it not much better) and now it's just <100 lines of codes in esbuild and works as expected.

But sometimes there are 3rd party libraries (like swiper -.-') with separate exports for CRA which are exclusive CRA and don't work with an other bundler

aigoncharov commented 2 years ago

This is what we ended up doing in Flipper

const resolveFbStubsToFbPlugin: Plugin = {
  name: 'resolve-fb-stubs-to-fb',
  setup({onResolve}) {
    onResolve({filter: /fb-stubs/}, (args) => {
      return {
        path: require.resolve(args.path.replace('fb-stubs', 'fb'), {
          paths: [args.resolveDir],
        }),
      };
    });
  },
};