Skip to content

Add types for vue-server-renderer (fix #5772) #5775

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 28, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/vue-server-renderer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "2.3.3",
"description": "server renderer for Vue 2.0",
"main": "index.js",
"types": "types/index.d.ts",
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/vue.git"
Expand All @@ -17,6 +18,9 @@
"bugs": {
"url": "https://github.com/vuejs/vue/issues"
},
"scripts": {
"test:types": "tsc -p types"
},
"dependencies": {
"chalk": "^1.1.3",
"hash-sum": "^1.0.2",
Expand All @@ -27,5 +31,10 @@
"source-map": "0.5.6",
"serialize-javascript": "^1.3.0"
},
"devDependencies": {
"@types/node": "^7.0.22",
"typescript": "^2.3.3",
"vue": "file:../.."
},
"homepage": "https://github.com/vuejs/vue/tree/dev/packages/vue-server-renderer#readme"
}
44 changes: 44 additions & 0 deletions packages/vue-server-renderer/types/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Vue = require('vue');
import { Readable } from 'stream';

export declare function createRenderer(options?: RendererOptions): Renderer;

export declare function createBundleRenderer(bundle: any, options?: BundleRendererOptions): BundleRenderer;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

http://ssr.vuejs.org/en/api.html#createbundlerendererbundle-options

IMHO a bundle is either a string or an object.


type RenderCallback = (err: Error, html: string) => void;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

err is nullable, if user turns on strictNullChecks TS will wrongly report if (err === null) {} as unreachable error.
(edit: strangely it does not report in 2.3.3)

done(null, result)

While html is also nullable, I think it is more desirable to declare it as string since users should use it after checking err. Declaring html as nullable will force users to unnecessarily recheck because TS cannot relate two variables in flow control :(

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While html is also nullable, I think it is more desirable to declare it as string

I agree. html should be string for convenience.


interface Renderer {
renderToString(vm: Vue, callback: RenderCallback): void;
renderToString(vm: Vue, context: object, callback: RenderCallback): void;

renderToStream(vm: Vue, context?: object): Readable;
}

interface BundleRenderer {
renderToString(callback: RenderCallback): void;
renderToString(context: object, callback: RenderCallback): void;

renderToStream(context?: object): Readable;
}

interface RendererOptions {
template?: string;
inject?: boolean;
shouldPreload?: (file: string, type: string) => boolean;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can even refine type to a precise list of file type listed here.

Might be an overkill.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that but not sure how benefit we can acquire by declaring it as string literal types. If the benefit is trivial, we can leave it as string for the simplicity of declarations?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, spec change and implementation oddity will be more problematic.

cache?: RenderCache;
directives?: {
[key: string]: Vue.DirectiveOptions | Vue.DirectiveFunction

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note server side directive will have different implementation. http://ssr.vuejs.org/en/api.html#directives

dirRenderer(node, dirs[i])

IMHO direcitives will be

 [key: string]: (vnode: VNode, dir: VNodeDirective) => void

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I totally didn't know about that, thanks 😅

};
}

interface BundleRendererOptions extends RendererOptions {
clientManifest?: any;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll update this option to object too.

runInNewContext?: boolean | 'once';
basedir?: string;
}

interface RenderCache {
get: (key: string, cb?: (res: string) => void) => string | void;
set: (key: string, val: string) => void;
has?: (key: string, cb?: (hit: boolean) => void) => boolean | void;
}
84 changes: 84 additions & 0 deletions packages/vue-server-renderer/types/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import Vue = require('vue');
import { readFileSync } from 'fs';
import { createRenderer, createBundleRenderer } from '../';

function createApp (context: any) {
return new Vue({
data: {
url: context.url
},
template: `<div>The visited URL is: {{ url }}</div>`
});
}

// Renderer test
const app = createApp({ url: 'http://localhost:8000/' });

const renderer = createRenderer({
template: readFileSync('./index.template.html', 'utf-8')
});

const context = {
title: 'Hello',
meta: `
<meta name="description" content="Vue.js SSR Example">
`
};

renderer.renderToString(app, context, (err, html) => {
if (err) throw err;
const res: string = html;
});

renderer.renderToStream(app, context).on('data', chunk => {
const html = chunk.toString();
});

// Bundle renderer test
declare const cacheClient: { [key: string]: string };

const bundleRenderer = createBundleRenderer('/path/to/vue-ssr-server-bundle.json', {
inject: false,
runInNewContext: 'once',
basedir: '/path/to/base',

shouldPreload: (file, type) => {
if (type === 'script' || type === 'style') {
return true;
}
if (type === 'font') {
return /\.woff2$/.test(file);
}
if (type === 'image') {
return file === 'hero.jpg';
}
return false;
},

cache: {
get: key => {
return cacheClient[key];
},
set: (key, val) => {
cacheClient[key] = val;
},
has: key => {
return !!cacheClient[key];
}
},

directives: {
example (vnode, directiveMeta) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vnode is inferred as HTMLElement

// transform vnode based on directive binding metadata
}
}
});

bundleRenderer.renderToString(context, (err, html) => {
if (err) throw err;
const res: string = html;
});

bundleRenderer.renderToStream(context).on('data', chunk => {
const html = chunk.toString();
});
13 changes: 13 additions & 0 deletions packages/vue-server-renderer/types/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"strict": true,
"noEmit": true
},
"compileOnSave": false,
"include": [
"**/*.ts"
]
}