How to Polyfill node core modules using vite
Asked Answered
I

3

7

It seems that vite does not do automatic polyfills anymore - vite 4.0.0

How do you guys go about this? I have tried multiple variations of what I could find over the internet and none of them seems to be solid.

✘ [ERROR] The injected path "/Users/marian/code/OzoneV2/app-web/node_modules/@esbuild-plugins/node-globals-polyfill/_buffer.js" cannot be marked as external

✘ [ERROR] The injected path "/Users/marian/code/OzoneV2/app-web/node_modules/@esbuild-plugins/node-globals-polyfill/_virtual-process-polyfill_.js" cannot be marked as external

Build failed with 2 errors:
error: The injected path "/Users/marian/code/OzoneV2/app-web/node_modules/@esbuild-plugins/node-globals-polyfill/_buffer.js" cannot be marked as external
error: The injected path "/Users/marian/code/OzoneV2/app-web/node_modules/@esbuild-plugins/node-globals-polyfill/_virtual-process-polyfill_.js" cannot be marked as external

my config

// 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";

export default {
    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: "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-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(),
            ],
        },
    },
};

Interplead answered 24/1, 2023 at 10:33 Comment(0)
M
8

Try using the npm package vite-plugin-node-polyfills.

Install the package via npm install --save-dev vite-plugin-node-polyfills, then add the plugin to your vite.config.ts file.

import { defineConfig } from 'vite'
import { nodePolyfills } from 'vite-plugin-node-polyfills'

export default defineConfig({
  plugins: [
    nodePolyfills(),
  ],
});

See the package repo for full customisation options: for example, you can also include only the polyfills that are relevant to your project.

plugins: [
  nodePolyfills({ include: ['fs', 'stream'] }),
],
Mart answered 1/2 at 11:1 Comment(2)
This is a godlike response for those looking to use libraries like Jotai or make client side calls from React Remix applications that are packed with Vite. If you're in that position, make sure you only include stream and you're good to go!Highgrade
Hello @Mart , I was trying to polyfill the os function because I settled protocolImports: true in my vite.config.ts , but when in App.tsx I implement import os from 'node:os'; console.log ( os.arch() ) it compiles even with a warning [plugin:vite:resolve] [plugin vite:resolve] Module "node:os" has been externalized for browser compatibility, imported by .... and when I build and then run on browser, it reports Uncaught (in promise) TypeError: Md.arch is not a function , but if I open node and run os.arch() it returns me the architecture....Abominate
A
0

I tried to use vite-plugin-node-polyfills but trying to make a sample like:

function useReturnStdOut() { 
  const [localArch,setLocalArch] = useState<string | null>(null); 
 
  const getData = async()=>{  
 
    exec.exec("ls", (error, stdout, stderr) => { 
      if (error) { 
        console.error(`exec error: ${error}`); 
        return; 
      } 
      if (stdout) { 
        console.log(`stdout: ${stdout}`); 
        setLocalArch(stdout); 
      } 
      if (stderr) { 
        console.error(`stderr: ${stderr}`);   
      } 
    });  
 
  } 
   
  useEffect(() => { 
    getData(); 
  }, [localArch]); 
 
  return localArch; 
} 

running on host from my mobile phone and debugging it I face always this error : Uncaught (in promise) TypeError: Cannot read properties of null (reading 'exec') even if I check if the arguments , stdout - stderr - error, exists ..... maybe shall I have missed something about this library even if I call it asynchronously?...

thanks in advance!

Abominate answered 5/9 at 9:45 Comment(0)
C
-1

I encountered the same issue "cannot be marked as external" when working with the bip39 package and getting error because of buffer not defined. I tried many stuffs so not sure how what I solved, but here is my configuration (working with svelteKit):

In vite.config.js:

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

const config: UserConfig = {
    plugins: [sveltekit()],

    resolve: {
        alias: {
            // polyfills
            Buffer: 'vite-compatible-readable-buffer',
            stream: 'vite-compatible-readable-stream',
            util: 'rollup-plugin-node-polyfills/polyfills/util',
        }
    }
};
export default config;

In layout.ts:

import { Buffer as BufferPolyfill } from 'buffer'

declare var Buffer: typeof BufferPolyfill; globalThis.Buffer = BufferPolyfill

In app.html:

<script>
    /**
     * this is a hack for error: global is not defined
     */
    var global = global || window
</script>

I hope it helps. I'm new to svelte and I don't 100% know what I'm doing :p

Cordeelia answered 24/1, 2023 at 20:40 Comment(5)
✘ [ERROR] Could not read from file: /home/projects/vitejs-vite-rm3gjc/rollup-plugin-node-polyfills/polyfills/util node_modules/jws/lib/verify-stream.js:7:19: 7 │ var util = require('util'); any idea why do I get this error?Interplead
stackblitz.com/edit/…Interplead
npmjs.com/package/rollup-plugin-node-polyfillsCordeelia
the module is installed; same errorInterplead
Strange because when I installed it in your stackblitz, it worked. Sorry for late reply, I was on holiday. Let me know if you still need helpCordeelia

© 2022 - 2024 — McMap. All rights reserved.