Skip to content

Commit

Permalink
Merge pull request #1095 from stealjs/ts
Browse files Browse the repository at this point in the history
Determine used exports for CJS modules
  • Loading branch information
matthewp committed Nov 27, 2018
2 parents 53f9b45 + 4a139ab commit bad9a20
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 27 deletions.
34 changes: 34 additions & 0 deletions lib/graph/each_dependants.js
@@ -0,0 +1,34 @@
var isString = require("lodash/isString");

/**
* @method graph.eachDependants
*/
module.exports = function(graph, names, callback){
var deps = {};
var nodeNames = isString(names) ? [names] : names;

function visit(name, node) {
if(!deps[name]) {
deps[name] = true;

if(node && node.dependencies.length) {
if(includes(node.dependencies, nodeNames)) {
callback(name, node);
}
}
}
}

for(var name in graph) {
visit(name, graph[name]);
}
};

function includes(arr1, arr2) {
for(var i = 0; i < arr2.length; i++) {
if(arr1.indexOf(arr2[i]) !== -1) {
return true;
}
}
return false;
}
9 changes: 9 additions & 0 deletions lib/graph/get_dependants.js
@@ -0,0 +1,9 @@
var eachDependants = require("./each_dependants");

module.exports = function(graph, name) {
var deps = [];
eachDependants(graph, name, function(depName) {
deps.push(depName);
});
return deps;
};
37 changes: 11 additions & 26 deletions lib/graph/treeshake.js
Expand Up @@ -4,6 +4,7 @@ var os = require("os");
var babel = require("babel-standalone");
var entries = require("object.entries");
var dependencyResolver = require("../node/dependency_resolver");
var getDependants = require("./get_dependants");
var processBabelPlugins = require("../process_babel_plugins");
var processBabelPresets = require("../process_babel_presets");
var rollup = require("steal-rollup");
Expand Down Expand Up @@ -31,7 +32,7 @@ function treeshake(data) {
experimentalPreserveModules: true,
experimentalCodeSplitting: true,
plugins: [
loadFromGraph(getNode),
loadFromGraph(getNode, data),
transpile(getNode, data)
],
onwarn: function(){}
Expand Down Expand Up @@ -75,7 +76,7 @@ function treeshake(data) {
});
}

function loadFromGraph(getNode) {
function loadFromGraph(getNode, data) {
return {
resolveId: function(id, importer) {
if(importer) {
Expand All @@ -90,25 +91,23 @@ function loadFromGraph(getNode) {

if(notESModule(node)) {
let needToExport = new Set();
let dependants = (node && node.load.metadata.dependants) || [];
let dependants = (node && getDependants(data.graph, node.load.name)) || [];

// Determine what to export by looking at dependants imports
for(let depName of dependants) {
let localNode = getNode(depName);
let subgraph = localNode.load.metadata.subgraph;
if(!subgraph) {
continue;
}
let specifiers = localNode.load.metadata.importSpecifiers || {};

for(let imp of subgraph.imports) {
let depName = moduleNameFromSpecifier(localNode, imp.source);
for(let [impSource,] of entries(specifiers)) {
let depName = moduleNameFromSpecifier(localNode, impSource);
if(depName !== id) {
continue;
}

for(let spec of imp.specifiers) {
needToExport.add(spec.imported);
}
let imported = localNode.load.metadata.importNames[impSource] || [];
imported.forEach(imported => {
needToExport.add(imported);
});
}
}

Expand Down Expand Up @@ -214,20 +213,6 @@ function transpile(getNode, data) {

let result = babel.transform(code, opts);

for(let depName of node.load.metadata.dependencies) {
let localNode = getNode(depName);
if(!localNode) {
continue;
}
if(!localNode.load.metadata.dependants) {
localNode.load.metadata.dependants = [];
}
localNode.load.metadata.dependants.push(id);
}

// Update metadata with specifiers
node.load.metadata.subgraph = result.metadata.modules;

return {
code: result.code,
map: result.map
Expand Down
38 changes: 37 additions & 1 deletion test/tree_shaking_test.js
Expand Up @@ -271,5 +271,41 @@ describe("Tree-shaking", function(){
assert.equal(app.a, "a", "main bundle loaded");
assert.equal(app.b, "b", "this bundle loaded");
});
})
});

describe("import { dep } from 'cjs'", function() {
before(function(done){
this.timeout(20000);
var base = path.join(__dirname, "treeshake", "cjs");
var config = { config: path.join(base, "package.json!npm") };
var page = `prod.html`;

rmdir(path.join(base, "dist"))
.then(function() {
return build(config, {
quiet: true,
minify: false
});
})
.then(function() {
var close;
return open(path.join("test", "treeshake", "cjs", page))
.then(function(args) {
close = args.close;
browser = args.browser;
return find(browser, "APP");
})
.then(function(mod) {
app = mod;
close();
done();
});
})
.catch(done);
});

it("Used imports are available", function() {
assert.equal(typeof app.assign, "function", "got the exported value");
});
});
});
6 changes: 6 additions & 0 deletions test/treeshake/cjs/dep.js
@@ -0,0 +1,6 @@

exports.pick = function(){};

exports.assign = function(){};

exports.isUndefined = function(){};
4 changes: 4 additions & 0 deletions test/treeshake/cjs/index.js
@@ -0,0 +1,4 @@
import { assign } from './dep';
import './other';

window.APP = { assign };
4 changes: 4 additions & 0 deletions test/treeshake/cjs/other.js
@@ -0,0 +1,4 @@
import { pick } from './dep';

window.APP = window.APP || {};
window.APP.pick = pick;
8 changes: 8 additions & 0 deletions test/treeshake/cjs/package.json
@@ -0,0 +1,8 @@
{
"name": "app",
"main": "index.js",
"version": "1.0.0",
"steal": {
"bundle": ["~/page"]
}
}
4 changes: 4 additions & 0 deletions test/treeshake/cjs/page.js
@@ -0,0 +1,4 @@
import { isUndefined } from './dep';

window.APP = window.APP || {};
window.APP.isUndefined = isUndefined;
1 change: 1 addition & 0 deletions test/treeshake/cjs/prod.html
@@ -0,0 +1 @@
<script src="./dist/steal.production.js"></script>

0 comments on commit bad9a20

Please sign in to comment.