CssModule.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Alexander Akait @alexander-akait
  4. */
  5. "use strict";
  6. const NormalModule = require("../NormalModule");
  7. const makeSerializable = require("../util/makeSerializable");
  8. /** @import { CssData } from "../DependencyTemplate" */
  9. /** @import Module, { BuildMeta } from "../Module" */
  10. /**
  11. * @import {
  12. * NormalModuleBuildInfo,
  13. * NormalModuleCreateData
  14. * } from "../NormalModule"
  15. */
  16. /** @import RequestShortener from "../RequestShortener" */
  17. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<[CssLayer, Supports, Media, Inheritance | undefined, CssParserExportType | undefined]>} ObjectDeserializerContext */
  18. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<[CssLayer, Supports, Media, Inheritance | undefined, CssParserExportType | undefined]>} ObjectSerializerContext */
  19. /** @import { CssParserExportType } from "../../declarations/WebpackOptions" */
  20. /** @typedef {string | undefined} CssLayer */
  21. /** @typedef {string | undefined} Supports */
  22. /** @typedef {string | undefined} Media */
  23. /** @typedef {[CssLayer, Supports, Media]} InheritanceItem */
  24. /** @typedef {InheritanceItem[]} Inheritance */
  25. /** @typedef {NormalModuleCreateData & { cssLayer: CssLayer, supports: Supports, media: Media, inheritance?: Inheritance, exportType?: CssParserExportType }} CssModuleCreateData */
  26. /**
  27. * Defines the build info properties specific to css modules.
  28. * @typedef {object} KnownCssModuleBuildInfo
  29. * @property {CssData=} cssData
  30. * @property {string=} charset charset at-rule
  31. */
  32. /** @typedef {NormalModuleBuildInfo & KnownCssModuleBuildInfo} CssModuleBuildInfo */
  33. /**
  34. * Defines the build meta properties specific to css modules.
  35. * @typedef {object} KnownCssModuleBuildMeta
  36. * @property {boolean=} isCssModule
  37. * @property {boolean=} needIdInConcatenation
  38. */
  39. /** @typedef {BuildMeta & KnownCssModuleBuildMeta} CssModuleBuildMeta */
  40. class CssModule extends NormalModule {
  41. /**
  42. * Creates an instance of CssModule.
  43. * @param {CssModuleCreateData} options options object
  44. */
  45. constructor(options) {
  46. super(options);
  47. // Redeclared with the css specific shape
  48. /** @type {CssModuleBuildInfo | undefined} */
  49. this.buildInfo = undefined;
  50. /** @type {CssModuleBuildMeta | undefined} */
  51. this.buildMeta = undefined;
  52. // Avoid override `layer` for `Module` class, because it is a feature to run module in specific layer
  53. /** @type {CssModuleCreateData['cssLayer']} */
  54. this.cssLayer = options.cssLayer;
  55. /** @type {CssModuleCreateData['supports']} */
  56. this.supports = options.supports;
  57. /** @type {CssModuleCreateData['media']} */
  58. this.media = options.media;
  59. /** @type {CssModuleCreateData['inheritance']} */
  60. this.inheritance = options.inheritance;
  61. /** @type {CssModuleCreateData['exportType']} */
  62. this.exportType = options.exportType;
  63. }
  64. /**
  65. * Returns the unique identifier used to reference this module.
  66. * @returns {string} a unique identifier of the module
  67. */
  68. identifier() {
  69. let identifier = super.identifier();
  70. if (this.cssLayer) {
  71. identifier += `|${this.cssLayer}`;
  72. }
  73. if (this.supports) {
  74. identifier += `|${this.supports}`;
  75. }
  76. if (this.media) {
  77. identifier += `|${this.media}`;
  78. }
  79. if (this.inheritance) {
  80. // Append directly — same bytes as `|` + items.join("|"), without the
  81. // intermediate `.map()` array + per-item strings (`identifier()` is
  82. // uncached and called repeatedly per module).
  83. for (let i = 0; i < this.inheritance.length; i++) {
  84. const item = this.inheritance[i];
  85. identifier += `|inheritance_${i}|${item[0] || ""}|${item[1] || ""}|${item[2] || ""}`;
  86. }
  87. }
  88. if (this.exportType) {
  89. identifier += `|${this.exportType}`;
  90. }
  91. // We generate extra code for HMR, so we need to invalidate the module
  92. if (this.hot) {
  93. identifier += `|${this.hot}`;
  94. }
  95. return identifier;
  96. }
  97. /**
  98. * Returns a human-readable identifier for this module.
  99. * @param {RequestShortener} requestShortener the request shortener
  100. * @returns {string} a user readable identifier of the module
  101. */
  102. readableIdentifier(requestShortener) {
  103. const readableIdentifier = super.readableIdentifier(requestShortener);
  104. let identifier = `css ${readableIdentifier}`;
  105. if (this.cssLayer) {
  106. identifier += ` (layer: ${this.cssLayer})`;
  107. }
  108. if (this.supports) {
  109. identifier += ` (supports: ${this.supports})`;
  110. }
  111. if (this.media) {
  112. identifier += ` (media: ${this.media})`;
  113. }
  114. if (this.exportType) {
  115. identifier += ` (exportType: ${this.exportType})`;
  116. }
  117. return identifier;
  118. }
  119. /**
  120. * Assuming this module is in the cache. Update the (cached) module with
  121. * the fresh module from the factory. Usually updates internal references
  122. * and properties.
  123. * @param {Module} module fresh module
  124. * @returns {void}
  125. */
  126. updateCacheModule(module) {
  127. super.updateCacheModule(module);
  128. const m = /** @type {CssModule} */ (module);
  129. this.cssLayer = m.cssLayer;
  130. this.supports = m.supports;
  131. this.media = m.media;
  132. this.inheritance = m.inheritance;
  133. this.exportType = m.exportType;
  134. }
  135. /**
  136. * Serializes this instance into the provided serializer context.
  137. * @param {ObjectSerializerContext} context context
  138. */
  139. serialize(context) {
  140. context
  141. .write(this.cssLayer)
  142. .write(this.supports)
  143. .write(this.media)
  144. .write(this.inheritance)
  145. .write(this.exportType);
  146. super.serialize(context);
  147. }
  148. /**
  149. * Restores this instance from the provided deserializer context.
  150. * @param {ObjectDeserializerContext} context context
  151. * @returns {CssModule} the deserialized object
  152. */
  153. static deserialize(context) {
  154. const obj = new CssModule({
  155. // will be deserialized by Module
  156. layer: /** @type {EXPECTED_ANY} */ (null),
  157. type: "",
  158. // will be filled by updateCacheModule
  159. resource: "",
  160. context: "",
  161. request: /** @type {EXPECTED_ANY} */ (null),
  162. userRequest: /** @type {EXPECTED_ANY} */ (null),
  163. rawRequest: /** @type {EXPECTED_ANY} */ (null),
  164. loaders: /** @type {EXPECTED_ANY} */ (null),
  165. matchResource: /** @type {EXPECTED_ANY} */ (null),
  166. parser: /** @type {EXPECTED_ANY} */ (null),
  167. parserOptions: /** @type {EXPECTED_ANY} */ (null),
  168. generator: /** @type {EXPECTED_ANY} */ (null),
  169. generatorOptions: /** @type {EXPECTED_ANY} */ (null),
  170. resolveOptions: /** @type {EXPECTED_ANY} */ (null),
  171. cssLayer: /** @type {EXPECTED_ANY} */ (null),
  172. supports: /** @type {EXPECTED_ANY} */ (null),
  173. media: /** @type {EXPECTED_ANY} */ (null),
  174. inheritance: /** @type {EXPECTED_ANY} */ (null),
  175. extractSourceMap: /** @type {EXPECTED_ANY} */ (null),
  176. exportType: /** @type {EXPECTED_ANY} */ (null)
  177. });
  178. obj.deserialize(context);
  179. return obj;
  180. }
  181. /**
  182. * Restores this instance from the provided deserializer context.
  183. * @param {ObjectDeserializerContext} context context
  184. */
  185. deserialize(context) {
  186. this.cssLayer = context.read();
  187. const c1 = context.rest;
  188. this.supports = c1.read();
  189. const c2 = c1.rest;
  190. this.media = c2.read();
  191. const c3 = c2.rest;
  192. this.inheritance = c3.read();
  193. const c4 = c3.rest;
  194. this.exportType = c4.read();
  195. super.deserialize(c4.rest);
  196. }
  197. }
  198. makeSerializable(CssModule, "webpack/lib/CssModule");
  199. module.exports = CssModule;