1e70710bb56ca6cd76d9e35958d089d033b73bb54ea58290bd8e9a652b82548d021c572e26349acfe3a139a1bf9ae3e921e9636758eb16d23084d333d8c60c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import { validate, isJS, onEmit } from './util'
  2. export default class VueSSRServerPlugin {
  3. constructor (options = {}) {
  4. this.options = Object.assign({
  5. filename: 'vue-ssr-server-bundle.json'
  6. }, options)
  7. }
  8. apply (compiler) {
  9. validate(compiler)
  10. onEmit(compiler, 'vue-server-plugin', (compilation, cb) => {
  11. const stats = compilation.getStats().toJson()
  12. const entryName = Object.keys(stats.entrypoints)[0]
  13. const entryInfo = stats.entrypoints[entryName]
  14. if (!entryInfo) {
  15. // #5553
  16. return cb()
  17. }
  18. const entryAssets = entryInfo.assets.filter(isJS)
  19. if (entryAssets.length > 1) {
  20. throw new Error(
  21. `Server-side bundle should have one single entry file. ` +
  22. `Avoid using CommonsChunkPlugin in the server config.`
  23. )
  24. }
  25. const entry = entryAssets[0]
  26. if (!entry || typeof entry !== 'string') {
  27. throw new Error(
  28. `Entry "${entryName}" not found. Did you specify the correct entry option?`
  29. )
  30. }
  31. const bundle = {
  32. entry,
  33. files: {},
  34. maps: {}
  35. }
  36. stats.assets.forEach(asset => {
  37. if (isJS(asset.name)) {
  38. bundle.files[asset.name] = compilation.assets[asset.name].source()
  39. } else if (asset.name.match(/\.js\.map$/)) {
  40. bundle.maps[asset.name.replace(/\.map$/, '')] = JSON.parse(compilation.assets[asset.name].source())
  41. }
  42. // do not emit anything else for server
  43. delete compilation.assets[asset.name]
  44. })
  45. const json = JSON.stringify(bundle, null, 2)
  46. const filename = this.options.filename
  47. compilation.assets[filename] = {
  48. source: () => json,
  49. size: () => json.length
  50. }
  51. cb()
  52. })
  53. }
  54. }