create-renderer.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /* @flow */
  2. import RenderStream from './render-stream'
  3. import TemplateRenderer from './template-renderer/index'
  4. import { createWriteFunction } from './write'
  5. import { createRenderFunction } from './render'
  6. import type { ClientManifest } from './template-renderer/index'
  7. export type Renderer = {
  8. renderToString: (component: Component, cb: (err: ?Error, res: ?string) => void) => void;
  9. renderToStream: (component: Component) => stream$Readable;
  10. };
  11. type RenderCache = {
  12. get: (key: string, cb?: Function) => string | void;
  13. set: (key: string, val: string) => void;
  14. has?: (key: string, cb?: Function) => boolean | void;
  15. };
  16. export type RenderOptions = {
  17. modules?: Array<(vnode: VNode) => string>;
  18. directives?: Object;
  19. isUnaryTag?: Function;
  20. cache?: RenderCache;
  21. template?: string;
  22. inject?: boolean;
  23. basedir?: string;
  24. shouldPreload?: Function;
  25. clientManifest?: ClientManifest;
  26. runInNewContext?: boolean;
  27. };
  28. export function createRenderer ({
  29. modules = [],
  30. directives = {},
  31. isUnaryTag = (() => false),
  32. template,
  33. inject,
  34. cache,
  35. shouldPreload,
  36. clientManifest
  37. }: RenderOptions = {}): Renderer {
  38. const render = createRenderFunction(modules, directives, isUnaryTag, cache)
  39. const templateRenderer = new TemplateRenderer({
  40. template,
  41. inject,
  42. shouldPreload,
  43. clientManifest
  44. })
  45. return {
  46. renderToString (
  47. component: Component,
  48. done: (err: ?Error, res: ?string) => any,
  49. context?: ?Object
  50. ): void {
  51. if (context) {
  52. templateRenderer.bindRenderFns(context)
  53. }
  54. let result = ''
  55. const write = createWriteFunction(text => {
  56. result += text
  57. return false
  58. }, done)
  59. try {
  60. render(component, write, context, () => {
  61. if (template) {
  62. result = templateRenderer.renderSync(result, context)
  63. }
  64. done(null, result)
  65. })
  66. } catch (e) {
  67. done(e)
  68. }
  69. },
  70. renderToStream (
  71. component: Component,
  72. context?: ?Object
  73. ): stream$Readable {
  74. if (context) {
  75. templateRenderer.bindRenderFns(context)
  76. }
  77. const renderStream = new RenderStream((write, done) => {
  78. render(component, write, context, done)
  79. })
  80. if (!template) {
  81. return renderStream
  82. } else {
  83. const templateStream = templateRenderer.createStream(context)
  84. renderStream.on('error', err => {
  85. templateStream.emit('error', err)
  86. })
  87. renderStream.pipe(templateStream)
  88. return templateStream
  89. }
  90. }
  91. }
  92. }