create-async-file-mapper.js 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. /* @flow */
  2. /**
  3. * Creates a mapper that maps files used during a server-side render
  4. * to async chunk files in the client-side build, so that we can inline them
  5. * directly in the rendered HTML to avoid waterfall requests.
  6. */
  7. import type { ServerManifest, ClientManifest } from './index'
  8. export type AsyncFileMapper = (files: Array<string>) => Array<string>;
  9. export function createMapper (
  10. serverManifest: ServerManifest,
  11. clientManifest: ClientManifest
  12. ): AsyncFileMapper {
  13. const fileMap = createFileMap(serverManifest, clientManifest)
  14. return function mapFiles (files: Array<string>): Array<string> {
  15. const res = new Set()
  16. for (let i = 0; i < files.length; i++) {
  17. const mapped = fileMap.get(files[i])
  18. if (mapped) {
  19. for (let j = 0; j < mapped.length; j++) {
  20. res.add(mapped[j])
  21. }
  22. }
  23. }
  24. return Array.from(res)
  25. }
  26. }
  27. function createFileMap (serverManifest, clientManifest) {
  28. const fileMap = new Map()
  29. Object.keys(serverManifest.modules).forEach(file => {
  30. fileMap.set(file, mapFile(serverManifest.modules[file], clientManifest))
  31. })
  32. return fileMap
  33. }
  34. function mapFile (moduleIds, clientManifest) {
  35. const files = new Set()
  36. moduleIds.forEach(id => {
  37. const fileIndices = clientManifest.modules[id]
  38. if (fileIndices) {
  39. fileIndices.forEach(index => {
  40. const file = clientManifest.all[index]
  41. // only include async files
  42. if (clientManifest.async.indexOf(file) > -1) {
  43. files.add(file)
  44. }
  45. })
  46. }
  47. })
  48. return Array.from(files)
  49. }