lasso
Version:
Lasso.js is a build tool and runtime library for building and bundling all of the resources needed by a web application
227 lines (180 loc) • 7.22 kB
JavaScript
var dependencyWalker = require('./dependency-walker');
var DependencyTree = require('./DependencyTree');
var logger = require('raptor-logging').logger(module);
var lassoPackageRoot = require('lasso-package-root');
var nodePath = require('path');
var recurseHandlers = {
none: function(rootDependency, lassoContext) {
return {
shouldIncludeDependency: function(dependency) {
return false;
},
shouldRecurseIntoPackageDependency: function(dependency) {
return false;
}
};
},
all: function(rootDependency, lassoContext) {
return {
shouldIncludeDependency: function(dependency) {
return true;
},
shouldRecurseIntoPackageDependency: function(dependency) {
return true;
}
};
},
dir: function(rootDependency, lassoContext) {
var baseDir = rootDependency.getDir(lassoContext) || '';
return {
shouldIncludeDependency: function(dependency) {
var dir = dependency.getDir(lassoContext);
return dir === baseDir;
},
shouldRecurseIntoPackageDependency: function(dependency) {
if (dependency.getDir(lassoContext) === baseDir) {
return true;
}
return false;
}
};
},
dirtree: function(rootDependency, lassoContext) {
var baseDir = rootDependency.getDir(lassoContext);
function checkDir(dependency) {
if (!baseDir) {
return false;
}
var dir = dependency.getDir(lassoContext);
if (!dir) {
return false;
}
return dir.startsWith(baseDir);
}
return {
shouldIncludeDependency: function(dependency) {
return checkDir(dependency);
},
shouldRecurseIntoPackageDependency: function(dependency) {
return checkDir(dependency);
}
};
},
module: function(rootDependency, lassoContext) {
var baseDir = rootDependency.getDir(lassoContext);
var nodeModulesDir;
if (baseDir) {
baseDir = lassoPackageRoot.getRootDir(baseDir);
nodeModulesDir = nodePath.join(baseDir, 'node_modules');
}
function checkDir(dependency) {
if (!baseDir) {
return false;
}
var dir = dependency.getDir(lassoContext);
if (!dir) {
return false;
}
return dir.startsWith(baseDir) && !dir.startsWith(nodeModulesDir);
}
return {
shouldIncludeDependency: function(dependency) {
return checkDir(dependency);
},
shouldRecurseIntoPackageDependency: function(dependency) {
return checkDir(dependency);
}
};
}
};
function shouldIncludeDependency (lassoContext, rootDependency, recurseHandler, dependency) {
if (dependency === rootDependency ||
(lassoContext.parentDependency && lassoContext.parentDependency === rootDependency)) {
// Always include the root dependency or any child dependencies if the top-level
// dependency was a package
return true;
}
return recurseHandler.shouldIncludeDependency(dependency);
}
function shouldRecurseIntoPackageDependency (rootDependency, recurseHandler, dependency) {
if (dependency === rootDependency) {
// Always recurse into top-level package dependencies
return true;
}
return recurseHandler.shouldRecurseIntoPackageDependency(dependency);
}
async function buildBundle(bundleMappings, dependencyRegistry, bundleConfig, lassoContext) {
var tree = logger.isDebugEnabled() ? new DependencyTree() : null;
var flags = lassoContext.flags;
var bundleDependencies = bundleConfig.getDependencies(dependencyRegistry);
var targetBundleName = bundleConfig.name;
// Each bundle should have its own phase data. Phase data is just a bucket of data that can
// be used by dependency handlers to keep track of what has been done for the current "phase"
// of optimization.
lassoContext.setPhase('app-bundle-mappings');
let dependencies = await bundleDependencies.normalize();
for (const rootDependency of dependencies) {
await rootDependency.init(lassoContext);
logger.debug('Root init');
var recurseInto = rootDependency._recurseInto || bundleConfig.getRecurseInto();
if (!recurseInto) {
if (rootDependency.getDir()) {
recurseInto = 'dirtree';
} else {
recurseInto = 'all';
}
}
if (!recurseHandlers[recurseInto]) {
throw new Error('Invalid recursion option: ' + recurseInto);
}
var recurseHandler = recurseHandlers[recurseInto](rootDependency, lassoContext);
await dependencyWalker.walk({
lassoContext: lassoContext,
dependency: rootDependency,
flags: flags,
shouldSkipDependency (dependency) {
if (dependency.isPageBundleOnlyDependency()) {
return true;
}
if (bundleMappings.getBundleForDependency(dependency)) {
// The dependency has already been added to another bundle
return true;
}
if (dependency.isPackageDependency()) {
return !shouldRecurseIntoPackageDependency(rootDependency, recurseHandler, dependency);
} else if (!dependency.read) {
// ignore non-readable dependencies during bundling phase
return true;
}
return false;
},
on: {
dependency (dependency, context) {
logger.debug(module.id, 'on dependency: ' + dependency.type);
if (dependency.isPackageDependency()) {
if (tree) {
tree.add(dependency, context.parentDependency);
}
// We are only interested in non-package dependencies
return;
}
if (shouldIncludeDependency(lassoContext, rootDependency, recurseHandler, dependency)) {
bundleMappings.addDependencyToBundle(
dependency,
targetBundleName,
context.slot,
bundleConfig,
lassoContext);
if (tree) {
tree.add(dependency, context.parentDependency);
}
}
}
}
});
}
if (tree) {
logger.debug('Bundle "' + targetBundleName + '":\n' + tree.toString());
}
}
exports.buildBundle = buildBundle;