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

Support Vite bundler better #1477

Closed
crutchcorn opened this issue Jan 4, 2023 · 5 comments
Closed

Support Vite bundler better #1477

crutchcorn opened this issue Jan 4, 2023 · 5 comments
Labels
waiting Waiting on OP response

Comments

@crutchcorn
Copy link

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

I'm attempting to use this package with Vite to bundle a React Native Web project. On doing so, it's been quite a challenge to use the .js files with .jsx syntax, as Vite likes the throw the following errors:

vite v4.0.4 building for production...
✓ 152 modules transformed.
[commonjs--resolver] Unexpected token (91:8) in C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/react-native-vector-icons/lib/create-icon-set.js
file: C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/react-native-vector-icons/lib/create-icon-set.js:91:8
89:
90:       return (
91:         <Text selectable={false} {...props}>
            ^
92:           {glyph}
93:           {children}
error during build:
SyntaxError: Unexpected token (91:8) in C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/react-native-vector-icons/lib/create-icon-set.js
    at Object.pp$4.raise (file:///C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/rollup/dist/es/shared/rollup.js:20310:13)
    at Object.pp$9.unexpected (file:///C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/rollup/dist/es/shared/rollup.js:17611:8)
    at Object.pp$5.parseExprAtom (file:///C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/rollup/dist/es/shared/rollup.js:19694:10)
    at Object.pp$5.parseExprSubscripts (file:///C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/rollup/dist/es/shared/rollup.js:19486:19)
    at Object.pp$5.parseMaybeUnary (file:///C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/rollup/dist/es/shared/rollup.js:19452:17)
    at Object.pp$5.parseExprOps (file:///C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/rollup/dist/es/shared/rollup.js:19379:19)
    at Object.pp$5.parseMaybeConditional (file:///C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/rollup/dist/es/shared/rollup.js:19362:19)
    at Object.pp$5.parseMaybeAssign (file:///C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/rollup/dist/es/shared/rollup.js:19329:19)
    at Object.pp$5.parseParenAndDistinguishExpression (file:///C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/rollup/dist/es/shared/rollup.js:19790:28)
    at Object.pp$5.parseExprAtom (file:///C:/Users/crutchcorn/git/Etc/react-native-monorepo-example/apps/vite-react-app/node_modules/rollup/dist/es/shared/rollup.js:19653:41)

Describe the solution you'd like
A clear and concise description of what you want to happen.

While there might be a way to migrate around this, I've spent some time with it and haven't made much headway. The official Vite team themselves suggests moving .js files to .jsx to side-step detection frustrations in doing this.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

I could use patch-package, and likely may do this in the interim, but this wouldn't be much help in the long run.

Additional context
Add any other context or screenshots about the feature request here.

I'm happy to make a PR renaming files to .jsx and fixing any related packaging errors that might arise from this.

@xiongemi
Copy link

xiongemi commented Oct 11, 2023

Actually I figure it out without need to change the file extension. This happens because react-native-vector-icons contains jsx code (e.g. <Text>) inside .js file.

First, I need to add files with .web to the extensions (the order of the item in the array actually matters):

const extensions = [
  '.mjs',
  '.web.tsx',
  '.tsx',
  '.web.ts',
  '.ts',
  '.web.jsx',
  '.jsx',
  '.web.js',
  '.js',
  '.css',
  '.json',
];

Add these extensions to resolve:

export default defineConfig({
...

  resolve: {
    extensions,
...

Then inside defineConfig, I added to optimizeDeps to resolve js files using jsx loader:

  optimizeDeps: {
    esbuildOptions: {
      resolveExtensions: extensions,
      jsx: "automatic",
      loader: { ".js": "jsx" },
    },
  },

When I serve up the web app, I will get this error message:

MaterialCommunityIcon.tsx:49 Error: Dynamic require of "react-native-vector-icons/MaterialCommunityIcons" is not supported

So my web app's index.html, I need to add:

    <style type="text/css">
      @font-face {
        font-family: 'MaterialCommunityIcons';
        src: url('/MaterialCommunityIcons.ttf') format('truetype');
      }
    </style>

Now the serve command is working. However, the build command still does not work with the same error.

I created a rollup plugin:

const rollupPlugin = (matchers: RegExp[]) => ({
  name: 'js-in-jsx',
  load(id: string) {
    if (
      matchers.some((matcher) => matcher.test(id)) &&
      id.endsWith('.js')
    ) {
      const file = readFileSync(id, { encoding: 'utf-8' });
      return esbuild.transformSync(file, { loader: 'jsx', jsx: 'automatic' });
    }
  },
});

Then add this plugin to the vite config:

  build: {
    rollupOptions: {
      plugins: [rollupPlugin([/react-native-vector-icons/])],
    },
  },

Now build command should work.

Another issue I notice:
In the web browser, I got this error:

NavigationContainer.tsx:29 Uncaught ReferenceError: global is not defined

In vite.config.ts, add:

  define: {
    global: "window",
  },

The final vite.config.ts:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import * as esbuild from 'esbuild';
import { readFileSync } from 'fs';

const extensions = [
  '.mjs',
  '.web.tsx',
  '.tsx',
  '.web.ts',
  '.ts',
  '.web.jsx',
  '.jsx',
  '.web.js',
  '.js',
  '.css',
  '.json',
];

const rollupPlugin = (matchers: RegExp[]) => ({
  name: 'js-in-jsx',
  load(id: string) {
    if (matchers.some((matcher) => matcher.test(id)) && id.endsWith('.js')) {
      const file = readFileSync(id, { encoding: 'utf-8' });
      return esbuild.transformSync(file, { loader: 'jsx', jsx: 'automatic' });
    }
  },
});

export default defineConfig({
  cacheDir: '../../node_modules/.vite/techy-jokes-web',
  define: {
    global: 'window',
  },

  resolve: {
    extensions,
    alias: {
      'react-native': 'react-native-web',
    },
  },

  build: {
    rollupOptions: {
      plugins: [rollupPlugin([/react-native-vector-icons/])],
    },
  },

  server: {
    port: 4200,
    host: 'localhost',
  },

  preview: {
    port: 4300,
    host: 'localhost',
  },

  optimizeDeps: {
    esbuildOptions: {
      resolveExtensions: extensions,
      jsx: 'automatic',
      loader: { '.js': 'jsx' },
    },
  },

  plugins: [react()],

  test: {
    globals: true,
    cache: { dir: '../../node_modules/.vitest' },
    environment: 'jsdom',
    include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
  },
});

@achadee
Copy link

achadee commented Oct 26, 2023

Dude I love you! thanks for this!

@johnf
Copy link
Collaborator

johnf commented Oct 28, 2023

I'm not familiar with vite, is there anything we could do in our library to make this more seamless?
Would simply renaming js to hsx solve the issue?

@johnf johnf added the waiting Waiting on OP response label Oct 28, 2023
@crutchcorn
Copy link
Author

Indeed @johnf - I could even test any alpha releases against our production Vite setup and would be happy to make a PR to do so

@andrew-bierman
Copy link

Thanks a ton for the config, this was super helpful!

If anyone faces this same issue with expo vector icons (which is built on top of react-native-vector-icons), you can get the above config working with minimal changes:

  • Update build to use the rollupPlugin for the expo package as well, and transform mixed ES modules (to fix a 'require is not defined' error that occurs post build).
build: {
  commonjsOptions: { transformMixedEsModules: true },
  rollupOptions: {
    plugins: [
      rollupPlugin([/react-native-vector-icons/, /@expo\/vector-icons/]),
    ],
  },
},

@johnf johnf closed this as completed May 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
waiting Waiting on OP response
Projects
None yet
Development

No branches or pull requests

5 participants