'use strict'; var toposort = require('toposort'); /* Sorts dependencies between chunks by their "parents" attribute. This function sorts chunks based on their dependencies with each other. The parent relation between chunks as generated by Webpack for each chunk is used to define a directed (and hopefully acyclic) graph, which is then topologically sorted in order to retrieve the correct order in which chunks need to be embedded into HTML. A directed edge in this graph is describing a "is parent of" relationship from a chunk to another (distinct) chunk. Thus topological sorting orders chunks from bottom-layer chunks to highest level chunks that use the lower-level chunks. @param {Array} chunks an array of chunks as generated by the html-webpack-plugin. It is assumed that each entry contains at least the properties "id" (containing the chunk id) and "parents" (array containing the ids of the parent chunks). Must not be null/undefined or empty @return {Array} A topologically sorted version of the input chunks, or null if no such order could be calculated (e.g. because the chunks and their parent relations did not define an directed acyclic graph). */ module.exports.dependency = function (chunks) { if (!chunks) { return null; } // We build a map (chunk-id -> chunk) for faster access during graph building. var nodeMap = []; chunks.forEach(function (chunk) { nodeMap[chunk.id] = chunk; }); // Next, we add an edge for each parent relationship into the graph var edges = []; chunks.forEach(function (chunk) { if (chunk.parents) { // Add an edge for each parent (parent -> child) chunk.parents.forEach(function (parentId) { var parentChunk = nodeMap[parentId]; if (!parentChunk) { return null; // We haven't found the referenced chunk in our map! } edges.push([parentChunk, chunk]); }); } }); // We now perform a topological sorting on the input chunks and built edges var sortedVertices = null; try { sortedVertices = toposort.array(chunks, edges); } catch (err) { return null; // Error during sort } return sortedVertices; }; /** * Sorts the chunks based on the chunk id. * * @param {Array} chunks the list of chunks to sort * @return {Array} The sorted list of chunks */ module.exports.id = function (chunks) { return chunks.sort(function orderEntryLast (a, b) { if (a.entry !== b.entry) { return b.entry ? 1 : -1; } else { return b.id - a.id; } }); }; /** * Performs identity mapping (no-sort). * @param {Array} chunks the chunks to sort * @return {Array} The sorted chunks */ module.exports.none = function (chunks) { return chunks; }; /** * Defines the default sorter. */ module.exports.auto = module.exports.id;