getAffectedModuleIds.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. var _values = require('babel-runtime/core-js/object/values');
  6. var _values2 = _interopRequireDefault(_values);
  7. var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
  8. var _defineProperty3 = _interopRequireDefault(_defineProperty2);
  9. var _extends3 = require('babel-runtime/helpers/extends');
  10. var _extends4 = _interopRequireDefault(_extends3);
  11. var _keys = require('babel-runtime/core-js/object/keys');
  12. var _keys2 = _interopRequireDefault(_keys);
  13. exports.default = getAffectedModuleIds;
  14. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  15. var isBuilt = function isBuilt(module) {
  16. return module.built;
  17. };
  18. var getId = function getId(module) {
  19. return module.id;
  20. };
  21. var affectedModules = function affectedModules(map, usageMap, affected, moduleId) {
  22. if (typeof affected[moduleId] !== 'undefined') {
  23. // module was already inspected, stop here otherwise we get into endless recursion
  24. return;
  25. }
  26. // module is identified as affected by this function call
  27. var module = map[moduleId];
  28. affected[module.id] = module; // eslint-disable-line no-param-reassign
  29. // next we need to mark all usages aka parents also as affected
  30. var usages = usageMap[module.id];
  31. if (typeof usages !== 'undefined') {
  32. var ids = (0, _keys2.default)(usages);
  33. ids.forEach(function (id) {
  34. return affectedModules(map, usageMap, affected, id);
  35. });
  36. }
  37. };
  38. /**
  39. * Builds a map where all modules are indexed by it's id
  40. * {
  41. * [moduleId]: Module
  42. * }
  43. */
  44. var buildModuleMap = function buildModuleMap(modules) {
  45. var moduleMap = modules.reduce(function (memo, module) {
  46. return (0, _extends4.default)({}, memo, (0, _defineProperty3.default)({}, module.id, module));
  47. }, {});
  48. return moduleMap;
  49. };
  50. /**
  51. * Builds a map with all modules that are used in other modules (child -> parent relation)
  52. *
  53. * {
  54. * [childModuleId]: {
  55. * [parentModuleId]: ParentModule
  56. * }
  57. * }
  58. *
  59. * @param modules Array<number>
  60. * @return ModuleUsageMap
  61. */
  62. var buildModuleUsageMap = function buildModuleUsageMap(chunks, modules) {
  63. // build a map of all modules with their parent
  64. // {
  65. // [childModuleId]: {
  66. // [parentModuleId]: ParentModule
  67. // }
  68. // }
  69. var moduleUsageMap = modules.reduce(function (memo, module) {
  70. module.dependencies.forEach(function (dependency) {
  71. var dependentModule = dependency.module;
  72. if (!dependentModule) {
  73. return;
  74. }
  75. if (typeof memo[dependentModule.id] === 'undefined') {
  76. memo[dependentModule.id] = {}; // eslint-disable-line no-param-reassign
  77. }
  78. memo[dependentModule.id][module.id] = module; // eslint-disable-line no-param-reassign
  79. });
  80. return memo;
  81. }, {});
  82. // build a map of all chunks with their modules
  83. // {
  84. // [chunkId]: {
  85. // [moduleId]: Module
  86. // }
  87. // }
  88. var chunkModuleMap = chunks.reduce(function (memo, chunk) {
  89. // build chunk map first to get also empty chunks (without modules)
  90. memo[chunk.id] = {}; // eslint-disable-line no-param-reassign
  91. return memo;
  92. }, {});
  93. modules.reduce(function (memo, module) {
  94. module.getChunks().forEach(function (chunk) {
  95. memo[chunk.id][module.id] = module; // eslint-disable-line no-param-reassign
  96. });
  97. return memo;
  98. }, chunkModuleMap);
  99. // detect modules with code split points (e.g. require.ensure) and enhance moduleUsageMap with that information
  100. modules.forEach(function (module) {
  101. module.blocks
  102. // chunkGroup can be invalid in in some cases
  103. .filter(function (block) {
  104. return block.chunkGroup != null;
  105. }).forEach(function (block) {
  106. // loop through all generated chunks by this module
  107. // $FlowFixMe - flow thinks that block.chunkGroup could be null
  108. block.chunkGroup.chunks.map(getId).forEach(function (chunkId) {
  109. // and mark all modules of this chunk as a direct dependency of the original module
  110. (0, _values2.default)(chunkModuleMap[chunkId]).forEach(function (childModule) {
  111. if (typeof moduleUsageMap[childModule.id] === 'undefined') {
  112. moduleUsageMap[childModule.id] = {};
  113. }
  114. moduleUsageMap[childModule.id][module.id] = module;
  115. });
  116. });
  117. });
  118. });
  119. return moduleUsageMap;
  120. };
  121. /**
  122. * Builds a list with ids of all affected modules in the following way:
  123. * - affected directly by a file change
  124. * - affected indirectly by a change of it's dependencies and so on
  125. *
  126. * @param chunks Array<Chunk>
  127. * @param modules Array<Module>
  128. * @return {Array.<number>}
  129. */
  130. function getAffectedModuleIds(chunks, modules) {
  131. var moduleMap = buildModuleMap(modules);
  132. var moduleUsageMap = buildModuleUsageMap(chunks, modules);
  133. var builtModules = modules.filter(isBuilt);
  134. var affectedMap = {};
  135. builtModules.forEach(function (module) {
  136. return affectedModules(moduleMap, moduleUsageMap, affectedMap, module.id);
  137. });
  138. return (0, _values2.default)(affectedMap).map(getId);
  139. }