validateSchema.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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[params.additionalProperty]
  116. }?`;
  117. }
  118. if (
  119. Object.prototype.hasOwnProperty.call(
  120. REMOVED,
  121. params.additionalProperty
  122. )
  123. ) {
  124. return `${formattedError}\n${REMOVED[params.additionalProperty]}?`;
  125. }
  126. if (!error.dataPath) {
  127. if (params.additionalProperty === "debug") {
  128. return (
  129. `${formattedError}\n` +
  130. "The 'debug' property was removed in webpack 2.0.0.\n" +
  131. "Loaders should be updated to allow passing this option via loader options in module.rules.\n" +
  132. "Until loaders are updated one can use the LoaderOptionsPlugin to switch loaders into debug mode:\n" +
  133. "plugins: [\n" +
  134. " new webpack.LoaderOptionsPlugin({\n" +
  135. " debug: true\n" +
  136. " })\n" +
  137. "]"
  138. );
  139. }
  140. if (params.additionalProperty) {
  141. return (
  142. `${formattedError}\n` +
  143. "For typos: please correct them.\n" +
  144. "For loader options: webpack >= v2.0.0 no longer allows custom properties in configuration.\n" +
  145. " Loaders should be updated to allow passing options via loader options in module.rules.\n" +
  146. " Until loaders are updated one can use the LoaderOptionsPlugin to pass these options to the loader:\n" +
  147. " plugins: [\n" +
  148. " new webpack.LoaderOptionsPlugin({\n" +
  149. " // test: /\\.xxx$/, // may apply this only for some modules\n" +
  150. " options: {\n" +
  151. ` ${params.additionalProperty}: …\n` +
  152. " }\n" +
  153. " })\n" +
  154. " ]"
  155. );
  156. }
  157. }
  158. }
  159. return formattedError;
  160. }
  161. }
  162. );
  163. };
  164. module.exports = validateSchema;