renderToStream causes error in some cases.
Version
3.0.11
Reproduction link
https://replit.com/@07akioni/vuessr
Steps to reproduce
Follow the link.
const { createApp, resolveComponent, h } = require("vue");
const { renderToStream: _renderToStream } = require("@vue/server-renderer");
const app = createApp({
render() {
const Foo = resolveComponent("foo");
return h(Foo);
},
});
app.component("foo", {
render: () => h("div", "foo"),
});
const promisifyStream = (stream) => {
return new Promise((resolve, reject) => {
let result = "";
console.log("ondata");
stream.on("data", (data) => {
result += data;
});
stream.on("error", () => {
reject(result);
});
stream.on("end", () => {
resolve(result);
});
});
};
const renderToStream = (app) => promisifyStream(_renderToStream(app));
renderToStream(app).then((v) => {
console.log(v);
});
What is expected?
No error.
What is actually happening?
internal/streams/readable.js:642
throw new ERR_METHOD_NOT_IMPLEMENTED('_read()');
^
Error [ERR_METHOD_NOT_IMPLEMENTED]: The _read() method is not implemented
at Readable._read (internal/streams/readable.js:642:9)
at Readable.read (internal/streams/readable.js:481:10)
at resume_ (internal/streams/readable.js:968:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21) {
code: 'ERR_METHOD_NOT_IMPLEMENTED'
}
It's wired that in stackbliz web container and vue's jest test there is no error.
I found that the reason why the tests passed is jest mutates Promise. Emmm...
@posva The original example is simplified to help people find the crucial part.
I've update it. Now it is the original logic extracted from a vue test case. The error happens in the same way.
the code sample runs fine in node 14:
// index.mjs
import { createApp, resolveComponent, h } from 'vue'
import { renderToStream as _renderToStream } from '@vue/server-renderer'
const app = createApp({
render() {
const Foo = resolveComponent('foo')
return h(Foo)
},
})
app.component('foo', {
render: () => h('div', 'foo'),
})
const promisifyStream = (stream) => {
return new Promise((resolve, reject) => {
let result = ''
console.log('ondata')
stream.on('data', (data) => {
result += data
})
stream.on('error', () => {
reject(result)
})
stream.on('end', () => {
resolve(result)
})
})
}
const renderToStream = (app) => promisifyStream(_renderToStream(app))
renderToStream(app).then((v) => {
console.log(v)
})
Do you have a boiled down reproduction that fails?
the code sample runs fine in node 14:
// index.mjs import { createApp, resolveComponent, h } from 'vue' import { renderToStream as _renderToStream } from '@vue/server-renderer' const app = createApp({ render() { const Foo = resolveComponent('foo') return h(Foo) }, }) app.component('foo', { render: () => h('div', 'foo'), }) const promisifyStream = (stream) => { return new Promise((resolve, reject) => { let result = '' console.log('ondata') stream.on('data', (data) => { result += data }) stream.on('error', () => { reject(result) }) stream.on('end', () => { resolve(result) }) }) } const renderToStream = (app) => promisifyStream(_renderToStream(app)) renderToStream(app).then((v) => { console.log(v) })
Do you have a boiled down reproduction that fails?
.mjs
works for me too. However please try cjs. My node version is v14.17.0.
https://github.com/07akioni/vue-ssr-bug-reprod (the same example)
The mjs
and cjs
modes seem to have some difference underhood.
➜ vue-ssr git:(main) NODE_DEBUG=stream node work.mjs
STREAM 75760: resume
STREAM 75760: readableAddChunk <div>foo</div>
STREAM 75760: readableAddChunk null
STREAM 75760: onEofChunk
STREAM 75760: emitReadable false false
STREAM 75760: emitReadable true
STREAM 75760: resume false
STREAM 75760: read 0
STREAM 75760: flow true
STREAM 75760: read undefined
STREAM 75760: need readable false
STREAM 75760: length less than watermark true
STREAM 75760: reading or ended false
STREAM 75760: endReadable false
STREAM 75760: read undefined
STREAM 75760: endReadable false
STREAM 75760: read 0
STREAM 75760: endReadable false
STREAM 75760: emitReadable_ false 0 true
STREAM 75760: flow true
STREAM 75760: read undefined
STREAM 75760: endReadable false
STREAM 75760: endReadableNT false 0
STREAM 75760: endReadableNT true 0
STREAM 75760: endReadableNT true 0
STREAM 75760: endReadableNT true 0
<div>foo</div>
➜ vue-ssr git:(main) NODE_DEBUG=stream node notwork.cjs.js
STREAM 75780: resume
STREAM 75780: resume false
STREAM 75780: read 0
STREAM 75780: need readable false
STREAM 75780: length less than watermark true
STREAM 75780: do read
internal/streams/readable.js:642
throw new ERR_METHOD_NOT_IMPLEMENTED('_read()');
^
Error [ERR_METHOD_NOT_IMPLEMENTED]: The _read() method is not implemented
at Readable._read (internal/streams/readable.js:642:9)
at Readable.read (internal/streams/readable.js:481:10)
at resume_ (internal/streams/readable.js:977:12)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
code: 'ERR_METHOD_NOT_IMPLEMENTED'
}
I think the problem is you shouldn't be using on('data')
, which creates the need for read()
but I'm really not sure.