Skip to content

Commit

Permalink
fix(ssr): stream mode throw error in exportStatic (#6510)
Browse files Browse the repository at this point in the history
* fix(ssr): stream mode throw error in exportStatic

* chore: add test case
  • Loading branch information
ycjcl868 authored Apr 29, 2021
1 parent 31f2372 commit d0f31d4
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 12 deletions.
6 changes: 4 additions & 2 deletions packages/preset-built-in/src/plugins/features/exportStatic.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { existsSync } from 'fs';
import { join } from 'path';
import { Stream } from 'stream';
import { IApi, IRoute } from '@umijs/types';
import { deepmerge, rimraf } from '@umijs/utils';
import pathToRegexp from '@umijs/deps/compiled/path-to-regexp';

import { isDynamicRoute } from '../utils';
import { isDynamicRoute, streamToString } from '../utils';
import { OUTPUT_SERVER_FILENAME } from '../features/ssr/constants';

export default (api: IApi) => {
Expand Down Expand Up @@ -113,7 +114,8 @@ export default (api: IApi) => {
});
api.logger.info(`${route.path} render success`);
if (!error) {
return html;
// convert into string if html instance stream
return html instanceof Stream ? streamToString(html) : html;
} else {
serverRenderFailed = true;
api.logger.error(`[SSR] ${route.path}`, error);
Expand Down
6 changes: 3 additions & 3 deletions packages/preset-built-in/src/plugins/features/ssr/ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const onBuildComplete = (api: IApi, _isTest = false) => async ({
if (_isTest) {
return serverContent;
}
fs.writeFileSync(serverPath, serverContent);
await fs.promises.writeFile(serverPath, serverContent);
}
}
return undefined;
Expand Down Expand Up @@ -126,7 +126,7 @@ export default (api: IApi) => {

api.onGenerateFiles(async () => {
const serverTpl = path.join(winPath(__dirname), 'templates/server.tpl');
const serverContent = fs.readFileSync(serverTpl, 'utf-8');
const serverContent = await fs.promises.readFile(serverTpl, 'utf-8');
const html = getHtmlGenerator({ api });

const defaultHTML = await html.getContent({
Expand Down Expand Up @@ -180,7 +180,7 @@ export default (api: IApi) => {
}),
});

const clientExportsContent = fs.readFileSync(
const clientExportsContent = await fs.promises.readFile(
path.join(winPath(__dirname), `templates/${CLIENT_EXPORTS}.tpl`),
'utf-8',
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const getPageChunks = (
* handle html with rootContainer(rendered)
* @param param
*/
export const handleHTML = async (opts: Partial<IHandleHTMLOpts> = {}) => {
export const handleHTML = async (opts: Partial<IHandleHTMLOpts> = {}): Promise<string | NodeJS.ReadableStream> => {
const {
pageInitialProps,
rootContainer,
Expand Down Expand Up @@ -156,11 +156,6 @@ export const handleHTML = async (opts: Partial<IHandleHTMLOpts> = {}) => {
${Object.keys(windowInitialVars)
.map((name) => `${name} = ${windowInitialVars[name]};`)
.join('\n')}\n\t</script>`;
// https://github.com/umijs/umi/issues/5840
const newRootHTML = `<div id="${mountElementId}">${rootContainer}</div>${scriptsContent}`.replace(
/\$/g,
'$$$',
);

if (mode === 'stream') {
const [beforeRootContainer, afterRootContainer] = html.split(rootHTML);
Expand All @@ -178,5 +173,11 @@ export const handleHTML = async (opts: Partial<IHandleHTMLOpts> = {}) => {
const htmlStream = mergeStream(streamQueue);
return htmlStream;
}

// https://github.com/umijs/umi/issues/5840
const newRootHTML = `<div id="${mountElementId}">${rootContainer}</div>${scriptsContent}`.replace(
/\$/g,
'$$$',
);
return html.replace(rootHTML, newRootHTML);
};
18 changes: 17 additions & 1 deletion packages/preset-built-in/src/plugins/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import fs from 'fs';
import { join } from 'path';
import { winPath } from '@umijs/utils';
import { getGlobalFile, isDynamicRoute, isTSFile } from './utils';
import {
getGlobalFile,
isDynamicRoute,
isTSFile,
streamToString,
} from './utils';
import { Stream } from 'stream';

test('getGlobalFile', () => {
const existsSyncMock = jest
Expand Down Expand Up @@ -37,3 +43,13 @@ test('isTSFile', () => {
expect(isTSFile(undefined)).toEqual(false);
expect(isTSFile('/bar/foo.ts/a.js')).toEqual(false);
});

test('streamToString', async () => {
const { Readable } = Stream;

// @ts-ignore
const helloStream = new Readable.from(['hello', ' ', 'world']);

const helloString = await streamToString(helloStream);
expect(helloString).toEqual('hello world');
});
17 changes: 17 additions & 0 deletions packages/preset-built-in/src/plugins/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { existsSync } from 'fs';
import { Stream } from 'stream';
import { join } from 'path';

type IGetGlobalFile = (opts: {
Expand Down Expand Up @@ -32,3 +33,19 @@ export const isTSFile = (path: string): boolean => {
/\.(ts|tsx)$/.test(path)
);
};

/**
* stream convert string
* refs: https://stackoverflow.com/questions/10623798/how-do-i-read-the-contents-of-a-node-js-stream-into-a-string-variable
*
* @param stream
* @returns
*/
export function streamToString(stream: Stream): Promise<string> {
const chunks: Buffer[] = [];
return new Promise((resolve, reject) => {
stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
stream.on('error', (err) => reject(err));
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
});
}

0 comments on commit d0f31d4

Please sign in to comment.