Closed NoelJacob closed 1 year ago
I did the following commands
pnpm init svelte@next
pnpm install
pnpm install algosdk
pnpm run dev
Then I get:
I could not add any kind of nodejs polyfills.
I tried few rollup polyfill plugins with vite and also changing vite configurations kit.vite.optimiseDeps.exclude
and kit.vite.ssr.noExternal
but all this throws different errors.
Maybe this is solvable by somehow configuring @rollup/plugin-node-resolve
in vite plugins?
The library works perfectly with Webpack with node-polyfill-webpack-plugin
.
I also could not getting it working with Snowpack or Rollup, although I didn't change their configs much.
My repo with the error.
I'm not familiar with vite, but you will need to add two polyfills for node packages in order for this package to work: buffer
and path-browserify
. You can see where these packages are declared in our webpack config here: https://github.com/algorand/js-algorand-sdk/blob/develop/webpack.config.js. Note that this package expects Buffer
to be a global variable, so just installing the buffer
package won't be enough.
I'm not familiar with vite, but you will need to add two polyfills for node packages in order for this package to work:
buffer
andpath-browserify
. You can see where these packages are declared in our webpack config here: https://github.com/algorand/js-algorand-sdk/blob/develop/webpack.config.js. Note that this package expectsBuffer
to be a global variable, so just installing thebuffer
package won't be enough.
Hello @jasonpaulos: I also ran into this error as well (while working with Reach. You mentioned being unfamiliar with Vite, and so I hope the following either provides clues or helps with suggestions.
I previously encountered an issue where process
was undefined (vite uses import.meta. ...
). Vite's config has a define
section for adding global constants: adding "process.env": someCustomFallbackObject
there worked.
A few Reach-sh
library updates later, this (Buffer) problem surfaced.
buffer
package and added it as a global in the config file.
import { Buffer } from 'buffer';
export default defineConfig({ plugins: [ ... ], define: { "process.env": env, Buffer: Buffer }, ... })
This moved the error message from OP's original report to:
Uncaught TypeError: Cannot read property 'from' of undefined
<img width="579" alt="Screen Shot 2021-07-24 at 5 08 21 PM" src="https://user-images.githubusercontent.com/6107109/126883730-b36629cf-39a4-4748-adc9-a599990b5f02.png">
After finding this thread, I added the following packages (`buffer ^6.0.3` was already installed):
```json
"path-browserify": "^1.0.1",
And the following to my vite.config.js
file:
resolve: {
alias: {
...
path: require.resolve("path-browserify")
},
The error message is unchanged. I hunted through node_modules
and my best guess is that it still can't find Buffer
(since I see references to Buffer.from( ... )
.
Any advice? Cheers for taking the time.
(edit: @jdtzmn [thanks!] was right about my omission, which made my sample a bit confusing)
Knowing nothing about Vite either, wouldn't you have to include the imported Buffer
in your defineConfig
?
import { Buffer } from 'buffer';
export default defineConfig({
plugins: [ ... ],
define: {
"process.env": env,
"Buffer": Buffer // <-- This line
},
...
})
You mentioned that you imported it, but it didn't appear in your code sample 🤷♂️ .
Knowing nothing about Vite either, wouldn't you have to include the imported
Buffer
in yourdefineConfig
?import { Buffer } from 'buffer'; export default defineConfig({ plugins: [ ... ], define: { "process.env": env, "Buffer": Buffer // <-- This line }, ... })
You mentioned that you imported it, but it didn't appear in your code sample 🤷♂️ .
Cheers for the response; I omitted it since the snippets are entirely demonstrative: it was indeed included in the file, which changes the error from
'Buffer' is undefined
to
Uncaught TypeError: Cannot read property 'from' of undefined
Which means the Buffer
import is recognized (using the "global" technique outlined above), but the failure persists around the use of Buffer
as a global variable in the actual packages.
(@jdtzmn :: double edit: I corrected my original post; thank you!)
@MrJackdaw two things to try:
Buffer
override in the alias
section (like with path-browserify
) instead of the define
section.buffer
import, as described in the buffer package's usage section.@jdtzmn Thanks for the suggestion. I tried your suggestion (and a few variations) -- and they ultimately confirmed my suspicion: "buffer" is getting defined, but isn't getting consumed (possibly due to how vite bundles the dev environment).
const Buffer = require("buffer/");
and left Buffer
in the define
global space: no change to error
Buffer
from the global name space and added it to the resolve
space:
...
resolve: {
alias: {
...
Buffer: require("buffer/")
}
}
which changed the error back to Buffer is not defined
Buffer
alias to
...
resolve: {
alias: {
...
Buffer: require.resolve("buffer/")
}
}
which changed the error to a slightly more descriptive error (with the same stack trace in my original post):
Uncaught TypeError: define_Buffer_default.from is not a function
It would seem that both config.resolve.alias
and config.define
can be used for some types of global variables--or their effects are somewhat interchangeable in this case. Vite recommends the use of plugins for advanced custom resolution: I tried a few but never got past the "undefined from
" error.
Hope this gives more insight; cheers again for the help
Hey all,
Generally this would be fixed by using a polyfill for the node.js Buffer
implementation, this can be done the following way:
npm i --save buffer
or yarn add buffer
and in your entry-point of vite doing:
import { Buffer } from 'buffer'
globalThis.Buffer = Buffer
This will ensure that even if you use SSR
it won't try to assert window being present. To have this work this needs to be your entry-point before ever importing this library.
Alternatively you can use rollup-plugin-node-polyfills
in your vite.config
by inserting it into the inputOptions
Hey all,
Generally this would be fixed by using a polyfill for the
node.js Buffer
implementation, this can be done the following way:
npm i --save buffer
oryarn add buffer
and in your entry-point of vite doing:import { Buffer } from 'buffer' globalThis.Buffer = Buffer
This will ensure that even if you use
SSR
it won't try to assert window being present. To have this work this needs to be your entry-point before ever importing this library.Alternatively you can use
rollup-plugin-node-polyfills
in yourvite.config
by inserting it into the inputOptions
Hey @JoviDeCroock, thanks for taking the time. Unfortunately, rollup-plugin-node-polyfills
was one of the first solutions I tried: there's no effect using the rollupInputOptions
, since that is a subset of instructions for the build output.
nodePolyfill
Buffer
issue was unresolved by the changebuffer
with safe-buffer
(made by the same person it seems)
buffer
) will cause a compile error related to buffer
importsbuffer
and its Buffer
class) results in the Buffer.from is not a function
erroralgosdk
(used under the hood by @reach-sh/stdlib
) as well as the Reach library from dependency optimizationIs there ... something I'm missing? Or is there any chance in hell that the sdk will switch over to an explicit polyfill (v.s. global reference) for its Buffer
usage?
This is what is working for me:
yarn add buffer
Replace window.Buffer
when your point of entry mounts (e.g. __layour.svelte
):
import { browser } from '$app/env';
import { onMount } from 'svelte';
onMount(async () => {
if (browser) {
const { Buffer } = await import('buffer')
window.Buffer = Buffer
}
})
algosdk
dynamically. Example:<script lang="ts">
import { onMount } from 'svelte';
let Wallet;
onMount(() => {
if (Wallet) {
return;
}
import('$lib/Wallet.svelte').then(module => {
Wallet = module.default;
)}
});
</script>
{#if Wallet}
<svelte:component this={Wallet} />
{/if}
@MrJackdaw
I finally found the fix for this issue, I'll keep it short and simple, install the following packages:
yarn add @esbuild-plugins/node-globals-polyfill path-browserify
Then in vite.config.js make sure you add:
import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'
import NodeGlobalsPolyfillPlugin from '@esbuild-plugins/node-globals-polyfill'
export default defineConfig({
resolve: {
alias: {
path: 'path-browserify',
},
},
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: 'globalThis'
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
buffer: true
})
]
}
},
})
The key here was the package @esbuild-plugins/node-globals-polyfill
, which later brought the path
issue, which was resolved adding it in the alias, and installing path-browserify
After this, algosdk
is now working fine. Hope it helps!
Some installation instructions for Vite were added to the FAQ page if anyone new is looking https://github.com/algorand/js-algorand-sdk/blob/develop/FAQ.md#it-says-error-cant-resolve-in-the-sdk
With Vite, you would see:
Uncaught ReferenceError: Buffer is not defined
You will have to install buffer
and path-browserify
as dependencies.
In vite.config.js
, specify:
resolve: {
alias: {
path: 'path-browserify';
}
}
In index.html
, add the following:
<script type="module">
import { Buffer } from 'buffer';
window.Buffer = Buffer;
</script>
To utilize the Buffer polyfill in production builds, in vite.config.js
, add:
import inject from '@rollup/plugin-inject';
export default defineConfig({
...,
build: {
rollupOptions: {
plugins: [inject({ Buffer: ['buffer', 'Buffer'] })],
},
},
...
});
This solved the problem in my case.
closing here as the original issue can be solved with relative configFile option added in 1.0.0-next.8:
svelte({configFile:"../svelte.config.js"})
we use algosdk in vue + vite projects frequently!
in truth, it hasnt always been so straight forward getting algosdk to work in this setup so we made a helpful pkg algonautjs
that is ESM native and wraps algosdk.
we also just open-sourced a wallet connection handler lib that supports most all algorand wallets, which you can find here: any-wallet
.
To my knowledge, over the past few months this SDK has eliminated the need for external configuration, so I'm closing this. If someone is still having issues, please comment. It's in our best interest to make using this SDK as easy as possible.
@NoelJacob please give more context for this issue