require "stream/web" produces warning
zdm opened this issue Β· 21 comments
Hi,
On node v16 it produces experimental warning.
(node:18876) ExperimentalWarning: stream/web is an experimental featur
Could you please use polyfill until stream/web
feature will get stable status?
Also instead of using try/catch
for load stream/web
you can check process.version
and load stream/web
if node version is >= 16.5.0.
I have the same warning with Node v16.8.0. The Web Streams API has been added in Node v16.5.0 but is experimental. I think you should use web-streams-polyfill until the API is stable (streams.cjs).
(node:23167) ExperimentalWarning: stream/web is an experimental feature. This feature could change at any time
at emitExperimentalWarning (node:internal/util:227:11)
at node:stream/web:7:1
at NativeModule.compileForInternalLoader (node:internal/bootstrap/loaders:312:7)
at NativeModule.compileForPublicLoader (node:internal/bootstrap/loaders:252:10)
at loadNativeModule (node:internal/modules/cjs/helpers:41:9)
at Function.Module._load (node:internal/modules/cjs/loader:804:15)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:94:18)
at Object.<anonymous> (/home/regseb/testcase/node_modules/fetch-blob/streams.cjs:7:31)
at Module._compile (node:internal/modules/cjs/loader:1101:14)
stream/web
api will be experimental for a year or more, so we are doomed to see this warning everywhere for a long time. ;-(
I want to use the stream version developers will probably use cuz they are not interchangeable.
you can't pipe data from web-streams-polyfill to node's whatwg:stream
Also instead of using try/catch for load stream/web you can check process.version and load stream/web if node version is >= 16.5.0.
I also use this pkg on other non-nodejs places like Deno - Deno don't have stuff like blob's backed up by the filesystem. so i would prefer not to use version detection.
Deno for instances already have a global stream api... but i doubt this will be long lived, both Deno and Node's blob currently support async blobs and they have the potential to read data from the disc in a async manner, but non have a way of actually getting a blob from the disc yet.
Could you, please, move stream/web
initialization code to the Blob.prototype.stream
function?
Like this:
var initialized;
try {
const { Blob } = require( "buffer" );
if ( Blob && !Blob.prototype.stream ) {
Blob.prototype.stream = function name ( params ) {
if ( !initialized && !globalThis.ReadableStream ) {
initialized = true;
try {
Object.assign( globalThis, require( "stream/web" ) );
}
catch ( error ) {
// TODO: Remove when only supporting node >= 16.5.0
Object.assign( globalThis, require( "web-streams-polyfill/dist/ponyfill.es2018.js" ) );
}
}
let position = 0;
const blob = this;
return new ReadableStream( {
"type": "bytes",
async pull ( ctrl ) {
const chunk = blob.slice( position, Math.min( blob.size, position + POOL_SIZE ) );
const buffer = await chunk.arrayBuffer();
position += buffer.byteLength;
ctrl.enqueue( new Uint8Array( buffer ) );
if ( position === blob.size ) {
ctrl.close();
}
},
} );
};
}
}
catch ( error ) {}
It have been on my mind. we could do something like that.
But we should probably expose a function that can run the initialized part
the stream are needed here also:
Lines 154 to 164 in 0e07457
Yes, or export the function and call it in the stream()
method.
Let's do this, because this warning is really annoying. ;-)
(It is also possible to run NodeJS with the flag --no-warning
)
This project is still quite Browser & Deno friendly and dose not really depend on any built in NodeJS stuff and I would also like to keep it that way.
Deno still lacks ways of creating Blob/Files backed up by the FileSystem. So i'm having thoughts of using this in Deno for another project i have.
So perhaps stream.cjs should expose a global function instead: globalThis._loadStreams()
(b/c .cjs can't use esm export)
I have been thinking of using conditional import with top level await, but that requires node v14.14...
Disable warnings is a bad practice, warnings are useful, but not in our case.
Are you really using deno? I am unable to imagine, where it can be used and what for. Only as hobby. ;-)
Are you really using deno? I am unable to imagine, where it can be used and what for. Only as hobby. ;-)
Yea, I use Deno for some own hoppy stuff. not so much for work.
tried convincing them to use Deno, but that would be a major rework. If i start with a new project/startup then i would try to use Deno instead if possible.
I think the correct way is to export from streams.cjs
function like this:
/* c8 ignore start */
// 64 KiB (same size chrome slice theirs blob into Uint8array's)
const POOL_SIZE = 65536;
var ReadableStream;
module.exports = function getReadableStream () {
if ( !ReadableStream ) {
try {
ReadableStream = require( "stream/web" ).ReadableStream;
}
catch ( error ) {
// TODO: Remove when only supporting node >= 16.5.0
ReadableStream = require( "web-streams-polyfill/dist/ponyfill.es2018.js" ).ReadableStream;
}
try {
const { Blob } = require( "buffer" );
if ( Blob && !Blob.prototype.stream ) {
Blob.prototype.stream = function name ( params ) {
let position = 0;
const blob = this;
return new ReadableStream( {
"type": "bytes",
async pull ( ctrl ) {
const chunk = blob.slice( position, Math.min( blob.size, position + POOL_SIZE ) );
const buffer = await chunk.arrayBuffer();
position += buffer.byteLength;
ctrl.enqueue( new Uint8Array( buffer ) );
if ( position === blob.size ) {
ctrl.close();
}
},
} );
};
}
}
catch ( error ) {}
}
return ReadableStream;
};
And then use it where you need ReadableStream.
And you will not pollute globalThis
.
What do you think?
If you want I can send pull req.
Hey, man, are you alive? Sorry for disturbing you, but let's close this issue and forget about it.
Sry. I have been busy on other projects
Uhm, okey. Why?
I mean not just close, I can send PR with the fix, if you want.
Pls, look at my comment above.
one smaller change could also be to do:
const orig = process.emitWarning
process.emitWarning = () => {}
Object.assign(globalThis, require('node:stream/web'))
process.emitWarning = orig
This is a bad idea to publish stable
release which is depends on unstable
or beta apis.
I think, that web/stream
should be removed from the stable release and moved to the next major pre-release version.
If somebody requires blobs with the streams support he can install pre-release version separately.
Warning, that produced by this module requires attention, and must be removed.
hi, will next version has a fix to this problem?
I think, that
web/stream
should be removed...
with some degree i would be okey with that but i also need a prediction on what is best for the overall eco-system and guess what most ppl will use the most.
I advocate that ppl will prefer the latest version of web/stream
first and formost, just b/c you don't need any polyfills and everyone will be using the same instance of stream π most important
using the native streams by node also have some perf adv over a polyfill in a way that it's faster and can better be converted to from node/whatwg streams + that they are transferable via workers
The problem with web-streams-polyfill and any (native or polyfilled) ReadableStream is that they are not interchangeable with each other, this have been reported a numbers of times, and i have had problem with it myself in streamsaver.js
and some other other streaming zip lib
- MattiasBuelens/web-streams-polyfill#97
- transcend-io/conflux#64
- MattiasBuelens/web-streams-polyfill#75
- MattiasBuelens/web-streams-polyfill#77
to summarize all the above problem with a code example you can't do this kind of things:
import {WritableStream} from 'web-streams-polyfill'
new window.Blob().stream().pipeTo(new WritableStream({ ... })) // throws
new window.Blob().stream().pipeTo(new window.WritableStream({ ... })) // works okey
this is going to throw an error: TypeError: Failed to execute 'pipeTo' on 'ReadableStream': parameter 1 is not of type 'WritableStream'
this will also be a problem if you use two different web-streams-polyfill versions
i depend on web-stream-polyfill v3.0.1 and you have v3.0.2 then we can't interchange streams
import {ReadableStream} from 'web-streams-polyfill@3.0.1'
import {WritableStream} from 'web-streams-polyfill@3.0.2'
new ReadableStream().pipeTo(new WritableStream({}))
this is going to throw the same kind of error: TypeError: Failed to execute 'pipeTo' on 'ReadableStream': parameter 1 is not of type 'WritableStream'
cuz they are not the same instance of streams.
this is the hole underlying problem of why i do not want to bundle node-fetch into a 0 dependency cjs module. cuz we would then have one version and you would be using another.
I would be comfortable with only using web-streams-polyfill if this got fixed
Initially node-fetch created as backend implementation of web api.
It should stay the same.
Blobs with the streams support - is non-standard object, and, as we can see, it brings more problems, then advantages.
Package should stay simple, be 100% compatible with the web fetch, and work without polyfils and other shit.
If somebody need stream - he can use .body
.
and other shit.
Language please!
Blobs with the streams support - is non-standard object
What do you mean by that? stream exist on blob.prototype.stream
Package should stay simple, be 100% compatible with the web fetch
That is what we are doing. staying true to what the spec is all about. Blob is part of fetch. to implement fetch you also need the other components such as Blob, File, FormData AbortSignal, EventTarget etc
it can't be simple and be 100% spec compatible at the same time. if we sacrifice a spec comp stream then it's not 100% spec comp. and some WPT-test would start failing
If somebody need stream - he can use .body.
involving node-fetch should not have anything to do fetch-blob and this issue b/c it's irrelevant.
try to see it as two separate packages. using res.body
is not an option
eventually node-fetch will have whatwg streams as well and it's going to have basically the same thing as fetch-blob and using web/stream as well