BannerPlugin.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { ConcatSource } = require("webpack-sources");
  7. const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
  8. const Template = require("./Template");
  9. const validateOptions = require("schema-utils");
  10. const schema = require("../schemas/plugins/BannerPlugin.json");
  11. const wrapComment = str => {
  12. if (!str.includes("\n")) {
  13. return Template.toComment(str);
  14. }
  15. return `/*!\n * ${str
  16. .replace(/\*\//g, "* /")
  17. .split("\n")
  18. .join("\n * ")}\n */`;
  19. };
  20. class BannerPlugin {
  21. constructor(options) {
  22. if (arguments.length > 1) {
  23. throw new Error(
  24. "BannerPlugin only takes one argument (pass an options object)"
  25. );
  26. }
  27. validateOptions(schema, options, "Banner Plugin");
  28. if (typeof options === "string" || typeof options === "function") {
  29. options = {
  30. banner: options
  31. };
  32. }
  33. this.options = options || {};
  34. if (typeof options.banner === "function") {
  35. const getBanner = this.options.banner;
  36. this.banner = this.options.raw
  37. ? getBanner
  38. : data => wrapComment(getBanner(data));
  39. } else {
  40. const banner = this.options.raw
  41. ? this.options.banner
  42. : wrapComment(this.options.banner);
  43. this.banner = () => banner;
  44. }
  45. }
  46. apply(compiler) {
  47. const options = this.options;
  48. const banner = this.banner;
  49. const matchObject = ModuleFilenameHelpers.matchObject.bind(
  50. undefined,
  51. options
  52. );
  53. compiler.hooks.compilation.tap("BannerPlugin", compilation => {
  54. compilation.hooks.optimizeChunkAssets.tap("BannerPlugin", chunks => {
  55. for (const chunk of chunks) {
  56. if (options.entryOnly && !chunk.canBeInitial()) {
  57. continue;
  58. }
  59. for (const file of chunk.files) {
  60. if (!matchObject(file)) {
  61. continue;
  62. }
  63. let basename;
  64. let query = "";
  65. let filename = file;
  66. const hash = compilation.hash;
  67. const querySplit = filename.indexOf("?");
  68. if (querySplit >= 0) {
  69. query = filename.substr(querySplit);
  70. filename = filename.substr(0, querySplit);
  71. }
  72. const lastSlashIndex = filename.lastIndexOf("/");
  73. if (lastSlashIndex === -1) {
  74. basename = filename;
  75. } else {
  76. basename = filename.substr(lastSlashIndex + 1);
  77. }
  78. const data = {
  79. hash,
  80. chunk,
  81. filename,
  82. basename,
  83. query
  84. };
  85. const comment = compilation.getPath(banner(data), data);
  86. compilation.assets[file] = new ConcatSource(
  87. comment,
  88. "\n",
  89. compilation.assets[file]
  90. );
  91. }
  92. }
  93. });
  94. });
  95. }
  96. }
  97. module.exports = BannerPlugin;