diff --git a/lib/graph/treeshake.js b/lib/graph/treeshake.js index 132f4128..25ac767d 100644 --- a/lib/graph/treeshake.js +++ b/lib/graph/treeshake.js @@ -132,32 +132,47 @@ function loadFromGraph(getNode) { function transpile(getNode, data) { let loader = data.loader; - let opts = loader.babelOptions || {}; - let required = ["es2015", {loose: false, modules: false}]; - opts.presets = processBabelPresets({ - baseURL: loader.baseURL, - babelOptions: opts, - loaderEnv: loader.getEnv() - }); + function getBabelOptions(node) { + let opts = loader.babelOptions || {}; + var npmPkg = node.load.metadata.npmPackage; + if(npmPkg) { + var pkgSteal = npmPkg.steal || npmPkg.system; + if(pkgSteal && pkgSteal.babelOptions) { + opts = pkgSteal.babelOptions; + } + } + return opts; + } - opts.plugins = processBabelPlugins({ - baseURL: loader.baseURL, - babelOptions: opts, - loaderEnv: loader.getEnv() - }); + function setBabelOptions(opts) { + let required = ["es2015", {loose: false, modules: false}]; - if(opts.presets && opts.presets.length) { - opts.presets = [required].concat(opts.presets); - } else { - opts.presets = [ - "react", - "stage-0", - required - ]; - } + opts.presets = processBabelPresets({ + baseURL: loader.baseURL, + babelOptions: opts, + loaderEnv: loader.getEnv() + }); - opts.sourceMaps = true; + opts.plugins = processBabelPlugins({ + baseURL: loader.baseURL, + babelOptions: opts, + loaderEnv: loader.getEnv() + }); + + if(opts.presets && opts.presets.length) { + opts.presets = [required].concat(opts.presets); + } else { + opts.presets = [ + "react", + "stage-0", + required + ]; + } + + opts.sourceMaps = true; + return opts; + } return { transform: function(code, id) { @@ -166,6 +181,8 @@ function transpile(getNode, data) { return code; } + let opts = setBabelOptions(getBabelOptions(node)); + let result = babel.transform(code, opts); for(let depName of node.load.metadata.dependencies) { diff --git a/lib/stream/treeshake.js b/lib/stream/treeshake.js index 50c5bab8..c5a44a25 100644 --- a/lib/stream/treeshake.js +++ b/lib/stream/treeshake.js @@ -6,7 +6,13 @@ module.exports = function() { return through.obj(function(data, enc, next) { var options = data.options; - if(options.treeShaking === false) { + var disabled = + // Can be disabled from the BuildOptions + options.treeShaking === false || + // Or from package.json config + data.loader.treeShaking === false; + + if(disabled) { next(null, data); return; } diff --git a/package.json b/package.json index 75126b5e..e4fccde2 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "prettier": "1.12.0", "pump": "^3.0.0", "rollup-plugin-commonjs": "^9.1.3", - "steal": "^2.0.0-pre.7", + "steal": "^2.0.0-pre.16", "steal-bundler": "^0.3.6", "steal-parse-amd": "^1.0.0", "steal-rollup": "^0.58.3", diff --git a/test/dev_bundle_forward/dev.html b/test/dev_bundle_forward/dev.html index 79d4a792..dd51d71c 100644 --- a/test/dev_bundle_forward/dev.html +++ b/test/dev_bundle_forward/dev.html @@ -8,10 +8,11 @@ diff --git a/test/dev_bundles_minify/dev.html b/test/dev_bundles_minify/dev.html index 78908e2c..46909edb 100644 --- a/test/dev_bundles_minify/dev.html +++ b/test/dev_bundles_minify/dev.html @@ -7,10 +7,11 @@ Minified development bundles - - \ No newline at end of file + diff --git a/test/export_standalone_test.js b/test/export_standalone_test.js index 8541370e..cb219bd3 100644 --- a/test/export_standalone_test.js +++ b/test/export_standalone_test.js @@ -97,7 +97,7 @@ describe("+standalone", function(){ }); - it.only("Can be used for node.js projects with process and can be set to production", function(done){ + it("Can be used for node.js projects with process and can be set to production", function(done){ this.timeout(10000); var outPath = __dirname + "/exports_basics/out.js"; diff --git a/test/tree_shaking_test.js b/test/tree_shaking_test.js index c65117b7..fb7cd1de 100644 --- a/test/tree_shaking_test.js +++ b/test/tree_shaking_test.js @@ -124,14 +124,55 @@ describe("Tree-shaking", function(){ }); describe("treeShaking: false", function(){ - before(buildAndOpen({ - treeShaking: false - })); - - it("Doesn\'t tree shake modules", function(){ - let dep = app.dep; - assert.equal(typeof dep.one, "function", "Included"); - assert.equal(typeof dep.two, "function", "Included"); + describe("as a BuildOption", function(){ + before(buildAndOpen({ + treeShaking: false + })); + + it("Doesn\'t tree shake modules", function(){ + let dep = app.dep; + assert.equal(typeof dep.one, "function", "Included"); + assert.equal(typeof dep.two, "function", "Included"); + }); + }); + + describe("in the package.json", function(){ + var app; + before(function(done){ + this.timeout(20000); + var base = path.join(__dirname, "treeshake", "disabled"); + 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", "disabled", page)) + .then(function(args) { + close = args.close; + browser = args.browser; + return find(browser, "app"); + }) + .then(function(mod) { + app = mod; + close(); + done(); + }); + }) + .catch(done); + }); + + it("Doesn\'t tree shake modules", function(){ + let dep = app.dep; + assert.equal(typeof dep.one, "function", "Included"); + assert.equal(typeof dep.two, "function", "Included"); + }); }); }); @@ -164,7 +205,7 @@ describe("Tree-shaking", function(){ }); }) .catch(done); - }) + }); it("Items from both are included in the build", function(){ assert.equal(app.a, "a", "main bundle loaded"); diff --git a/test/treeshake/disabled/bundle-a.js b/test/treeshake/disabled/bundle-a.js new file mode 100644 index 00000000..a5cbaf86 --- /dev/null +++ b/test/treeshake/disabled/bundle-a.js @@ -0,0 +1,8 @@ + +export function one() { + return 1; +} + +export function two() { + return 2; +} diff --git a/test/treeshake/disabled/from-exports.js b/test/treeshake/disabled/from-exports.js new file mode 100644 index 00000000..4a708fca --- /dev/null +++ b/test/treeshake/disabled/from-exports.js @@ -0,0 +1,7 @@ + +export let rexpOne = 'one'; +export let rexpTwo = 'two'; + +function doThings() { + +} diff --git a/test/treeshake/disabled/main.js b/test/treeshake/disabled/main.js new file mode 100644 index 00000000..e7e020bc --- /dev/null +++ b/test/treeshake/disabled/main.js @@ -0,0 +1,78 @@ +// two is not used. Using two should throw. +import { one } from "dep"; + +// A default export +import anon from "dep/another"; + +// A package not using sideEffects: false +import { one as twoOne } from "dep2"; + +// A built-in module that should be ignored. +import steal from "@steal"; + +// Importing a module for its side effects +import "dep3"; + +// Importing a module that itself should be tree-shaken +import {default as dep4} from "dep4"; + +// Importing a module that re-exports another +import { rexpOne } from "./reexports"; + +// Import a CommonJS module +import dep5 from "dep5"; + +// Import a package but only use some subpackages +import { DefineMap } from "can"; + +export default function(){ + window.globals = { + one, + anon, + twoOne, + steal, + rexpOne, + dep4, + dep5, + DefineMap + }; + + let shouldFail = steal.import("can-connect@1.0.0#main").then(null, function(err){ + err.didFail = true; + return err; + }); + + // return all of the exports so the tests can assert things. + let p = Promise.all([ + steal.import("~/bundle-a"), + steal.import("dep"), + steal.import("dep2"), + steal.import("dep4/other"), + steal.import("dep4/and-another"), + steal.import("~/from-exports"), + shouldFail + ]); + + return p + .then(([ + bundleA, + dep, + depTwo, + dep4Other, + dep4AndAnother, + fromExports, + canConnect + ]) => { + return { + anon, + bundleA, + dep, + depTwo, + dep4Other, + dep4AndAnother, + fromExports, + dep5, + canConnect + }; + }); +}; diff --git a/test/treeshake/disabled/node_modules/can-connect/main.js b/test/treeshake/disabled/node_modules/can-connect/main.js new file mode 100644 index 00000000..50f93639 --- /dev/null +++ b/test/treeshake/disabled/node_modules/can-connect/main.js @@ -0,0 +1,3 @@ +var connect = {"behavior": "worked"}; + +export default connect; diff --git a/test/treeshake/disabled/node_modules/can-connect/package.json b/test/treeshake/disabled/node_modules/can-connect/package.json new file mode 100644 index 00000000..2076624e --- /dev/null +++ b/test/treeshake/disabled/node_modules/can-connect/package.json @@ -0,0 +1,5 @@ +{ + "name": "can-connect", + "main": "main.js", + "version": "1.0.0" +} diff --git a/test/treeshake/disabled/node_modules/can-define/main.js b/test/treeshake/disabled/node_modules/can-define/main.js new file mode 100644 index 00000000..39296931 --- /dev/null +++ b/test/treeshake/disabled/node_modules/can-define/main.js @@ -0,0 +1,5 @@ +function DefineMap() { + +} + +export default DefineMap; diff --git a/test/treeshake/disabled/node_modules/can-define/package.json b/test/treeshake/disabled/node_modules/can-define/package.json new file mode 100644 index 00000000..2e44c2b4 --- /dev/null +++ b/test/treeshake/disabled/node_modules/can-define/package.json @@ -0,0 +1,5 @@ +{ + "name": "can-define", + "main": "main.js", + "version": "1.0.0" +} diff --git a/test/treeshake/disabled/node_modules/can/main.js b/test/treeshake/disabled/node_modules/can/main.js new file mode 100644 index 00000000..ede39e2b --- /dev/null +++ b/test/treeshake/disabled/node_modules/can/main.js @@ -0,0 +1,2 @@ +export { default as DefineMap} from "can-define"; +export { default as connect} from "can-connect"; diff --git a/test/treeshake/disabled/node_modules/can/package.json b/test/treeshake/disabled/node_modules/can/package.json new file mode 100644 index 00000000..53d1ec61 --- /dev/null +++ b/test/treeshake/disabled/node_modules/can/package.json @@ -0,0 +1,9 @@ +{ + "name": "can", + "main": "main.js", + "version": "1.0.0", + "dependencies": { + "can-define": "1.0.0", + "can-connect": "1.0.0" + } +} diff --git a/test/treeshake/disabled/node_modules/dep/another.js b/test/treeshake/disabled/node_modules/dep/another.js new file mode 100644 index 00000000..c9fbb5a1 --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep/another.js @@ -0,0 +1,4 @@ + +export default function() { + return 'default export'; +} diff --git a/test/treeshake/disabled/node_modules/dep/main.js b/test/treeshake/disabled/node_modules/dep/main.js new file mode 100644 index 00000000..973bf85b --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep/main.js @@ -0,0 +1,8 @@ + +export function one() { + // THIS IS ACTUALLY USED. +} + +export function two() { + throw new Error("dep.two should have been treeshaken"); +} diff --git a/test/treeshake/disabled/node_modules/dep/package.json b/test/treeshake/disabled/node_modules/dep/package.json new file mode 100644 index 00000000..66a01032 --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep/package.json @@ -0,0 +1,6 @@ +{ + "name": "dep", + "main": "main.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/test/treeshake/disabled/node_modules/dep2/main.js b/test/treeshake/disabled/node_modules/dep2/main.js new file mode 100644 index 00000000..f539142d --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep2/main.js @@ -0,0 +1,7 @@ +export function one() { + return 1; +} + +export function two() { + return 2; +} diff --git a/test/treeshake/disabled/node_modules/dep2/package.json b/test/treeshake/disabled/node_modules/dep2/package.json new file mode 100644 index 00000000..36278079 --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep2/package.json @@ -0,0 +1,5 @@ +{ + "name": "dep2", + "main": "main.js", + "version": "1.0.0" +} diff --git a/test/treeshake/disabled/node_modules/dep3/main.js b/test/treeshake/disabled/node_modules/dep3/main.js new file mode 100644 index 00000000..4e91fa3e --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep3/main.js @@ -0,0 +1,6 @@ + +export function one() { + window.DEP3_SIDE_EFFECT = true; +} + +one(); diff --git a/test/treeshake/disabled/node_modules/dep3/package.json b/test/treeshake/disabled/node_modules/dep3/package.json new file mode 100644 index 00000000..ae3b0b59 --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep3/package.json @@ -0,0 +1,6 @@ +{ + "name": "dep3", + "main": "main.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/test/treeshake/disabled/node_modules/dep4/and-another.js b/test/treeshake/disabled/node_modules/dep4/and-another.js new file mode 100644 index 00000000..46d4044c --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep4/and-another.js @@ -0,0 +1,7 @@ +export function anotherOne() { + return 'another'; +}; + +export function anotherTwo() { + return 'two'; +}; diff --git a/test/treeshake/disabled/node_modules/dep4/main.js b/test/treeshake/disabled/node_modules/dep4/main.js new file mode 100644 index 00000000..4c9ebae6 --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep4/main.js @@ -0,0 +1,3 @@ +import {first} from './other'; + +export default first; diff --git a/test/treeshake/disabled/node_modules/dep4/other.js b/test/treeshake/disabled/node_modules/dep4/other.js new file mode 100644 index 00000000..3cb0a74d --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep4/other.js @@ -0,0 +1,13 @@ +import {anotherOne, anotherTwo} from './and-another'; + +function callAnotherTwo() { + return anotherTwo(); +} + +export function first() { + return anotherOne(); +}; + +export function second() { + return callAnotherTwo(); +} diff --git a/test/treeshake/disabled/node_modules/dep4/package.json b/test/treeshake/disabled/node_modules/dep4/package.json new file mode 100644 index 00000000..067dab0f --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep4/package.json @@ -0,0 +1,6 @@ +{ + "name": "dep4", + "main": "main.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/test/treeshake/disabled/node_modules/dep5/main.js b/test/treeshake/disabled/node_modules/dep5/main.js new file mode 100644 index 00000000..d0b7285f --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep5/main.js @@ -0,0 +1,3 @@ +exports.doStuff = function(){ + return "worked"; +}; diff --git a/test/treeshake/disabled/node_modules/dep5/package.json b/test/treeshake/disabled/node_modules/dep5/package.json new file mode 100644 index 00000000..ca0e4150 --- /dev/null +++ b/test/treeshake/disabled/node_modules/dep5/package.json @@ -0,0 +1,6 @@ +{ + "name": "dep5", + "main": "main.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/test/treeshake/disabled/package.json b/test/treeshake/disabled/package.json new file mode 100644 index 00000000..3e03368e --- /dev/null +++ b/test/treeshake/disabled/package.json @@ -0,0 +1,18 @@ +{ + "name": "treeshake", + "main": "main.js", + "version": "1.0.0", + "dependencies": { + "can": "1.0.0", + "dep": "1.0.0", + "dep2": "1.0.0", + "dep3": "1.0.0", + "dep4": "1.0.0", + "dep5": "1.0.0" + }, + "steal": { + "bundle": ["treeshake/bundle-a"], + "treeShaking": false + }, + "sideEffects": false +} diff --git a/test/treeshake/disabled/prod.html b/test/treeshake/disabled/prod.html new file mode 100644 index 00000000..61d3dcfc --- /dev/null +++ b/test/treeshake/disabled/prod.html @@ -0,0 +1,13 @@ + diff --git a/test/treeshake/disabled/reexports.js b/test/treeshake/disabled/reexports.js new file mode 100644 index 00000000..f1addbd3 --- /dev/null +++ b/test/treeshake/disabled/reexports.js @@ -0,0 +1,2 @@ + +export * from "./from-exports";