vite: Build issues with v3. TypeError: Class extends value undefined is not a constructor or null

Describe the bug

After updating to version 3 we started getting the following error in our bundle script:

account_multisig.js:48 Uncaught TypeError: Class extends value undefined is not a constructor or null
    at account_multisig.js:48:41
    at requireAccount_multisig (account_multisig.js:453:2)
    at common-index.js:34:31
    at requireCommonIndex (common-index.js:53:136)
    at requireRpc_errors (rpc_errors.js:10:24)
    at json-rpc-provider.js:20:22
    at requireJsonRpcProvider (json-rpc-provider.js:356:27)
    at index.js:9:29
    at requireProviders (index.js:12:131)
    at requireAccount (account.js:10:21)

This does not occur in v2. It does also not happen while we are in “dev” mode in v3.

It appears to be an issue with how things are being bundled in the newer version- as the new code is unable to create a specific class in a library near-api-js as it used to, and the output code does look a little strange.

Reproduction

https://github.com/lostpebble/vite-class-undefined-error

System Info

System:
    OS: Windows 10 10.0.19044
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 4.29 GB / 15.79 GB
  Binaries:
    Node: 16.15.1 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.5 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
    npm: 8.11.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 104.0.5112.81
    Edge: Spartan (44.19041.1266.0), Chromium (104.0.1293.54)
    Internet Explorer: 11.0.19041.1566
  npmPackages:
    vite: ^3.0.8 => 3.0.8

Used Package Manager

yarn

Logs

No response

Validations

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 13
  • Comments: 22 (4 by maintainers)

Commits related to this issue

Most upvoted comments

It seems it’s related to @rollup/plugin-commonjs v22.

For a workaround, use Esbuild Deps Optimization at Build Time. Set optimizeDeps.disabled = false and build.commonjsOptions.include = [].

I think you forgot to set build.commonjsOptions.include = [] which disables commonjs plugin v22 used inside Vite. https://stackblitz.com/edit/github-g2azcc?file=package.json,vite.config.ts

what is the point of using the Rollup commonjs plugin?

There’s some tree-shaking issues with it but we’re going to make it default in future. See https://vitejs.dev/blog/announcing-vite3.html#esbuild-deps-optimization-at-build-time-experimental

I had an absolute field day with the garbage that this error is, I’ll spare you with the details and tell you how to solve it.

resolve: {
    alias: {
        // Whatever you already had here +
        'near-api-js': 'near-api-js/dist/near-api-js.js',
    },
},

Massive props to the Metaplex team for not adding it in the Vite starter example, but hiding it behind a commit that was done in November to the file itself, not the example. I’ll probably make a PR for them, considering they haven’t done anything about it since November, until then enjoy.

Also, for the Buffer problem here’s my complete config. But you most likely only need the inject part in rollupOptions, the buffer module installed.

import { defineConfig } from 'vite'
import nodePolyfills from "rollup-plugin-node-polyfills";
import inject from '@rollup/plugin-inject'

// https://vitejs.dev/config/
export default defineConfig({
    resolve: {
        alias: {
            stream: "rollup-plugin-node-polyfills/polyfills/stream",
            events: "rollup-plugin-node-polyfills/polyfills/events",
            assert: "assert",
            crypto: "crypto-browserify",
            util: "util",
            http: "stream-http",
            https: "https-browserify",
            url: "url",
            'near-api-js': 'near-api-js/dist/near-api-js.js',
        },
    },
    define: {
        "process.env": process.env ?? {},
    },
    build: {
        target: "es2020",
        rollupOptions: {
            plugins: [inject({ Buffer: ['buffer', 'Buffer'] })],
        },
    },
    optimizeDeps: {
        esbuildOptions: {
            target: "es2020"
        }
    }
})

And inside the index.html before your main bundle.

<script>
    // Global node polyfill.
    window.global = window;
</script>

Ok, I found the issue for my case. It’s because the project is using an old version of Vite (2.x), indirectly imported by quasar. Not sure why a newly-created quasar project will use an old version of quasar toolkit and vite. After manually updating their versions and an override (see here), the issue is gone.

Hope it’s useful for others.

got en error “Uncaught TypeError: EventEmitter is not a constructor” using vite.

anyway, fixed by run npm install events. hope it will help someone.

see https://github.com/mapbox/mapbox-gl-geocoder/issues/441#issuecomment-1021774132

Please check the import and export in the file. 1.check on which file it throwing error 2.console the import and check whether it is undefined or not if not then go ahead 3.remove { } from import statement.

@adueck Solution worked for me.

Checkout this full vite config incase you have any other issues that might be related https://gist.github.com/FbN/0e651105937c8000f10fefdf9ec9af3d

I had to add more config from the link.

I think you forgot to set build.commonjsOptions.include = [] which disables commonjs plugin v22 used inside Vite. https://stackblitz.com/edit/github-g2azcc?file=package.json,vite.config.ts

Thanks so much @sapphi-red ! The vite.config.ts at that stackblitz link is the one thing that got it working perfectly for me. Now I can import cjs stuff and stuff with global and it’s working no problem, using Vite v4. Now I can finally migrate to vite from create-react-app. It would be nice if there was some kind of default that could handle this. That’s a pretty complex config file and hard to come by.

@sapphi-red, is there a simpler/better way to do this in Vite v4?

Here’s the magic vite.config.ts for anyone with this problem:

import { defineConfig } from 'vite';
import { resolve } from 'path';
import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill';
import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfill';
import nodePolyfills from 'rollup-plugin-polyfill-node';
import cjs from '@rollup/plugin-commonjs';

// https://vitejs.dev/config/
export default defineConfig(async ({ mode }) => {
  return {
    server: {
      https: false,
      port: 3000,
      fs: {
        allow: ['../'],
      },
    },
    // envDir: "./env_web",
    plugins: [],
    build: {
      // minify: false,
      // target: "es2015",
      outDir: 'dist_web',
      sourcemap: true,
      commonjsOptions: { include: [] },
      rollupOptions: {
        plugins: [
          // Enable rollup polyfills plugin
          // used during production bundling
          nodePolyfills({
            include: ['node_modules/**/*.js', '../../node_modules/**/*.js'],
          }),
          cjs(),
        ],
      },
    },
    resolve: {
      alias: {
        '@': resolve(__dirname, 'src'),
        process: 'rollup-plugin-node-polyfills/polyfills/process-es6',
        buffer: 'rollup-plugin-node-polyfills/polyfills/buffer-es6',
        events: 'rollup-plugin-node-polyfills/polyfills/events',
        util: 'rollup-plugin-node-polyfills/polyfills/util',
        sys: 'util',
        stream: 'rollup-plugin-node-polyfills/polyfills/stream',
        _stream_duplex:
          'rollup-plugin-node-polyfills/polyfills/readable-stream/duplex',
        _stream_passthrough:
          'rollup-plugin-node-polyfills/polyfills/readable-stream/passthrough',
        _stream_readable:
          'rollup-plugin-node-polyfills/polyfills/readable-stream/readable',
        _stream_writable:
          'rollup-plugin-node-polyfills/polyfills/readable-stream/writable',
        _stream_transform:
          'rollup-plugin-node-polyfills/polyfills/readable-stream/transform',
      },
    },
    optimizeDeps: {
      esbuildOptions: {
        // Node.js global to browser globalThis
        define: {
          global: 'globalThis',
        },
        // Enable esbuild polyfill plugins
        plugins: [
          NodeGlobalsPolyfillPlugin({
            process: true,
          }),
          NodeModulesPolyfillPlugin(),
        ],
      },
    },
  };
});

@val-samonte I have the same issue as you with Buffer becoming undefined. Any workaround?

Edit: I fixed the issue by setting commonjsOptions: { transformMixedEsModules: true, } Source: https://github.com/chnejohnson/vue-dapp/issues/20#issuecomment-973698464