remorses/esbuild-plugins

(In)compatibility with vite 4

AntonOfTheWoods opened this issue ยท 32 comments

This might well not be the right place to submit a bug report, though could be useful as a record of workarounds.

It appears that these are no longer compatible with vite 4.

https://stackblitz.com/edit/vitejs-vite-va6gek?file=vite.config.js&terminal=dev

Yep, Vite 4 would at least still run/compile with errors, but 4.0.2 just outright dies now...
Screen Shot 2022-12-18 at 12 25 03 PM

We have the same issue.

I only notice the issue with @esbuild-plugins/node-globals-polyfill, and not with @esbuild-plugins/node-modules-polyfill. The others I have no idea.

Having the same issue as @timothyallan

Having the same issue since upgrading to Vite 4

Having the same issue after upgrading to Vite 4

I am using this for the Nuxt3 project so my workaround for this to work with Vite 4 is

Keep the local copy Buffer.js and process.js from this repo inside the project's utils directory

// nuxt.config.ts

import path from 'path'
import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfill'
import { defineNuxtConfig } from 'nuxt/config'

const polyfills = []
polyfills.push(path.resolve(__dirname, './utils/Buffer.js'))
polyfills.push(path.resolve(__dirname, './utils/process.js'))

export default defineNuxtConfig({
   vite: {
    optimizeDeps: {
      include: ['./utils/Buffer.js', './utils/process.js', 'bn.js', 'js-sha3', 'hash.js', 'aes-js', 'scrypt-js', 'bech32', '@web3-onboard/walletconnect'],
      esbuildOptions: { inject: [...polyfills], plugins: [ NodeModulesPolyfillPlugin() ] }
    }
  }
})

This does give a warning for Buffer.js and process.js but works just fine

โœ˜ [ERROR] The injected path ".../Buffer.js" cannot be marked as external
โœ˜ [ERROR] The injected path ".../process.js" cannot be marked as external

Any update?

same issue, help ๐Ÿ˜ญ

bluwy commented

This is an upstream bug from evanw/esbuild#2762. A workaround for now is a custom esbuild plugin like:

import { defineConfig } from 'vite'
import NodeModulesPolyfills from '@esbuild-plugins/node-modules-polyfill'

export default defineConfig({
  optimizeDeps: {
    esbuildOptions: {
      plugins: [
        NodeModulesPolyfills.default(),
        {
          name: 'fix-node-globals-polyfill',
          setup(build) {
            build.onResolve(
              { filter: /_virtual-process-polyfill_\.js/ },
              ({ path }) => ({ path })
            )
          }
        }
      ]
    }
  }
})

Hi,
I'm on sveltekit which now uses vite 4 too. I am using socket.io (buffer and process) and had same error messages.

@bluwy 's workaround didn't work for me at all
but @itsmnthn did, in dev only, but solved the build part by including process and buffer in aliases.

here is my full working vite.config.ts file :

import { sveltekit } from '@sveltejs/kit/vite'
import type { UserConfig } from 'vite'

import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill'
import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfill'
import rollupNodePolyFill from 'rollup-plugin-node-polyfills'

// polyfills inject workaround for vite 4 incompatibility
// https://github.com/remorses/esbuild-plugins/issues/24  for solving dev error
// https://stackoverflow.com/questions/72773373/buffer-is-not-exported-by-vite-browser-externalbuffer for solving build error

import path from 'path'
const polyfills = []
polyfills.push(path.resolve(__dirname, './utils/Buffer.js'))
polyfills.push(path.resolve(__dirname, './utils/process.js'))

const config: UserConfig = {
	plugins: [sveltekit()],
	resolve: {
		//alias: [{ find: '@', replacement: '/src' }],
		alias: {
			// This Rollup aliases are extracted from @esbuild-plugins/node-modules-polyfill,
			// see https://github.com/remorses/esbuild-plugins/blob/master/node-modules-polyfill/src/polyfills.ts
			// process and buffer are excluded because already managed
			// by node-globals-polyfill
			util: 'rollup-plugin-node-polyfills/polyfills/util',
			sys: 'util',
			events: 'rollup-plugin-node-polyfills/polyfills/events',
			stream: 'rollup-plugin-node-polyfills/polyfills/stream',
			path: 'rollup-plugin-node-polyfills/polyfills/path',
			querystring: 'rollup-plugin-node-polyfills/polyfills/qs',
			punycode: 'rollup-plugin-node-polyfills/polyfills/punycode',
			url: 'rollup-plugin-node-polyfills/polyfills/url',
			string_decoder: 'rollup-plugin-node-polyfills/polyfills/string-decoder',
			http: 'rollup-plugin-node-polyfills/polyfills/http',
			https: 'rollup-plugin-node-polyfills/polyfills/http',
			os: 'rollup-plugin-node-polyfills/polyfills/os',
			assert: 'rollup-plugin-node-polyfills/polyfills/assert',
			constants: 'rollup-plugin-node-polyfills/polyfills/constants',
			_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',
			timers: 'rollup-plugin-node-polyfills/polyfills/timers',
			console: 'rollup-plugin-node-polyfills/polyfills/console',
			vm: 'rollup-plugin-node-polyfills/polyfills/vm',
			zlib: 'rollup-plugin-node-polyfills/polyfills/zlib',
			tty: 'rollup-plugin-node-polyfills/polyfills/tty',
			domain: 'rollup-plugin-snode-polyfills/polyfills/domain',
			buffer: 'rollup-plugin-node-polyfills/polyfills/buffer-es6',
			process: 'rollup-plugin-node-polyfills/polyfills/process-es6'
		}
	},
	optimizeDeps: {			
		esbuildOptions: {
			// polyfills inject workaround for vite 4 incompatibility
			inject: [...polyfills],
			// Node.js global to browser globalThis
			define: {
				global: 'globalThis'
			},
			// Enable esbuild polyfill plugins
			plugins: [
				NodeModulesPolyfillPlugin()
			]
		}
	},
	build: {		
		rollupOptions: {
			plugins: [
				// Enable rollup polyfills plugin
				rollupNodePolyFill()
			]
		}
	}
}

export default config

thanks!

I am having same issue.

Facing the same issue here, @robotpapier's workaround made it work.

Is there any ETA on an update to fix this?

This is an upstream bug from evanw/esbuild#2762. A workaround for now is a custom esbuild plugin like:

import { defineConfig } from 'vite'
import NodeModulesPolyfills from '@esbuild-plugins/node-modules-polyfill'

export default defineConfig({
  optimizeDeps: {
    esbuildOptions: {
      plugins: [
        NodeModulesPolyfills.default(),
        {
          name: 'fix-node-globals-polyfill',
          setup(build) {
            build.onResolve(
              { filter: /_virtual-process-polyfill_\.js/ },
              ({ path }) => ({ path })
            )
          }
        }
      ]
    }
  }
})

Property 'default' does not exist on type '(options?: NodePolyfillsOptions) => Plugin'.ts(2339)

@Terkea Try using NodeModulesPolyfills(), without the .default.

@Terkea literally used the workaround yesterday and asked my self the same question ๐Ÿ˜‰. Here without default.

import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfill';

plugins: [
    NodeModulesPolyfillPlugin(),
    {
        name: 'fix-node-globals-polyfill',
        setup(build) {
             build.onResolve({ filter: /_virtual-process-polyfill_\.js/ }, ({ path }) => ({ path }));
        }
   }
]

@Terkea literally used the workaround yesterday and asked my self the same question ๐Ÿ˜‰. Here without default.

import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfill';

plugins: [
    NodeModulesPolyfillPlugin(),
    {
        name: 'fix-node-globals-polyfill',
        setup(build) {
             build.onResolve({ filter: /_virtual-process-polyfill_\.js/ }, ({ path }) => ({ path }));
        }
   }
]

Thank you for the prompt response, I have tried this and I still get some errors. FYI I have the index.html window.Buffer bit

Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/buffer.js?v=92178562' does not provide an export named 'default' (at index.html:10:14)
asymmetricKeyDetailsSupported.js:3 Uncaught ReferenceError: process is not defined
    at node_modules/jsonwebtoken/lib/asymmetricKeyDetailsSupported.js (asymmetricKeyDetailsSupported.js:3:35)
    at __require (chunk-OL3AADLO.js?v=2548af80:9:50)
    at node_modules/jsonwebtoken/lib/validateAsymmetricKey.js (validateAsymmetricKey.js:1:42)
    at __require (chunk-OL3AADLO.js?v=2548af80:9:50)
    at node_modules/jsonwebtoken/verify.js (verify.js:6:31)
    at __require (chunk-OL3AADLO.js?v=2548af80:9:50)
    at node_modules/jsonwebtoken/index.js (index.js:2:11)
    at __require (chunk-OL3AADLO.js?v=2548af80:9:50)
    at index.js:12:2

This is an upstream bug from evanw/esbuild#2762. A workaround for now is a custom esbuild plugin like:

import { defineConfig } from 'vite'
import NodeModulesPolyfills from '@esbuild-plugins/node-modules-polyfill'

export default defineConfig({
  optimizeDeps: {
    esbuildOptions: {
      plugins: [
        NodeModulesPolyfills.default(),
        {
          name: 'fix-node-globals-polyfill',
          setup(build) {
            build.onResolve(
              { filter: /_virtual-process-polyfill_\.js/ },
              ({ path }) => ({ path })
            )
          }
        }
      ]
    }
  }
})

Property 'default' does not exist on type '(options?: NodePolyfillsOptions) => Plugin'.ts(2339)

Same issue when doing

plugins: [
        NodeModulesPolyfills.default(),
        {
          name: "fix-node-globals-polyfill",
          setup(build) {
            build.onResolve(
              { filter: /_virtual-process-polyfill_\.js/ },
              ({ path }) => ({ path })
            );
          },
        },
      ],

Property 'default' does not exist on type '(options?: NodePolyfillsOptions) => Plugin'.ts(2339)

I have put together a POC for this https://stackblitz.com/edit/vitejs-vite-rm3gjc?file=package.json

Regarding buffer, in one of my SvelteKit app I solved it by npm i buffer and adds following in main +layout.ts. Hope it helps.

import { Buffer } from "buffer";
globalThis.Buffer = Buffer;

@Terkea just do NodeModulesPolyfills()

Fixed in latest version

@remorses I am using versions

    "@esbuild-plugins/node-globals-polyfill": "0.2.1",
    "@esbuild-plugins/node-modules-polyfill": "0.2.0",

and still, get the same error

โœ˜ [ERROR] The injected path "/Users/marian/tools/test/vite-project/node_modules/@esbuild-plugins/node-globals-polyfill/_buffer.js" cannot be marked as external

Build failed with 1 error:
error: The injected path "/Users/marian/tools/test/vite-project/node_modules/@esbuild-plugins/node-globals-polyfill/_buffer.js" cannot be marked as external

I'm getting the same as well.

Can you share a repro? The plugin now works with latest esbuild maybe VIte is doing something weird with externals

Can you share a repro? The plugin now works with latest esbuild maybe VIte is doing something weird with externals

https://stackblitz.com/edit/vitejs-vite-hfzps4?file=index.html,src%2FApp.tsx,vite.config.ts&terminal=dev

bluwy commented

I think further down with the _buffer.js error, you can workaround with:

{
  name: 'fix-node-globals-polyfill',
  setup(build) {
    build.onResolve(
      { filter: /_buffer\.js/ },
      ({ path }) => ({ path })
    )
  }
}

too. But I haven't really investigate why this is needed yet.

Should this be reopened, as it specifically deals with vite 4?

found a solution that works for me

        "@esbuild-plugins/node-globals-polyfill": "0.2.3",
        "@esbuild-plugins/node-modules-polyfill": "0.2.2",
        "rollup-plugin-node-polyfills": "^0.2.1",
        "util": "^0.12.5",

vite.config.ts

// yarn add --dev @esbuild-plugins/node-globals-polyfill
import { NodeGlobalsPolyfillPlugin } from "@esbuild-plugins/node-globals-polyfill";
// yarn add --dev @esbuild-plugins/node-modules-polyfill
import { NodeModulesPolyfillPlugin } from "@esbuild-plugins/node-modules-polyfill";
// You don't need to add this to deps, it's included by @esbuild-plugins/node-modules-polyfill
import rollupNodePolyFill from "rollup-plugin-node-polyfills";
import react from "@vitejs/plugin-react";
import tsconfigPaths from "vite-tsconfig-paths";

export default {
    plugins: [
        react(),
        tsconfigPaths(),
        {
            name: "fix-node-globals-polyfill",
            setup(build) {
                build.onResolve({ filter: /util\.js/ }, ({ path }) => ({ path }));
            },
        },
    ],
    resolve: {
        alias: {
            // This Rollup aliases are extracted from @esbuild-plugins/node-modules-polyfill,
            // see https://github.com/remorses/esbuild-plugins/blob/master/node-modules-polyfill/src/polyfills.ts
            // process and buffer are excluded because already managed
            // by node-globals-polyfill
            util: "util",
            sys: "util",
            events: "rollup-plugin-node-polyfills/polyfills/events",
            stream: "rollup-plugin-node-polyfills/polyfills/stream",
            path: "rollup-plugin-node-polyfills/polyfills/path",
            querystring: "rollup-plugin-node-polyfills/polyfills/qs",
            punycode: "rollup-plugin-node-polyfills/polyfills/punycode",
            url: "rollup-plugin-node-polyfills/polyfills/url",
            string_decoder: "rollup-plugin-node-polyfills/polyfills/string-decoder",
            http: "rollup-plugin-node-polyfills/polyfills/http",
            https: "rollup-plugin-node-polyfills/polyfills/http",
            os: "rollup-plugin-node-polyfills/polyfills/os",
            assert: "rollup-plugin-node-polyfills/polyfills/assert",
            constants: "rollup-plugin-node-polyfills/polyfills/constants",
            _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",
            timers: "rollup-plugin-node-polyfills/polyfills/timers",
            console: "rollup-plugin-node-polyfills/polyfills/console",
            vm: "rollup-plugin-node-polyfills/polyfills/vm",
            zlib: "rollup-plugin-node-polyfills/polyfills/zlib",
            tty: "rollup-plugin-node-polyfills/polyfills/tty",
            domain: "rollup-plugin-node-polyfills/polyfills/domain",
        },
    },
    optimizeDeps: {
        esbuildOptions: {
            // Node.js global to browser globalThis
            define: {
                global: "globalThis",
            },
            // Enable esbuild polyfill plugins
            plugins: [
                NodeGlobalsPolyfillPlugin({
                    process: true,
                    buffer: true,
                }),
                NodeModulesPolyfillPlugin(),
            ],
        },
    },
    build: {
        rollupOptions: {
            plugins: [
                // Enable rollup polyfills plugin
                // used during production bundling
                rollupNodePolyFill(),
            ],
        },
    },
};

should be fixed in latest version, if not open a new issue please

DevDcx commented

This is not fixed . Trying to import Twilio into a Vite + Vue3 Project.

instead of using esbuild plugin, I ended up using rollup

build: {
    rollupOptions: {
      plugins: [
        // this is the working way for Vite 3, in Vite 4 we use a esbuild plugin instead
        inject({
          Buffer: ['Buffer', 'buffer'],
        }),
      ],
    },
  },

In Vite esbuild plugins only run for your node_modules files