validateSchema.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { validate } = require("schema-utils");
  7. /* cSpell:disable */
  8. const DID_YOU_MEAN = {
  9. rules: "module.rules",
  10. loaders: "module.rules or module.rules.*.use",
  11. query: "module.rules.*.options (BREAKING CHANGE since webpack 5)",
  12. noParse: "module.noParse",
  13. filename: "output.filename or module.rules.*.generator.filename",
  14. file: "output.filename",
  15. chunkFilename: "output.chunkFilename",
  16. chunkfilename: "output.chunkFilename",
  17. ecmaVersion:
  18. "output.environment (output.ecmaVersion was a temporary configuration option during webpack 5 beta)",
  19. ecmaversion:
  20. "output.environment (output.ecmaVersion was a temporary configuration option during webpack 5 beta)",
  21. ecma: "output.environment (output.ecmaVersion was a temporary configuration option during webpack 5 beta)",
  22. path: "output.path",
  23. pathinfo: "output.pathinfo",
  24. pathInfo: "output.pathinfo",
  25. jsonpFunction: "output.chunkLoadingGlobal (BREAKING CHANGE since webpack 5)",
  26. chunkCallbackName:
  27. "output.chunkLoadingGlobal (BREAKING CHANGE since webpack 5)",
  28. jsonpScriptType: "output.scriptType (BREAKING CHANGE since webpack 5)",
  29. hotUpdateFunction: "output.hotUpdateGlobal (BREAKING CHANGE since webpack 5)",
  30. splitChunks: "optimization.splitChunks",
  31. immutablePaths: "snapshot.immutablePaths",
  32. managedPaths: "snapshot.managedPaths",
  33. maxModules: "stats.modulesSpace (BREAKING CHANGE since webpack 5)",
  34. hashedModuleIds:
  35. 'optimization.moduleIds: "hashed" (BREAKING CHANGE since webpack 5)',
  36. namedChunks:
  37. 'optimization.chunkIds: "named" (BREAKING CHANGE since webpack 5)',
  38. namedModules:
  39. 'optimization.moduleIds: "named" (BREAKING CHANGE since webpack 5)',
  40. occurrenceOrder:
  41. 'optimization.chunkIds: "size" and optimization.moduleIds: "size" (BREAKING CHANGE since webpack 5)',
  42. automaticNamePrefix:
  43. "optimization.splitChunks.[cacheGroups.*].idHint (BREAKING CHANGE since webpack 5)",
  44. noEmitOnErrors:
  45. "optimization.emitOnErrors (BREAKING CHANGE since webpack 5: logic is inverted to avoid negative flags)",
  46. Buffer:
  47. "to use the ProvidePlugin to process the Buffer variable to modules as polyfill\n" +
  48. "BREAKING CHANGE: webpack 5 no longer provided Node.js polyfills by default.\n" +
  49. "Note: if you are using 'node.Buffer: false', you can just remove that as this is the default behavior now.\n" +
  50. "To provide a polyfill to modules use:\n" +
  51. 'new ProvidePlugin({ Buffer: ["buffer", "Buffer"] }) and npm install buffer.',
  52. process:
  53. "to use the ProvidePlugin to process the process variable to modules as polyfill\n" +
  54. "BREAKING CHANGE: webpack 5 no longer provided Node.js polyfills by default.\n" +
  55. "Note: if you are using 'node.process: false', you can just remove that as this is the default behavior now.\n" +
  56. "To provide a polyfill to modules use:\n" +
  57. 'new ProvidePlugin({ process: "process" }) and npm install buffer.'
  58. };
  59. const REMOVED = {
  60. concord:
  61. "BREAKING CHANGE: resolve.concord has been removed and is no longer available.",
  62. devtoolLineToLine:
  63. "BREAKING CHANGE: output.devtoolLineToLine has been removed and is no longer available."
  64. };
  65. /* cSpell:enable */
  66. /**
  67. * @param {Parameters<typeof validate>[0]} schema a json schema
  68. * @param {Parameters<typeof validate>[1]} options the options that should be validated
  69. * @param {Parameters<typeof validate>[2]=} validationConfiguration configuration for generating errors
  70. * @returns {void}
  71. */
  72. const validateSchema = (schema, options, validationConfiguration) => {
  73. validate(
  74. schema,
  75. options,
  76. validationConfiguration || {
  77. name: "Webpack",
  78. postFormatter: (formattedError, error) => {
  79. const children = error.children;
  80. if (
  81. children &&
  82. children.some(
  83. child =>
  84. child.keyword === "absolutePath" &&
  85. child.dataPath === ".output.filename"
  86. )
  87. ) {
  88. return `${formattedError}\nPlease use output.path to specify absolute path and output.filename for the file name.`;
  89. }
  90. if (
  91. children &&
  92. children.some(
  93. child =>
  94. child.keyword === "pattern" && child.dataPath === ".devtool"
  95. )
  96. ) {
  97. return (
  98. `${formattedError}\n` +
  99. "BREAKING CHANGE since webpack 5: The devtool option is more strict.\n" +
  100. "Please strictly follow the order of the keywords in the pattern."
  101. );
  102. }
  103. if (error.keyword === "additionalProperties") {
  104. const params =
  105. /** @type {import("ajv").AdditionalPropertiesParams} */ (
  106. error.params
  107. );
  108. if (
  109. Object.prototype.hasOwnProperty.call(
  110. DID_YOU_MEAN,
  111. params.additionalProperty
  112. )
  113. ) {
  114. return `${formattedError}\nDid you mean ${
  115. DID_YOU_MEAN[
  116. /** @type {keyof DID_YOU_MEAN} */ (params.additionalProperty)
  117. ]
  118. }?`;
  119. }
  120. if (
  121. Object.prototype.hasOwnProperty.call(
  122. REMOVED,
  123. params.additionalProperty
  124. )
  125. ) {
  126. return `${formattedError}\n${
  127. REMOVED[/** @type {keyof REMOVED} */ (params.additionalProperty)]
  128. }?`;
  129. }
  130. if (!error.dataPath) {
  131. if (params.additionalProperty === "debug") {
  132. return (
  133. `${formattedError}\n` +
  134. "The 'debug' property was removed in webpack 2.0.0.\n" +
  135. "Loaders should be updated to allow passing this option via loader options in module.rules.\n" +
  136. "Until loaders are updated one can use the LoaderOptionsPlugin to switch loaders into debug mode:\n" +
  137. "plugins: [\n" +
  138. " new webpack.LoaderOptionsPlugin({\n" +
  139. " debug: true\n" +
  140. " })\n" +
  141. "]"
  142. );
  143. }
  144. if (params.additionalProperty) {
  145. return (
  146. `${formattedError}\n` +
  147. "For typos: please correct them.\n" +
  148. "For loader options: webpack >= v2.0.0 no longer allows custom properties in configuration.\n" +
  149. " Loaders should be updated to allow passing options via loader options in module.rules.\n" +
  150. " Until loaders are updated one can use the LoaderOptionsPlugin to pass these options to the loader:\n" +
  151. " plugins: [\n" +
  152. " new webpack.LoaderOptionsPlugin({\n" +
  153. " // test: /\\.xxx$/, // may apply this only for some modules\n" +
  154. " options: {\n" +
  155. ` ${params.additionalProperty}: …\n` +
  156. " }\n" +
  157. " })\n" +
  158. " ]"
  159. );
  160. }
  161. }
  162. }
  163. return formattedError;
  164. }
  165. }
  166. );
  167. };
  168. module.exports = validateSchema;