rollup / rollup Goto Github PK
View Code? Open in Web Editor NEWNext-generation ES module bundler
Home Page: https://rollupjs.org
License: Other
Next-generation ES module bundler
Home Page: https://rollupjs.org
License: Other
Issue #44 focused on export * from '...'
within a bundle. This issue presents the problem of exporting all exports of a module through the bundle boundary. This simple example:
// --- main.js
export * from './wat';
export function a() {}
// --- wat.js
export function wat () { return 4711; }
results in the following error:
Cannot read property 'id' of undefined
TypeError: Cannot read property 'id' of undefined
at /.../repo/node_modules/rollup/.gobble-build/01-rollup/1/rollup.js:1922:41
at Array.forEach (native)
at Bundle.generate (/.../repo/node_modules/rollup/.gobble-build/01-rollup/1/rollup.js:1882:19)
at Object.generate (/.../repo/node_modules/rollup/.gobble-build/01-rollup/1/rollup.js:2183:32)
at /.../repo/node_modules/rollup/bin/runRollup.js:56:23
I'll take a look at the cause and possible solutions to the issue.
Thanks for your hard work on this. I'm actually surprised other bundlers like Webpack hasn't yet figured out the "let's exclude stuff we don't need" idea.
One of the most winning aspects of Webpack is hot module replacement. Will Rollup have to worry about hot reloading? Or is that something Rollup can leave off to Webpack? Just got curious.
Hi Rich. This project looks very exciting. I'm sold.
I have a question about pre-ES6 modules... I tried importing lodash as an experiment (today's lodash), and got this error:
Package lodash does not have a jsnext:main field, and so cannot be included in your rollup. Try adding it as an external module instead (e.g. options.external = ['lodash']
Is this a permanent design decision or is it just early days? Will you ever add functionality that can read an old-style main
script and traverse require()
calls...or do you recommend another strategy for people who want to mix ES6 and old school modules in one bundle (e.g. using Browserify as another build step after rollup)?
When rolling up multiple files that reference an external module (React in this case) I ended up with the following invalid ES6 import statement:
import { createElement, Component, createElement, isValidElement, Component, DOM, Component, DOM, Component, DOM, Component, DOM, Component, cloneElement, isValidElement, Component, Component, PropTypes, PropTypes, PropTypes, PropTypes, PropTypes, PropTypes, PropTypes, PropTypes } from 'react';
Note the duplicate import declarations… it appears these aren't being de-duped.
We can't cache analysis quite as aggressively as e.g. Browserify, because we have more work to do to deconflict names within a bundle. But it should be possible to avoid repeating at least some of the work, to enable fast incremental rebuilds.
Also, there will be times when we want to supply a module's contents, rather than having it be read from disk. The two things overlap.
It’s quite likely I’m doing something wrong here, but would you mind taking a look? I mostly have things working in d3-bundler, but my second example is generating duplicate Selection classes.
The broken example/two.js is:
import {select, selectAll} from "d3-selection";
import "d3-selection-multi";
export {select, selectAll};
The working example/one.js is:
import {select, selectAll} from "d3-selection";
import {ease} from "d3-transition";
export {select, selectAll, ease};
So, selection-event’s event export is dynamic: it’s set to the current event whenever an event listener is trigger. (This replaces the global d3.event
of your.) This is re-exported as event in d3-selection.
This seemed to work in Esperanto, but in Rollup’s UMD output, I noticed it’s just assigning the event to the exports
object. Thus, the exported event is always null, because the generated code internally is setting event = …
(see source) but not exports.event = …
.
foo.js:
function foo() {
return "I am foo!";
}
export default function() {
return foo();
};
bar.js:
import foo from "./foo";
foo();
Rollup of bar.js:
function _foo() {
return "I am foo!";
}
var _foo = function() {
return _foo();
}
_foo();
This causes an infinite loop because the default import from foo into bar becomes var _foo
which overwrites the earlier function _foo
.
We have a quite big (400K source) project that I would like to bundle with rollup, but it it currently fails when I use a named import from an external dependency.
The problem is here:
https://github.com/rollup/rollup/blob/master/src/Bundle.js#L238
TypeError: Cannot read property 'mat4' of undefined
I will try to reduce this to a smaller testcase and fix it in the process, but it might take me some time…
Found while working through #66 – bit of a tricky case, but is possibly superseded by #71, so am just going to leave this test case here:
// main.js
import foo from './foo';
assert.equal( foo(), 'not actually foo' );
// foo.js
export default notActuallyFoo;
function notActuallyFoo () {
return 'not ' + foo();
}
function foo () {
return 'actually foo';
}
The notActuallyFoo
function gets aliased as foo
(because of import foo...
), and ends up calling itself, blowing the stack.
Via esperantojs/esperanto#123. Currently at stage 1: https://github.com/leebyron/ecmascript-more-export-from. Probably worth considering if/when it reaches stage 2, once Acorn (or another ESTree-generating parser) handles it.
Rollup needs to be capable of resolving external modules. The obvious scenario is the one in which external modules live in a node_modules
folder, and (at least in some cases) have a jsnext:main field pointing to an ES6 module. Also, it would be good to support jspm_packages
.
But we might not want to bundle external modules, so it shouldn't necessarily be the default. Maybe it looks like this:
rollup -i main.js -o bundle.js --resolve npm jspm
rollup.rollup( 'main.js', {
resolvePath: [ rollup.npm, rollup.jspm ]
}).then( function ( bundle ) {
/* ... */
});
The other factors to consider are a) whether to try and convert legacy formats to ES6 and b) whether to support loader plugins (e.g. import 'styles.css!'
or import data from 'data.json!'
or whatever).
Need to bear in mind how all this interacts with transform
steps, caches and so on.
For example, consider test.js:
import foo from "./foo";
export {
foo
};
And foo.js:
function valueOf() {
return 42;
}
export default function() {
return valueOf();
};
The output from rollup -b -- test.js
lacks the valueOf function:
var foo = function() {
return valueOf();
}
export { foo };
Renaming the function to valueOf_ works around the issue. I suspect there is code somewhere that is using an Object as a map when it should be using a Map.
Just to say that as more and more projects/modules are switching to ES6+ using modules this concept (as you describe here) and a guide on how to optimally structure module libraries should be pushed FAR and WIDE! I know you working with Guy from jspm
and others, which is great but this really needs big publicity/visibility!
Just saying ;)
This is about as minimal a reproduction as I've been able to put together - changing just about anything seems to 'fix' it:
// somewhere in the global namespace
function getAnswer ( object ) {
return object.answer;
}
// main.js
import answer from './answer';
console.log( answer );
// answer.js
var prop,
answer;
var foo = { answer: 'wrong' };
var bar = { answer: 'right' };
if ( typeof bar === "object" ) {
for ( prop in bar ) {
if ( bar.hasOwnProperty(prop) ) {
foo[prop] = bar[prop];
}
}
}
answer = getAnswer( foo );
export default answer;
This should log 'right', but logs 'wrong' - getAnswer
is called before the if (typeof ...
block. The IIFE output looks like this:
(function () { 'use strict';
var prop,
answer;
var bar = { answer: 'right' };
var foo = { answer: 'wrong' };
answer = get_answer( foo );
if ( typeof bar === "object" ) {
for ( prop in bar ) {
if ( bar.hasOwnProperty(prop) ) {
foo[prop] = bar[prop];
}
}
}
console.log( 'answer', answer );
})();
Really loving this project! The APIs are great to work with.
Just been playing around with hooking it in to SystemJS builder and I'm even defining a custom loader to manage everything in-memory which is great.
It would be nice to be able to use the same naming system as SystemJS without having to translate into file paths, so I'm trying to set both resolvePath and resolveExternal, but it seems the entry point still gets resolved to a path.
Would it be possible to have the above resolution run through the same hooks as above?
The ES specification defines module loading through two hooks:
It would be nice to maintain some consistency with this by allowing any naming system.
I know it's very much my use case, but let me know if it's a possibility.
Unable to check right now, but I'd strongly expect this Esperanto issue to apply to Rollup as well:
import foo from 'foo';
export default {
// `foo` might be rewritten `_foo`, which means the
// shorthand property no longer works
foo
}
Here’s linear.js (abridged):
export function Linear() {};
Linear.prototype.lineStart = function() {};
Linear.prototype.lineEnd = function() {};
Linear.prototype.point = function(x, y) {};
export function LinearClosed() {};
LinearClosed.prototype = Object.create(Linear.prototype);
LinearClosed.prototype.lineEnd = function() {};
The resulting rolled-up file:
function Linear() {}
Linear.prototype.lineStart = function() {};
Linear.prototype.lineEnd = function() {};
Linear.prototype.point = function(x, y) {};
function LinearClosed() {}
LinearClosed.prototype.lineEnd = function() {};
LinearClosed.prototype = Object.create(Linear.prototype);
Note that the last two lines have been reversed, so the assignment to LinearClosed.prototype.lineEnd gets overwritten. This code is in d3-shape. I can work on creating an isolated test case if you need it.
Cases like this...
// a.js
import B from './B';
export default class A {
constructor () {}
b () {
return new B();
}
}
// b.js
import A from './A';
export default class B extends A {
constructor () {
super();
}
}
...aren't dealt with very intelligently - if a statement that's already been included in the bundle is encountered (indicating a cyclical dependency), it isn't followed a second time. So in situations like the above, if we encounter A
first, we include the definition for B
(because it's used inside the A
definition), which leads us back to A
which is ignored, even though it needs to go first.
The solution with Esperanto was to distinguish between 'strong' and 'weak' dependencies (weak meaning inside a function'), and reordering bundles with cyclical dependencies to ensure that strong dependencies appeared at the top. We can actually improve on this - because of hoisting, nothing can ever strongly depend on a function. (EDIT: actually that's not true, you can assign properties to functions which means the functions must be declared first. A function can never strongly depend on anything else, but we get that for free anyway.)
Rich
I must be missing something basic.
I have a module foo.js
:
var isTouch = true;
function fooTest() {
return isTouch
}
export { fooTest }
In my main.js
I import it successfully :
import { fooTest } from "foo";
But if I try to import from within another module, say, foo2.js
:
import { fooTest } from "foo";
This hangs rollup. What is the stupid thing I am doing wrong?? I'm following this ES6 syntax.
works:
echo "import foo from \"foo\"" > rollup.js && rollup -e foo rollup.js
fails:
echo "import \"foo\"" > rollup.js && rollup -e foo rollup.js
I’m seeing a problem in d3-color where statements are output out-of-order, and so the code crashes. For example:
__prototype.rgb = …;
… // code continues
var __prototype = Hsl.prototype = new Color;
Notice that __prototype
is defined after the assignment, and so the code throws a TypeError: Cannot set property 'rgb' of undefined.
The recent statements.sort in c0a7640 for 0.7.3 may be the cause. This looked suspicious:
// within a module, statements should preserve their original order
// TODO is this foolproof?
this.statements.sort( ( a, b ) => {
if ( a.module !== b.module ) return -1; // no change
return a.index - b.index;
});
Forgive my lack of familiarity with the code, but I am unsure what you are trying to achieve by returning -1, here. That would mean to always put a
before b
, and this logic is nondeterministic and potentially contradictory since you don’t control the underlying sort algorithm and which elements are being compared.
If you don’t care about the relative order of two statements in different modules, you might instead return zero or NaN (and perhaps rely on a stable sorting algorithm). Or, perhaps just define an arbitrary order of modules, such as by id, and compare those before comparing by index.
Anyway, that’s just my wild guess from looking at the commits since 0.7.2. I apologize if this is a distraction.
I have a very simple straightforward re-export like this:
export {json} from "./xhr"
That fails with the following error:
TypeError: Cannot read property 'isExternal' of undefined
at Module.getCanonicalName (.gobble-build/01-rollup/1/rollup.js:1238:17)
at .gobble-build/01-rollup/1/rollup.js:2055:76
Renaming it like export {json as json2} from "./xhr"
solves the problem however. So I would guess it some kind of naming conflict. Hopefully it will be solved by #71 or similar.
I haven’t been able to create a reduced testcase so far :-(
When rollup tries to bundle an external module which doesn't exist. It gets stuck in an infinite loop in defaultExternalResolver, where dir
was modified like so
'/home/user/repo' ->
'/home/user' -> '/home' -> '' -> '.' -> '.' -> ...
never reaching the terminating condition dir === '/'
.
The issue was mentioned in #52. Thanks for bringing it up @petulla!
See https://gist.github.com/mbostock/525efe52c9015002fdca for a test case.
Consider two identical foo.js and bar.js:
function thing(thing) {}
export default thing;
And an index.js which is rolled up:
import foo from "./foo";
import bar from "./bar";
export {
foo,
bar
};
The resulting code is broken:
'use strict';
function thing(thing) {}
var bar = _thing;
function thing(thing) {}
var foo = thing;
exports.foo = foo;
exports.bar = bar;
If you change foo.js or bar.js so that the argument thing
has a different name than the function thing
, the error is fixed.
It would be useful to be able to run rollup in-browser, for the sake of custom builders (cc @mbostock) and interactive demos.
There are four external dependencies - path
, sander
, magic-string
and acorn
. acorn
and magic-string
both work in-browser (and magic-string
and its only dependency use jsnext:main
, so they be bundled with Rollup). The path
functions can be replaced with internal helpers without too much difficulty.
sander
is a little trickier, since it's a wrapper around fs
. But if there were a neat way to exclude it from the build there'd be no problem - it's possible to supply a custom load
function which returns the contents of the sought module (it just so happens that the default load
uses sander
to read from disk).
Since functions are assumed to be capable of mutating their arguments, mutate
is correctly included when you import foo
:
let foo = {};
mutate( foo );
export default foo;
But the same logic includes irrelevant
:
let foo = {};
function irrelevant () {
mutate( foo );
}
export default foo;
Only top-level call expressions need be included. (As mentioned previously, it would eventually be nice to analyse function definitions and determine whether they are capable of mutating their arguments.)
Hello,
I am using the rollup command line tool, and I noticed that it breaks with the following error:
./node_modules/.bin/rollup --output dist/reactive-model.js src/reactiveModel.js
module.js:338
throw err;
^
Error: Cannot find module 'source-map-support'
at Function.Module._resolveFilename (module.js:336:15)
at Function.Module._load (module.js:278:25)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at Object.<anonymous> (/Users/curran/repos/reactive-model/node_modules/rollup/bin/runRollup.js:1:63)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Module.require (module.js:365:17)
After npm install source-map-support
everything works well, but I was just wondering if it might make sense to promote source-map-support
from devDependencies
to dependencies
in your package.json
?
Loving rollup so far, great work!
It would be awesome if there was a way to get a bit of information on the CLI in the README.
This may or may not be related to #32. Here’s the test case:
https://gist.github.com/mbostock/d7717d61446600938e47
The problem is:
var default = Baz(baz);
^^^^^^^
SyntaxError: Unexpected token default
I have code roughly like this:
// widgets.js
export {default as Box} from "./box"
// lib.js
import * as Widgets form "./widgets"
export {Widgets}
That fails with
TypeError: Cannot read property 'suggestedNames' of undefined
at Module.getCanonicalName (.gobble-build/01-rollup/1/rollup.js:1234:28)
at .gobble-build/01-rollup/1/rollup.js:2055:76
I haven’t been able to create a minified testcase yet.
Have fixed this locally, but want to leave some breadcrumbs for myself in case it comes up again. To fix #21, export default foo
statements (which are a bit of a special case) need to be moved into the correct place. But the placement was wrong - the statements were inserted before later statements from the same module, rather than after earlier statements, which turns out not to be the same thing if you have a situation like this...
var Foo = function () {
this.bar = bar();
}
export default Foo;
Foo = 'something else';
function bar() {
return 42;
}
...because the statement that defines Foo
depends on the final statement defining bar
, which meant the export default Foo
(which gets rewritten as var _Foo = Foo
, to capture the value at that moment in time) statement was being moved right to the top.
See #9 (comment). On a similar note, consecutive statements from different modules should perhaps be separated with an extra newline for readability's sake
Let’s say I have some code in foo.js:
export var quince = 42;
export default function() {
console.log("foo");
};
Meanwhile, over in bar.js:
import foo from "./foo";
export default function() {
foo();
console.log("bar", quince);
};
(Note that bar.js is referring to quince
, but I forgot to import it from foo.js. In fact, maybe I meant for quince
to refer to something else, from a different module or even a global.)
And lastly in baz.js:
import {quince} from "./foo";
import bar from "./bar";
export default function() {
bar();
console.log("baz", quince);
};
Rolling up baz.js:
'use strict';
var quince = 42;
var foo = function() {
console.log("foo");
};
var bar = function() {
foo();
console.log("bar", quince);
};
var baz = function() {
bar();
console.log("baz", quince);
};
module.exports = baz;
So, now bar.js’s quince
is referring to the one in foo.js—but only because it was imported by baz.js. It seems like since bar.js refers to the symbol quince
, the symbol imported from foo.js should be renamed to prevent masking (like foo_quince
or whatever… though of course then you have to make sure foo_quince
isn’t referred to anywhere in the original code, too).
Found while adding a test for #57 – the ES6 output should be identical to the input in this scenario:
// main.js
import factory from 'factory';
factory( null );
Instead we get this:
factory( null );
Given this situation...
// main.js
import Foo from './Foo';
var foo = new Foo();
var baz = new Foo.Baz();
// Foo.js
import { Bar } from './Bar';
import { Baz } from './Baz';
Bar.Baz = Baz; // this statement is ignored
export default Bar;
// Bar.js
export function Bar () {
alert( 'bar' );
}
// Baz.js
export function Baz () {
alert('baz');
}
...we'd expect Foo
to have a Baz
property, but Rollup goes straight to the original Foo
definition, ignoring the Bar.Baz = Baz
line:
function Bar () {
alert( 'bar' );
}
var Foo = Bar;
var foo = new Foo();
var baz = new Foo.Baz();
We need to catch any statements that mutate imported bindings, wherever they are.
Discovered while refactoring:
import { parse } from 'acorn';
class Module {
...
parse () {
// ...
}
}
The parse
method name is incorrectly rewritten as acorn.parse
.
Real edge case, but part of the spec nonetheless. Test here, currently marked with skip: true
Too lazy to check right now, but will need to ensure that esperantojs/esperanto#188 doesn't appear in this project
Found while investigating #26 - there's a test for it, but it was being misled by the fact that functions created with new Function
have an undefined
context by default.
When I attempt to rollup
code like that below, I get this error:
Module wat.js does not export wat (imported by main.js)
I assume this is due to "export * from ...". Minimal example:
// --- main.js
import { wat } from './wat';
wat();
// --- wat.js
export * from './wat-impl';
// --- wat-impl.js
export function wat() {}
Do you have plans to support this pattern in the pipeline?
I ran into an error when trying to rollup a module that uses the following export-from form:
export {default as Foo} from 'foo';
This is more of a question than an issue. Does it make sense that I have to import twice in order to achieve an import with side effects? Consider the following D3 build:
import {
event,
mouse,
namespace,
namespaces,
requote,
select,
selectAll,
selection,
touch,
touches
} from "d3-selection";
import {
ease,
transition
} from "d3-transition";
import "d3-transition";
export default {
get event() { return event; },
mouse: mouse,
namespace: namespace,
namespaces: namespaces,
requote: requote,
select: select,
selectAll: selectAll,
selection: selection,
touch: touch,
touches: touches,
ease: ease,
transition: transition
};
The first import of d3-transition exposes ease and transition. But the second is also needed to set selection.prototype.transition.
It makes sense that Rollup would ignore the side-effects by default, so that I can explicitly chose to include that code (or not). But I wanted to double-check that this seems right to you.
I should be able to do this, right?
import {bisectRight, bisectLeft} from "./src/bisect";
export {
bisectLeft,
bisectRight,
bisectRight as bisect
}
Please think about poor guys like me with notebooks where every space is valuable.
https://github.com/rollup/rollup/blob/master/src/finalisers/iife.js#L31
Bundling the following to UMD, where 'factory' is external
import factory from 'factory';
factory(null);
// yields:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('factory')) :
typeof define === 'function' && define.amd ? define(['factory'], factory) :
factory(factory);
}(this, function (factory) { 'use strict';
factory(null);
}));
As you can see, the UMD factory function is passed itself instead of it's dependency. Mitigated by prefixing dependency name with global.
.
typeof define === 'function' && define.amd ? define(['factory'], factory) :
- factory(factory);
+ factory(global.factory);
}(this, function (factory) { 'use strict';
Unused test here
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.