client-plugin.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. 'use strict';
  2. /* */
  3. var isJS = function (file) { return /\.js(\?[^.]+)?$/.test(file); };
  4. var isCSS = function (file) { return /\.css(\?[^.]+)?$/.test(file); };
  5. var ref = require('chalk');
  6. var red = ref.red;
  7. var yellow = ref.yellow;
  8. var webpack = require('webpack');
  9. var prefix = "[vue-server-renderer-webpack-plugin]";
  10. var warn = exports.warn = function (msg) { return console.error(red((prefix + " " + msg + "\n"))); };
  11. var tip = exports.tip = function (msg) { return console.log(yellow((prefix + " " + msg + "\n"))); };
  12. var isWebpack5 = !!(webpack.version && webpack.version[0] > 4);
  13. var onEmit = function (compiler, name, stageName, hook) {
  14. if (isWebpack5) {
  15. // Webpack >= 5.0.0
  16. compiler.hooks.compilation.tap(name, function (compilation) {
  17. if (compilation.compiler !== compiler) {
  18. // Ignore child compilers
  19. return
  20. }
  21. var stage = webpack.Compilation[stageName];
  22. compilation.hooks.processAssets.tapAsync({ name: name, stage: stage }, function (assets, cb) {
  23. hook(compilation, cb);
  24. });
  25. });
  26. } else if (compiler.hooks) {
  27. // Webpack >= 4.0.0
  28. compiler.hooks.emit.tapAsync(name, hook);
  29. } else {
  30. // Webpack < 4.0.0
  31. compiler.plugin('emit', hook);
  32. }
  33. };
  34. var stripModuleIdHash = function (id) {
  35. if (isWebpack5) {
  36. // Webpack >= 5.0.0
  37. return id.replace(/\|\w+$/, '')
  38. }
  39. // Webpack < 5.0.0
  40. return id.replace(/\s\w+$/, '')
  41. };
  42. var getAssetName = function (asset) {
  43. if (typeof asset === 'string') {
  44. return asset
  45. }
  46. return asset.name
  47. };
  48. var hash = require('hash-sum');
  49. var uniq = require('lodash.uniq');
  50. var VueSSRClientPlugin = function VueSSRClientPlugin (options) {
  51. if ( options === void 0 ) options = {};
  52. this.options = Object.assign({
  53. filename: 'vue-ssr-client-manifest.json'
  54. }, options);
  55. };
  56. VueSSRClientPlugin.prototype.apply = function apply (compiler) {
  57. var this$1 = this;
  58. var stage = 'PROCESS_ASSETS_STAGE_ADDITIONAL';
  59. onEmit(compiler, 'vue-client-plugin', stage, function (compilation, cb) {
  60. var stats = compilation.getStats().toJson();
  61. var allFiles = uniq(stats.assets
  62. .map(function (a) { return a.name; }));
  63. var initialFiles = uniq(Object.keys(stats.entrypoints)
  64. .map(function (name) { return stats.entrypoints[name].assets; })
  65. .reduce(function (assets, all) { return all.concat(assets); }, [])
  66. .map(getAssetName)
  67. .filter(function (file) { return isJS(file) || isCSS(file); }));
  68. var asyncFiles = allFiles
  69. .filter(function (file) { return isJS(file) || isCSS(file); })
  70. .filter(function (file) { return initialFiles.indexOf(file) < 0; });
  71. var manifest = {
  72. publicPath: stats.publicPath,
  73. all: allFiles,
  74. initial: initialFiles,
  75. async: asyncFiles,
  76. modules: { /* [identifier: string]: Array<index: number> */ }
  77. };
  78. var assetModules = stats.modules.filter(function (m) { return m.assets.length; });
  79. var fileToIndex = function (asset) { return manifest.all.indexOf(getAssetName(asset)); };
  80. stats.modules.forEach(function (m) {
  81. // ignore modules duplicated in multiple chunks
  82. if (m.chunks.length === 1) {
  83. var cid = m.chunks[0];
  84. var chunk = stats.chunks.find(function (c) { return c.id === cid; });
  85. if (!chunk || !chunk.files) {
  86. return
  87. }
  88. var id = stripModuleIdHash(m.identifier);
  89. var files = manifest.modules[hash(id)] = chunk.files.map(fileToIndex);
  90. // find all asset modules associated with the same chunk
  91. assetModules.forEach(function (m) {
  92. if (m.chunks.some(function (id) { return id === cid; })) {
  93. files.push.apply(files, m.assets.map(fileToIndex));
  94. }
  95. });
  96. }
  97. });
  98. var json = JSON.stringify(manifest, null, 2);
  99. compilation.assets[this$1.options.filename] = {
  100. source: function () { return json; },
  101. size: function () { return json.length; }
  102. };
  103. cb();
  104. });
  105. };
  106. module.exports = VueSSRClientPlugin;