server-plugin.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. 'use strict';
  2. /* */
  3. var isJS = function (file) { return /\.js(\?[^.]+)?$/.test(file); };
  4. var ref = require('chalk');
  5. var red = ref.red;
  6. var yellow = ref.yellow;
  7. var webpack = require('webpack');
  8. var prefix = "[vue-server-renderer-webpack-plugin]";
  9. var warn = exports.warn = function (msg) { return console.error(red((prefix + " " + msg + "\n"))); };
  10. var tip = exports.tip = function (msg) { return console.log(yellow((prefix + " " + msg + "\n"))); };
  11. var isWebpack5 = !!(webpack.version && webpack.version[0] > 4);
  12. var validate = function (compiler) {
  13. if (compiler.options.target !== 'node') {
  14. warn('webpack config `target` should be "node".');
  15. }
  16. if (compiler.options.output) {
  17. if (compiler.options.output.library) {
  18. // Webpack >= 5.0.0
  19. if (compiler.options.output.library.type !== 'commonjs2') {
  20. warn('webpack config `output.library.type` should be "commonjs2".');
  21. }
  22. } else if (compiler.options.output.libraryTarget !== 'commonjs2') {
  23. // Webpack < 5.0.0
  24. warn('webpack config `output.libraryTarget` should be "commonjs2".');
  25. }
  26. }
  27. if (!compiler.options.externals) {
  28. tip(
  29. 'It is recommended to externalize dependencies in the server build for ' +
  30. 'better build performance.'
  31. );
  32. }
  33. };
  34. var onEmit = function (compiler, name, stageName, hook) {
  35. if (isWebpack5) {
  36. // Webpack >= 5.0.0
  37. compiler.hooks.compilation.tap(name, function (compilation) {
  38. if (compilation.compiler !== compiler) {
  39. // Ignore child compilers
  40. return
  41. }
  42. var stage = webpack.Compilation[stageName];
  43. compilation.hooks.processAssets.tapAsync({ name: name, stage: stage }, function (assets, cb) {
  44. hook(compilation, cb);
  45. });
  46. });
  47. } else if (compiler.hooks) {
  48. // Webpack >= 4.0.0
  49. compiler.hooks.emit.tapAsync(name, hook);
  50. } else {
  51. // Webpack < 4.0.0
  52. compiler.plugin('emit', hook);
  53. }
  54. };
  55. var getAssetName = function (asset) {
  56. if (typeof asset === 'string') {
  57. return asset
  58. }
  59. return asset.name
  60. };
  61. var VueSSRServerPlugin = function VueSSRServerPlugin (options) {
  62. if ( options === void 0 ) options = {};
  63. this.options = Object.assign({
  64. filename: 'vue-ssr-server-bundle.json'
  65. }, options);
  66. };
  67. VueSSRServerPlugin.prototype.apply = function apply (compiler) {
  68. var this$1 = this;
  69. validate(compiler);
  70. var stage = 'PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER';
  71. onEmit(compiler, 'vue-server-plugin', stage, function (compilation, cb) {
  72. var stats = compilation.getStats().toJson();
  73. var entryName = Object.keys(stats.entrypoints)[0];
  74. var entryInfo = stats.entrypoints[entryName];
  75. if (!entryInfo) {
  76. // #5553
  77. return cb()
  78. }
  79. var entryAssets = entryInfo.assets
  80. .map(getAssetName)
  81. .filter(isJS);
  82. if (entryAssets.length > 1) {
  83. throw new Error(
  84. "Server-side bundle should have one single entry file. " +
  85. "Avoid using CommonsChunkPlugin in the server config."
  86. )
  87. }
  88. var entry = entryAssets[0];
  89. if (!entry || typeof entry !== 'string') {
  90. throw new Error(
  91. ("Entry \"" + entryName + "\" not found. Did you specify the correct entry option?")
  92. )
  93. }
  94. var bundle = {
  95. entry: entry,
  96. files: {},
  97. maps: {}
  98. };
  99. Object.keys(compilation.assets).forEach(function (name) {
  100. if (isJS(name)) {
  101. bundle.files[name] = compilation.assets[name].source();
  102. } else if (name.match(/\.js\.map$/)) {
  103. bundle.maps[name.replace(/\.map$/, '')] = JSON.parse(compilation.assets[name].source());
  104. }
  105. // do not emit anything else for server
  106. delete compilation.assets[name];
  107. });
  108. var json = JSON.stringify(bundle, null, 2);
  109. var filename = this$1.options.filename;
  110. compilation.assets[filename] = {
  111. source: function () { return json; },
  112. size: function () { return json.length; }
  113. };
  114. cb();
  115. });
  116. };
  117. module.exports = VueSSRServerPlugin;