template-stream.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /* @flow */
  2. const Transform = require('stream').Transform
  3. import type TemplateRenderer from './index'
  4. import type { ParsedTemplate } from './parse-template'
  5. export default class TemplateStream extends Transform {
  6. started: boolean;
  7. renderer: TemplateRenderer;
  8. template: ParsedTemplate;
  9. context: Object;
  10. constructor (
  11. renderer: TemplateRenderer,
  12. template: ParsedTemplate,
  13. context: Object
  14. ) {
  15. super()
  16. this.started = false
  17. this.renderer = renderer
  18. this.template = template
  19. this.context = context || {}
  20. }
  21. _transform (data: Buffer | string, encoding: string, done: Function) {
  22. if (!this.started) {
  23. this.emit('beforeStart')
  24. this.start()
  25. }
  26. this.push(data)
  27. done()
  28. }
  29. start () {
  30. this.started = true
  31. this.push(this.template.head(this.context))
  32. // inline server-rendered head meta information
  33. if (this.context.head) {
  34. this.push(this.context.head)
  35. }
  36. // inline preload directives for initial chunks
  37. const preloadLinks = this.renderer.renderPreloadLinks(this.context)
  38. if (preloadLinks) {
  39. this.push(preloadLinks)
  40. }
  41. // inline prefetch directives for async chunks not used during render
  42. const prefetchLinks = this.renderer.renderPrefetchLinks(this.context)
  43. if (prefetchLinks) {
  44. this.push(prefetchLinks)
  45. }
  46. // inline server-rendered CSS collected by vue-style-loader
  47. if (this.context.styles) {
  48. this.push(this.context.styles)
  49. }
  50. this.push(this.template.neck(this.context))
  51. }
  52. _flush (done: Function) {
  53. this.emit('beforeEnd')
  54. // inline initial store state
  55. const state = this.renderer.renderState(this.context)
  56. if (state) {
  57. this.push(state)
  58. }
  59. // embed scripts needed
  60. const scripts = this.renderer.renderScripts(this.context)
  61. if (scripts) {
  62. this.push(scripts)
  63. }
  64. this.push(this.template.tail(this.context))
  65. done()
  66. }
  67. }