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

react: Uncaught TypeError: factory is not a function #211

Open
PaRoxUs opened this issue Dec 4, 2024 · 12 comments
Open

react: Uncaught TypeError: factory is not a function #211

PaRoxUs opened this issue Dec 4, 2024 · 12 comments

Comments

@PaRoxUs
Copy link

PaRoxUs commented Dec 4, 2024

Everythign works in dev mode, but if you build without adding:

        exposes: {
          './App': './src/App', // Needed for the build to work
        },

the app won't work and you get Uncaught TypeError: factory is not a function

@gioboa
Copy link
Collaborator

gioboa commented Dec 4, 2024

hi @PaRoxUs which framework are you using? can you create a basic reproduction please?

@PaRoxUs
Copy link
Author

PaRoxUs commented Dec 6, 2024

We are using react, I'll try my best to create an example, but it has to wait ATM.

@gioboa gioboa changed the title Uncaught TypeError: factory is not a function react: Uncaught TypeError: factory is not a function Dec 6, 2024
@sougiovn
Copy link

Got this error once, the cause was that I was using vite-plugin-top-level-await plugin and building for target >chrome87, which doesn't need this plugin.

@gioboa
Copy link
Collaborator

gioboa commented Jan 8, 2025

@PaRoxUs did you solve this issue?

@PaRoxUs
Copy link
Author

PaRoxUs commented Jan 8, 2025

Well, it works if we add the App to the build and I did't have time to create an example with the error.

@gioboa
Copy link
Collaborator

gioboa commented Jan 8, 2025

I'll try to recreate it, so from the remote you are only exposing the components, right?

@PaRoxUs
Copy link
Author

PaRoxUs commented Jan 8, 2025

Its our main app that only host remote components, so it dosen't need to expose any components.

@gioboa
Copy link
Collaborator

gioboa commented Jan 8, 2025

Its our main app that only host remote components, so it dosen't need to expose any components.

Can you share the configurations here please?

@PaRoxUs
Copy link
Author

PaRoxUs commented Jan 8, 2025

import { defineConfig, UserConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { federation } from '@module-federation/vite'
import { dependencies } from './package.json'
import dotenv from 'dotenv'

dotenv.config({
  path: '.env.' + process.env.ENV,
})

export default defineConfig((): UserConfig => {
  return {
    base: process.env.VITE_APP_BASE,
    plugins: [
      react(),
      federation({
        name: 'main',
        filename: 'main.js',
        shared: {
          react: {
            requiredVersion: dependencies.react,
            singleton: true,
          },
          'react-dom': {
            requiredVersion: dependencies['react-dom'],
            singleton: true,
          },
          jotai: {
            requiredVersion: dependencies.jotai,
            singleton: true,
          },
          'react-router-dom': {
            requiredVersion: dependencies['react-router-dom'],
            singleton: true,
          },
          'react-hook-form': {
            requiredVersion: dependencies['react-hook-form'],
            singleton: true,
          },
          '@tanstack/react-query': {
            requiredVersion: dependencies['@tanstack/react-query'],
            singleton: true,
          },
          '@tanstack/react-table': {
            requiredVersion: dependencies['@tanstack/react-table'],
            singleton: true,
          },
        },
        exposes: {
          './App': './src/App',
        },
        remotes: {
          components: {
            type: 'module',
            name: 'components',
            entry: process.env.VITE_REMOTE_URL_COMPONENTS,
            entryGlobalName: 'components',
            shareScope: 'default',
          },


        },
      }),
    ],
    server: {
      host: 'localhost',
      origin: process.env.VITE_APP_BASE,
      port: 5170,
      proxy: {
        '/api': {
          target: 'http://localhost:8054',
          changeOrigin: true,
        },
      },
    },
    build: {
      modulePreload: false,
      target: 'esnext',
      minify: false,
    },
  }
})

@gioboa
Copy link
Collaborator

gioboa commented Jan 8, 2025

you should solve the issue with
modulepreload: true it's the default btw

@OlegSotnikov
Copy link

OlegSotnikov commented Jan 8, 2025

Hey @gioboa
Here is our case (Vue 3.5.13, Vite 6.0.7) with the same behavior: if we don't expose App we get "TypeError: factory is not a function". So, it's not react-specific. My guess: there is something with wrong order of imports if we don't expose App.

import { fileURLToPath, URL } from 'node:url'
import { existsSync } from 'node:fs'

import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import components from 'unplugin-vue-components/vite'
import autoImport from 'unplugin-auto-import/vite'
import { federation } from '@module-federation/vite'
import unheadVite from '@unhead/addons/vite'

import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
//@ts-expect-error
import { StudioUiResolver } from '@appmaster/studio-ui/resolver/index'

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), '')

  return {
    base: env.VITE_BASE_URL,
    server: {
      port: 8080,
      proxy: {
        '/api': { target: 'https://[MASKED]' },
      },
    },
    preview: {
      proxy: {
        '/api': { target: 'https://[MASKED]' },
      },
    },
    optimizeDeps: {
      include: ['qs', 'tailwindcss/plugin', 'naive-ui'],
    },
    build: {
      target: 'esnext',
      sourcemap: true,
    },
    resolve: {
      alias: {
        '@': fileURLToPath(new URL('./src', import.meta.url)),
      },
    },
    plugins: [
      vue(),
      unheadVite(),
      components({
        extensions: ['vue'],
        include: [/\.vue$/, /\.vue\?vue/],
        directoryAsNamespace: true,
        resolvers: [
          NaiveUiResolver(),
          StudioUiResolver({ existsSync, sideEffects: env.NODE_ENV === 'development' }),
        ],
      }),
      autoImport({
        dirs: ['src/use', 'src/store', 'src/utils', 'src/types'],
        imports: [
          'vue',
          'vue-i18n',
          'vue-router',
          {
            'naive-ui': ['useMessage'],
            '@vueuse/rxjs': ['useSubscription'],
          },
        ],
      }),
      federation({
        name: 'base-app',
        filename: 'remoteEntry-[hash].js',
        manifest: true,
        // Uncomment to fix factory is not a function error
        // exposes: {
        //   './App': './src/App.vue',
        // },
        remotes: {
          'mod-auth': {
            type: 'module',
            name: 'mod-auth',
            entry: '/auth/mf-manifest.json',
          },
          'mod-workspace': {
            type: 'module',
            name: 'mod-workspace',
            entry: '/workspace/mf-manifest.json',
          },
        },
        shared: {
          axios: { singleton: true },
          vue: { singleton: true },
          'vue-i18n': { singleton: true },
          'vue-router': { singleton: true },
          dayjs: { singleton: true },
        },
      }),
    ],
  }
})

@OlegSotnikov
Copy link

OlegSotnikov commented Jan 9, 2025

It looks like in our particular case we have an issue with unplugin-auto-import
If we remove it and use manual imports across the project it starts working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants