7d2b6e5ae2a9ed60141c9b4fb2c05868bbcc6d1d7af2ce0aa7d269c81d99fa498185cac9ac5b0c94fb7103ac62e35b00aaeed8331b370dba69d5caaae7fc6b 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. const hash = require('hash-sum')
  2. const uniq = require('lodash.uniq')
  3. import { isJS, isCSS, onEmit } from './util'
  4. export default class VueSSRClientPlugin {
  5. constructor (options = {}) {
  6. this.options = Object.assign({
  7. filename: 'vue-ssr-client-manifest.json'
  8. }, options)
  9. }
  10. apply (compiler) {
  11. onEmit(compiler, 'vue-client-plugin', (compilation, cb) => {
  12. const stats = compilation.getStats().toJson()
  13. const allFiles = uniq(stats.assets
  14. .map(a => a.name))
  15. const initialFiles = uniq(Object.keys(stats.entrypoints)
  16. .map(name => stats.entrypoints[name].assets)
  17. .reduce((assets, all) => all.concat(assets), [])
  18. .filter((file) => isJS(file) || isCSS(file)))
  19. const asyncFiles = allFiles
  20. .filter((file) => isJS(file) || isCSS(file))
  21. .filter(file => initialFiles.indexOf(file) < 0)
  22. const manifest = {
  23. publicPath: stats.publicPath,
  24. all: allFiles,
  25. initial: initialFiles,
  26. async: asyncFiles,
  27. modules: { /* [identifier: string]: Array<index: number> */ }
  28. }
  29. const assetModules = stats.modules.filter(m => m.assets.length)
  30. const fileToIndex = file => manifest.all.indexOf(file)
  31. stats.modules.forEach(m => {
  32. // ignore modules duplicated in multiple chunks
  33. if (m.chunks.length === 1) {
  34. const cid = m.chunks[0]
  35. const chunk = stats.chunks.find(c => c.id === cid)
  36. if (!chunk || !chunk.files) {
  37. return
  38. }
  39. const id = m.identifier.replace(/\s\w+$/, '') // remove appended hash
  40. const files = manifest.modules[hash(id)] = chunk.files.map(fileToIndex)
  41. // find all asset modules associated with the same chunk
  42. assetModules.forEach(m => {
  43. if (m.chunks.some(id => id === cid)) {
  44. files.push.apply(files, m.assets.map(fileToIndex))
  45. }
  46. })
  47. }
  48. })
  49. const json = JSON.stringify(manifest, null, 2)
  50. compilation.assets[this.options.filename] = {
  51. source: () => json,
  52. size: () => json.length
  53. }
  54. cb()
  55. })
  56. }
  57. }