DllReferencePlugin.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const parseJson = require("json-parse-better-errors");
  7. const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency");
  8. const DelegatedModuleFactoryPlugin = require("./DelegatedModuleFactoryPlugin");
  9. const ExternalModuleFactoryPlugin = require("./ExternalModuleFactoryPlugin");
  10. const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency");
  11. const NullFactory = require("./NullFactory");
  12. const makePathsRelative = require("./util/identifier").makePathsRelative;
  13. const WebpackError = require("./WebpackError");
  14. const validateOptions = require("schema-utils");
  15. const schema = require("../schemas/plugins/DllReferencePlugin.json");
  16. class DllReferencePlugin {
  17. constructor(options) {
  18. validateOptions(schema, options, "Dll Reference Plugin");
  19. this.options = options;
  20. }
  21. apply(compiler) {
  22. compiler.hooks.compilation.tap(
  23. "DllReferencePlugin",
  24. (compilation, { normalModuleFactory }) => {
  25. compilation.dependencyFactories.set(
  26. DelegatedSourceDependency,
  27. normalModuleFactory
  28. );
  29. compilation.dependencyFactories.set(
  30. DelegatedExportsDependency,
  31. new NullFactory()
  32. );
  33. }
  34. );
  35. compiler.hooks.beforeCompile.tapAsync(
  36. "DllReferencePlugin",
  37. (params, callback) => {
  38. const manifest = this.options.manifest;
  39. if (typeof manifest === "string") {
  40. params.compilationDependencies.add(manifest);
  41. compiler.inputFileSystem.readFile(manifest, (err, result) => {
  42. if (err) return callback(err);
  43. // Catch errors parsing the manifest so that blank
  44. // or malformed manifest files don't kill the process.
  45. try {
  46. params["dll reference " + manifest] = parseJson(
  47. result.toString("utf-8")
  48. );
  49. } catch (e) {
  50. // Store the error in the params so that it can
  51. // be added as a compilation error later on.
  52. const manifestPath = makePathsRelative(
  53. compiler.options.context,
  54. manifest
  55. );
  56. params[
  57. "dll reference parse error " + manifest
  58. ] = new DllManifestError(manifestPath, e.message);
  59. }
  60. return callback();
  61. });
  62. } else {
  63. return callback();
  64. }
  65. }
  66. );
  67. compiler.hooks.compile.tap("DllReferencePlugin", params => {
  68. let manifest = this.options.manifest;
  69. if (typeof manifest === "string") {
  70. // If there was an error parsing the manifest
  71. // file, exit now because the error will be added
  72. // as a compilation error in the "compilation" hook.
  73. if (params["dll reference parse error " + manifest]) {
  74. return;
  75. }
  76. manifest = params["dll reference " + manifest];
  77. }
  78. const name = this.options.name || manifest.name;
  79. const sourceType =
  80. this.options.sourceType || (manifest && manifest.type) || "var";
  81. const externals = {};
  82. const source = "dll-reference " + name;
  83. externals[source] = name;
  84. const normalModuleFactory = params.normalModuleFactory;
  85. new ExternalModuleFactoryPlugin(sourceType, externals).apply(
  86. normalModuleFactory
  87. );
  88. new DelegatedModuleFactoryPlugin({
  89. source: source,
  90. type: this.options.type,
  91. scope: this.options.scope,
  92. context: this.options.context || compiler.options.context,
  93. content: this.options.content || manifest.content,
  94. extensions: this.options.extensions
  95. }).apply(normalModuleFactory);
  96. });
  97. compiler.hooks.compilation.tap(
  98. "DllReferencePlugin",
  99. (compilation, params) => {
  100. let manifest = this.options.manifest;
  101. if (typeof manifest === "string") {
  102. // If there was an error parsing the manifest file, add the
  103. // error as a compilation error to make the compilation fail.
  104. let e = params["dll reference parse error " + manifest];
  105. if (e) {
  106. compilation.errors.push(e);
  107. }
  108. }
  109. }
  110. );
  111. }
  112. }
  113. class DllManifestError extends WebpackError {
  114. constructor(filename, message) {
  115. super();
  116. this.name = "DllManifestError";
  117. this.message = `Dll manifest ${filename}\n${message}`;
  118. Error.captureStackTrace(this, this.constructor);
  119. }
  120. }
  121. module.exports = DllReferencePlugin;