Blame view

node_modules/vue/src/server/create-renderer.js 2.92 KB
aaac7fed   liuqimichale   add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
  /* @flow */
  
  import RenderStream from './render-stream'
  import { createWriteFunction } from './write'
  import { createRenderFunction } from './render'
  import { createPromiseCallback } from './util'
  import TemplateRenderer from './template-renderer/index'
  import type { ClientManifest } from './template-renderer/index'
  
  export type Renderer = {
    renderToString: (component: Component, context: any, cb: any) => ?Promise<string>;
    renderToStream: (component: Component, context?: Object) => stream$Readable;
  };
  
  type RenderCache = {
    get: (key: string, cb?: Function) => string | void;
    set: (key: string, val: string) => void;
    has?: (key: string, cb?: Function) => boolean | void;
  };
  
  export type RenderOptions = {
    modules?: Array<(vnode: VNode) => ?string>;
    directives?: Object;
    isUnaryTag?: Function;
    cache?: RenderCache;
    template?: string;
    inject?: boolean;
    basedir?: string;
    shouldPreload?: Function;
    shouldPrefetch?: Function;
    clientManifest?: ClientManifest;
    runInNewContext?: boolean | 'once';
  };
  
  export function createRenderer ({
    modules = [],
    directives = {},
    isUnaryTag = (() => false),
    template,
    inject,
    cache,
    shouldPreload,
    shouldPrefetch,
    clientManifest
  }: RenderOptions = {}): Renderer {
    const render = createRenderFunction(modules, directives, isUnaryTag, cache)
    const templateRenderer = new TemplateRenderer({
      template,
      inject,
      shouldPreload,
      shouldPrefetch,
      clientManifest
    })
  
    return {
      renderToString (
        component: Component,
        context: any,
        cb: any
      ): ?Promise<string> {
        if (typeof context === 'function') {
          cb = context
          context = {}
        }
        if (context) {
          templateRenderer.bindRenderFns(context)
        }
  
        // no callback, return Promise
        let promise
        if (!cb) {
          ({ promise, cb } = createPromiseCallback())
        }
  
        let result = ''
        const write = createWriteFunction(text => {
          result += text
          return false
        }, cb)
        try {
          render(component, write, context, err => {
            if (template) {
              result = templateRenderer.renderSync(result, context)
            }
            if (err) {
              cb(err)
            } else {
              cb(null, result)
            }
          })
        } catch (e) {
          cb(e)
        }
  
        return promise
      },
  
      renderToStream (
        component: Component,
        context?: Object
      ): stream$Readable {
        if (context) {
          templateRenderer.bindRenderFns(context)
        }
        const renderStream = new RenderStream((write, done) => {
          render(component, write, context, done)
        })
        if (!template) {
          return renderStream
        } else {
          const templateStream = templateRenderer.createStream(context)
          renderStream.on('error', err => {
            templateStream.emit('error', err)
          })
          renderStream.pipe(templateStream)
          return templateStream
        }
      }
    }
  }