Merge pull request #6952 from loganfsmyth/commonjs-lazy
Add a 'lazy' options to modules-commonjs
This commit is contained in:
@@ -127,3 +127,37 @@ function _interopRequireDefault(obj) {
|
||||
In cases where the auto-unwrapping of `default` is not needed, you can set the
|
||||
`noInterop` option to `true` to avoid the usage of the `interopRequireDefault`
|
||||
helper (shown in inline form above).
|
||||
|
||||
### `lazy`
|
||||
|
||||
`boolean`, `Array<string>`, or `(string) => boolean`, defaults to `false`
|
||||
|
||||
Changes Babel's compiled `import` statements to be lazily evaluated when their
|
||||
imported bindings are used for the first time.
|
||||
|
||||
This can improve initial load time of your module because evaluating
|
||||
dependencies up front is sometimes entirely un-necessary. This is especially
|
||||
the case when implementing a library module.
|
||||
|
||||
The value of `lazy` has a few possible effects:
|
||||
|
||||
* `false` - No lazy initialization of any imported module.
|
||||
* `true` - Do not lazy-initialize local `./foo` imports, but lazy-init `foo` dependencies.
|
||||
|
||||
Local paths are much more likely to have circular dependencies, which may break if loaded lazily,
|
||||
so they are not lazy by default, whereas dependencies between independent modules are rarely cyclical.
|
||||
|
||||
* `Array<string>` - Lazy-initialize all imports with source matching one of the given strings.
|
||||
* `(string) => boolean` - Pass a callback that will be called to decide if a given source string should be lazy-loaded.
|
||||
|
||||
The two cases where imports can never be lazy are:
|
||||
|
||||
* `import "foo";`
|
||||
|
||||
Side-effect imports are automatically non-lazy since their very existence means
|
||||
that there is no binding to later kick off initialization.
|
||||
|
||||
* `export * from "foo"`
|
||||
|
||||
Re-exporting all names requires up-front execution because otherwise there is no
|
||||
way to know what names need to be exported.
|
||||
|
||||
@@ -16,9 +16,19 @@ export default function(api, options) {
|
||||
strict,
|
||||
strictMode,
|
||||
noInterop,
|
||||
lazy = false,
|
||||
// Defaulting to 'true' for now. May change before 7.x major.
|
||||
allowCommonJSExports = true,
|
||||
} = options;
|
||||
|
||||
if (
|
||||
typeof lazy !== "boolean" &&
|
||||
typeof lazy !== "function" &&
|
||||
(!Array.isArray(lazy) || !lazy.every(item => typeof item === "string"))
|
||||
) {
|
||||
throw new Error(`.lazy must be a boolean, array of strings, or a function`);
|
||||
}
|
||||
|
||||
const getAssertion = localName => template.expression.ast`
|
||||
(function(){
|
||||
throw new Error("The CommonJS '" + "${localName}" + "' variable is not available in ES6 modules.");
|
||||
@@ -122,6 +132,7 @@ export default function(api, options) {
|
||||
strictMode,
|
||||
allowTopLevelThis,
|
||||
noInterop,
|
||||
lazy,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -132,14 +143,26 @@ export default function(api, options) {
|
||||
|
||||
let header;
|
||||
if (isSideEffectImport(metadata)) {
|
||||
if (metadata.lazy) throw new Error("Assertion failure");
|
||||
|
||||
header = t.expressionStatement(loadExpr);
|
||||
} else {
|
||||
header = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(
|
||||
t.identifier(metadata.name),
|
||||
wrapInterop(path, loadExpr, metadata.interop) || loadExpr,
|
||||
),
|
||||
]);
|
||||
const init =
|
||||
wrapInterop(path, loadExpr, metadata.interop) || loadExpr;
|
||||
|
||||
if (metadata.lazy) {
|
||||
header = template.ast`
|
||||
function ${metadata.name}() {
|
||||
const data = ${init};
|
||||
${metadata.name} = function(){ return data; };
|
||||
return data;
|
||||
}
|
||||
`;
|
||||
} else {
|
||||
header = template.ast`
|
||||
var ${metadata.name} = ${init};
|
||||
`;
|
||||
}
|
||||
}
|
||||
header.loc = metadata.loc;
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import foo from "foo";
|
||||
|
||||
console.log(foo);
|
||||
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
function _foo() {
|
||||
const data = babelHelpers.interopRequireDefault(require("foo"));
|
||||
|
||||
_foo = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
console.log(_foo().default);
|
||||
@@ -0,0 +1,3 @@
|
||||
import { foo } from "foo";
|
||||
|
||||
console.log(foo);
|
||||
13
packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-named/expected.js
vendored
Normal file
13
packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-named/expected.js
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
function _foo() {
|
||||
const data = require("foo");
|
||||
|
||||
_foo = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
console.log(_foo().foo);
|
||||
@@ -0,0 +1,3 @@
|
||||
import * as foo from "foo";
|
||||
|
||||
console.log(foo);
|
||||
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
function foo() {
|
||||
const data = babelHelpers.interopRequireWildcard(require("foo"));
|
||||
|
||||
foo = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
console.log(foo());
|
||||
6
packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/options.json
vendored
Normal file
6
packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/options.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"plugins": [
|
||||
"external-helpers",
|
||||
["transform-modules-commonjs", { "lazy": true }]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "foo";
|
||||
17
packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/reexport-all/expected.js
vendored
Normal file
17
packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/reexport-all/expected.js
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _foo = require("foo");
|
||||
|
||||
Object.keys(_foo).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
import foo from "foo";
|
||||
export { foo as default };
|
||||
@@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "default", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo().default;
|
||||
}
|
||||
});
|
||||
|
||||
function _foo() {
|
||||
const data = babelHelpers.interopRequireDefault(require("foo"));
|
||||
|
||||
_foo = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import { named } from "foo";
|
||||
export { named };
|
||||
@@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "named", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo().named;
|
||||
}
|
||||
});
|
||||
|
||||
function _foo() {
|
||||
const data = require("foo");
|
||||
|
||||
_foo = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import * as namespace from "foo";
|
||||
export { namespace };
|
||||
@@ -0,0 +1,23 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.namespace = void 0;
|
||||
|
||||
function namespace() {
|
||||
const data = babelHelpers.interopRequireWildcard(require("foo"));
|
||||
|
||||
namespace = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Object.defineProperty(exports, "namespace", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return namespace();
|
||||
}
|
||||
});
|
||||
1
packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/sideeffect/actual.js
vendored
Normal file
1
packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/sideeffect/actual.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import "foo";
|
||||
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
|
||||
require("foo");
|
||||
@@ -0,0 +1,3 @@
|
||||
import foo from "./foo";
|
||||
|
||||
console.log(foo);
|
||||
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
var _foo = babelHelpers.interopRequireDefault(require("./foo"));
|
||||
|
||||
console.log(_foo.default);
|
||||
@@ -0,0 +1,3 @@
|
||||
import { foo } from "./foo";
|
||||
|
||||
console.log(foo);
|
||||
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
var _foo = require("./foo");
|
||||
|
||||
console.log(_foo.foo);
|
||||
@@ -0,0 +1,3 @@
|
||||
import * as foo from "./foo";
|
||||
|
||||
console.log(foo);
|
||||
@@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
|
||||
var foo = babelHelpers.interopRequireWildcard(require("./foo"));
|
||||
console.log(foo);
|
||||
6
packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-local/options.json
vendored
Normal file
6
packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-local/options.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"plugins": [
|
||||
"external-helpers",
|
||||
["transform-modules-commonjs", { "lazy": true }]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./foo";
|
||||
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _foo = require("./foo");
|
||||
|
||||
Object.keys(_foo).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
import foo from "./foo";
|
||||
export { foo as default };
|
||||
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "default", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo.default;
|
||||
}
|
||||
});
|
||||
|
||||
var _foo = babelHelpers.interopRequireDefault(require("./foo"));
|
||||
@@ -0,0 +1,2 @@
|
||||
import { named } from "./foo";
|
||||
export { named };
|
||||
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "named", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo.named;
|
||||
}
|
||||
});
|
||||
|
||||
var _foo = require("./foo");
|
||||
@@ -0,0 +1,2 @@
|
||||
import * as namespace from "./foo";
|
||||
export { namespace };
|
||||
@@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.namespace = void 0;
|
||||
var namespace = babelHelpers.interopRequireWildcard(require("./foo"));
|
||||
exports.namespace = namespace;
|
||||
@@ -0,0 +1 @@
|
||||
import "./a";
|
||||
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
|
||||
require("./a");
|
||||
@@ -0,0 +1,7 @@
|
||||
import foo1 from "white";
|
||||
|
||||
console.log(foo1);
|
||||
|
||||
import foo2 from "black";
|
||||
|
||||
console.log(foo2);
|
||||
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
var _white = babelHelpers.interopRequireDefault(require("white"));
|
||||
|
||||
function _black() {
|
||||
const data = babelHelpers.interopRequireDefault(require("black"));
|
||||
|
||||
_black = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
console.log(_white.default);
|
||||
console.log(_black().default);
|
||||
@@ -0,0 +1,7 @@
|
||||
import { foo1 } from "white";
|
||||
|
||||
console.log(foo1);
|
||||
|
||||
import { foo2 } from "black";
|
||||
|
||||
console.log(foo2);
|
||||
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
var _white = require("white");
|
||||
|
||||
function _black() {
|
||||
const data = require("black");
|
||||
|
||||
_black = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
console.log(_white.foo1);
|
||||
console.log(_black().foo2);
|
||||
@@ -0,0 +1,7 @@
|
||||
import * as foo1 from "white";
|
||||
|
||||
console.log(foo1);
|
||||
|
||||
import * as foo2 from "black";
|
||||
|
||||
console.log(foo2);
|
||||
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
var foo1 = babelHelpers.interopRequireWildcard(require("white"));
|
||||
|
||||
function foo2() {
|
||||
const data = babelHelpers.interopRequireWildcard(require("black"));
|
||||
|
||||
foo2 = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
console.log(foo1);
|
||||
console.log(foo2());
|
||||
6
packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-whitelist/options.json
vendored
Normal file
6
packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-whitelist/options.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"plugins": [
|
||||
"external-helpers",
|
||||
["transform-modules-commonjs", { "lazy": ["white"] }]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from "white";
|
||||
|
||||
export * from "black";
|
||||
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _white = require("white");
|
||||
|
||||
Object.keys(_white).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _white[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var _black = require("black");
|
||||
|
||||
Object.keys(_black).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _black[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
import foo from "white";
|
||||
export { foo as default };
|
||||
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "default", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _white.default;
|
||||
}
|
||||
});
|
||||
|
||||
var _white = babelHelpers.interopRequireDefault(require("white"));
|
||||
@@ -0,0 +1,5 @@
|
||||
import { named1 } from "white";
|
||||
export { named1 };
|
||||
|
||||
import { named2 } from "black";
|
||||
export { named2 };
|
||||
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "named1", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _white.named1;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "named2", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _black().named2;
|
||||
}
|
||||
});
|
||||
|
||||
var _white = require("white");
|
||||
|
||||
function _black() {
|
||||
const data = require("black");
|
||||
|
||||
_black = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import * as namespace1 from "white";
|
||||
export { namespace1 };
|
||||
|
||||
import * as namespace2 from "black";
|
||||
export { namespace2 };
|
||||
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.namespace2 = exports.namespace1 = void 0;
|
||||
var namespace1 = babelHelpers.interopRequireWildcard(require("white"));
|
||||
exports.namespace1 = namespace1;
|
||||
|
||||
function namespace2() {
|
||||
const data = babelHelpers.interopRequireWildcard(require("black"));
|
||||
|
||||
namespace2 = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Object.defineProperty(exports, "namespace2", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return namespace2();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
import "white";
|
||||
import "black";
|
||||
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
require("white");
|
||||
|
||||
require("black");
|
||||
Reference in New Issue
Block a user