fast-csv icon indicating copy to clipboard operation
fast-csv copied to clipboard

[FEATURE] support in-browser parsing

Open JoeGermuska opened this issue 4 years ago • 6 comments

Parsing or Formatting?

  • [ ] Formatting
  • [x] Parsing

Is your feature request related to a problem? Please describe. I'm looking for a small CSV parsing library that works in web browsers. (There are surprisingly few.) Since fast-csv imports fs, it doesn't fit the bill.

Describe the solution you'd like Only load fs if createFile is going to be used, or only define createFile if fs loads successfully, or...

Describe alternatives you've considered I could use another library, or take advantage of this project's MIT license to adapt the existing code to my needs.

JoeGermuska avatar Aug 03 '20 22:08 JoeGermuska

would be great to get this working in browser

maccman avatar Feb 13 '21 03:02 maccman

A browser version would be very helpful to me as well.

An idea: extract the CSV processing logic into a common library, and then have separate packages for server and browser, which each import the common library and offer interfaces like fs for node and FileReader for browser? Something like fast-csv-node and fast-csv-browser?

mrbrianevans avatar Oct 19 '21 09:10 mrbrianevans

Here's another place where I'm hitting errors when trying to use it in the browser:

function maybeReadMore(stream, state) {
  if (!state.readingMore) {
    state.readingMore = true;
    process.nextTick(maybeReadMore_, stream, state);   // << here
  }
}

Venryx avatar Feb 13 '22 22:02 Venryx

Okay, I seem to have gotten it working in the browser after...

  1. Adding this to my webpack.config.js: (after adding stream-browserify as an npm dependency)
resolve: {
	fallback: {
		stream: require.resolve("stream-browserify"),
	},
},
  1. Adding this to my startup code:
globalThis.process = globalThis.process ?? {};
process.nextTick = function(func, ...args) {
	const func_bound = func.bind(this, ...args);
	setTimeout(func_bound, 0);
};

globalThis["setImmediate" as any] = function(func, ...args) {
	const func_bound = func.bind(this, ...args);
	setTimeout(func_bound, 0);
};

For some reason, I did not need to handle the fs import in my case. (Not sure whether this is due to my not calling certain functions, or whether some dependency in my tree is adding an empty shim for the module.)

Venryx avatar Feb 14 '22 00:02 Venryx

Does the extensive use of very short lived promises (per-row) and NodeJS buffers/streams limit the performance of running this in the browser/ElectronJS?

I've been using @fast-csv/format with shims and found much better performance from writing my own version that runs synchronously. (sub-second vs minutes).

Edit: It looks like this is really a stream-browserify / immediate issue, as process.nextTick() becomes setTimeout(), which must wait for an animation frame at ~60Hz. Maybe there's a trick here with buffering the stream?

Diving a little deeper, I think this is where the shim comes from: https://github.com/defunctzombie/node-process

ted537 avatar Dec 31 '22 00:12 ted537

for parsing, take a look at https://github.com/leeoniya/uDSV

leeoniya avatar Sep 10 '23 13:09 leeoniya