chunksorter.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. 'use strict';
  2. var toposort = require('toposort');
  3. var _ = require('lodash');
  4. /*
  5. Sorts dependencies between chunks by their "parents" attribute.
  6. This function sorts chunks based on their dependencies with each other.
  7. The parent relation between chunks as generated by Webpack for each chunk
  8. is used to define a directed (and hopefully acyclic) graph, which is then
  9. topologically sorted in order to retrieve the correct order in which
  10. chunks need to be embedded into HTML. A directed edge in this graph is
  11. describing a "is parent of" relationship from a chunk to another (distinct)
  12. chunk. Thus topological sorting orders chunks from bottom-layer chunks to
  13. highest level chunks that use the lower-level chunks.
  14. @param {Array} chunks an array of chunks as generated by the html-webpack-plugin.
  15. It is assumed that each entry contains at least the properties "id"
  16. (containing the chunk id) and "parents" (array containing the ids of the
  17. parent chunks).
  18. @return {Array} A topologically sorted version of the input chunks
  19. */
  20. module.exports.dependency = function (chunks) {
  21. if (!chunks) {
  22. return chunks;
  23. }
  24. // We build a map (chunk-id -> chunk) for faster access during graph building.
  25. var nodeMap = {};
  26. chunks.forEach(function (chunk) {
  27. nodeMap[chunk.id] = chunk;
  28. });
  29. // Next, we add an edge for each parent relationship into the graph
  30. var edges = [];
  31. chunks.forEach(function (chunk) {
  32. if (chunk.parents) {
  33. // Add an edge for each parent (parent -> child)
  34. chunk.parents.forEach(function (parentId) {
  35. // webpack2 chunk.parents are chunks instead of string id(s)
  36. var parentChunk = _.isObject(parentId) ? parentId : nodeMap[parentId];
  37. // If the parent chunk does not exist (e.g. because of an excluded chunk)
  38. // we ignore that parent
  39. if (parentChunk) {
  40. edges.push([parentChunk, chunk]);
  41. }
  42. });
  43. }
  44. });
  45. // We now perform a topological sorting on the input chunks and built edges
  46. return toposort.array(chunks, edges);
  47. };
  48. /**
  49. * Sorts the chunks based on the chunk id.
  50. *
  51. * @param {Array} chunks the list of chunks to sort
  52. * @return {Array} The sorted list of chunks
  53. */
  54. module.exports.id = function (chunks) {
  55. return chunks.sort(function orderEntryLast (a, b) {
  56. if (a.entry !== b.entry) {
  57. return b.entry ? 1 : -1;
  58. } else {
  59. return b.id - a.id;
  60. }
  61. });
  62. };
  63. /**
  64. * Performs identity mapping (no-sort).
  65. * @param {Array} chunks the chunks to sort
  66. * @return {Array} The sorted chunks
  67. */
  68. module.exports.none = function (chunks) {
  69. return chunks;
  70. };
  71. /**
  72. * Sort manually by the chunks
  73. * @param {Array} chunks the chunks to sort
  74. * @return {Array} The sorted chunks
  75. */
  76. module.exports.manual = function (chunks, specifyChunks) {
  77. var chunksResult = [];
  78. var filterResult = [];
  79. if (Array.isArray(specifyChunks)) {
  80. for (var i = 0; i < specifyChunks.length; i++) {
  81. filterResult = chunks.filter(function (chunk) {
  82. if (chunk.names[0] && chunk.names[0] === specifyChunks[i]) {
  83. return true;
  84. }
  85. return false;
  86. });
  87. filterResult.length > 0 && chunksResult.push(filterResult[0]);
  88. }
  89. }
  90. return chunksResult;
  91. };
  92. /**
  93. * Defines the default sorter.
  94. */
  95. module.exports.auto = module.exports.id;
  96. // In webpack 2 the ids have been flipped.
  97. // Therefore the id sort doesn't work the same way as it did for webpack 1
  98. // Luckily the dependency sort is working as expected
  99. if (Number(require('webpack/package.json').version.split('.')[0]) > 1) {
  100. module.exports.auto = module.exports.dependency;
  101. }