Most people treat these is interchangeable:
// named import
import { bar } from './foo.js';
bar();
// namespace import
import * as foo from './foo.js';
foo.bar();
Generally, the point here is that foo
is a collection of functions (or other values) — it's not supposed to be thought of as an object. If the author wants bar
to be a method of foo rather than a standalone function, she should write it as such and have a default export foo
with a property bar
. (This isn't just an aesthetic choice — the author has no control over which import form people will use. Assuming people will use the namespace form is bad programming.)
Rollup treats the two forms as equivalent (demo 1, demo 2). If it didn't, it would have to import all of foo
, including the bits that aren't used. (It does deoptimise like this if there's a dynamic lookup on foo
, or if foo
is e.g. exported or passed to a function.) That would suck.
The only time the two forms aren't equivalent is if bar
uses this
. If Rollup can analyse bar
and determine that that's the case, it can a) warn and b) deoptimise. (That doesn't currently happen but it could.) But if bar
looked like this...
function makeAFunction () {
return function () {
console.log('analyse', this);
}
}
export const bar = makeAFunction();
...then analysis gets much harder — in some cases, it would be impossible. So Rollup is faced with a choice between a) deoptimising every time it can't fully analyse a namespace import (lots of false positives, would completely defeat tree-shaking), and b) not being 100% spec-compliant in this case, where the author wrote some bad code. The ideological choice is b, the pragmatic choice is a.
Thinking about this more - using
import *
is an uncommon case imo, but certainly usingimport *
for reflection is even less common - if you apply your heuristics, it seems like you'll come up with the following categories:import *
, but only used staticallyimport *
, ? ? ? (some small percentage of this group usesthis
)The question is then what to do in the third group - one choice is to import the whole module (correct per spec, but slower); another choice is to bail out and refuse to continue (advising them to avoid
import *
, or use some sort of override comment); another choice is to silently do the wrong thing for named imports usingthis
.I'd be very surprised if the number of people impacted by "bail out" is significant; and my suspicion is that this would be a better approach than risking silent failure in any situation. Thoughts?