9

I was wondering if there is any difference in memory and performance between the 2 import.

If I have lodash in my node module, does it compile all the file anyway no matter the import?

ProgrammerGoku
  • 103
  • 1
  • 6
  • You can measure the memory usage / speed on your machine and look at the results. – byxor Jul 25 '17 at 13:48
  • 1
    It really depends on what module bundler you are using. And if you're talking of native javascripts modules, you should tag this with ES8 instead of ES6 – Ulysse BN Jul 25 '17 at 13:49
  • @UlysseBN Did ES8 change anything about modules? – Bergi Jul 25 '17 at 16:20
  • Oh my bad, I wrote too much about async/await and got confused.. This is indeed part of [ES6](http://www.ecma-international.org/ecma-262/6.0/#sec-imports). – Ulysse BN Jul 25 '17 at 16:37
  • 2
    Please, check this out - https://stackoverflow.com/questions/35250500/correct-way-to-import-lodash – Daniel Mylian Jul 25 '17 at 18:11

1 Answers1

11

In theory, based on the specification for import, yes, there is supposed to be a difference.

The specification allows for a compliant optimization to use static analysis of a named import in order to only load what is required to provide indexOf(), if the lodash module is written as an ES2015 module.

It would create an ImportEntry record that keeps references to how to resolve the import when running static analysis on the ES2015 module, so that only the relevant export's would be evaluated.

In practice, this is not so simple, and since there is currently not a native implementation, transpilers like Babel will convert the ES2015 import syntax into a CommonJS functional equivalent.

Unfortunately, this functionally equivalent method must still evaluate the entire module, since its exports are not known until it has been fully evaluated.

This is why the ES2015 specification requires import and export to be in the top-level scope, so that static analysis will allow a JavaScript engine to optimize by determining what portions of the file can be safely omitted when evaluating code for an export.

On the other hand, there are non-native bundlers like Rollup and Webpack that perform static analysis in order to do tree-shaking and remove sections of dead code that are not referenced by import's to the module within the bundle. This optimization is independent of the use of import / export, but using named imports instead of glob stars allows for easier and more optimal static analysis to occur within these bundlers, and eventually any native implementation that will be released in the future.

TL;DR

In theory, yes there is a difference, but in practice, there isn't a difference until native implementations are available for import / export, or unless you use a bundler that performs static analysis and tree-shaking independent of the actual syntax and specification.

In any case, it is recommended to use named imports, so that you can incur any possible optimizations in whatever environment you're using.

ECMAScript Section 15.2 Modules Specification

Community
  • 1
  • 1
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • ES2018 has not yet been released? – Bergi Jul 25 '17 at 16:27
  • @Bergi I didn't even address that. I'm just saying until native implementations of `import` and `export` are available, there's no incurred performance boost from using the new syntax and transpiling it to CommonJS. – Patrick Roberts Jul 25 '17 at 16:31
  • 1
    This is partially wrong. You assume OP is using Babel for module transpiling, which he may not be. Both rollup and webpack use native ES6 `import` and `export` to perform tree-shaking (amongst other), thus are more performant when only including what you need in code. – Ulysse BN Jul 25 '17 at 16:39
  • 1
    @PatrickRoberts I just wondered why you linked the ES2018 draft instead of the current standard, or ES6 in which modules were specified for the first time. – Bergi Jul 25 '17 at 16:41
  • @Bergi oh, when I googled for the specification, those were the first specs that came up for me, plus in the comments, I saw it was mentioned that the question should be tagged ES8, so I figured I'd address from the perspective of the most recent spec. If you'd like, you can provide me links for the older specs I can update with those in addition, or instead of. – Patrick Roberts Jul 25 '17 at 16:43
  • 1
    @PatrickRoberts http://www.ecma-international.org/ecma-262/ is the current one - http://www.ecma-international.org/ecma-262/8.0/ or http://www.ecma-international.org/ecma-262/6.0/ might also work – Bergi Jul 25 '17 at 16:45
  • @UlysseBN If that is why you are accusing my answer of being partially wrong, you are "partially wrong" as well. Rollup and Weback don't use "native" implementations, but they do use static analysis for tree-shaking where possible, and that is still not the same thing. You're not incurring the performance boost from using `import` and `export`,you're incurring it from how you write the module, and from what bundler you use. You could write the functionally equivalent CommonJS in Webpack, for example, and it would still perform the tree-shaking, if your module separates concerns well enough. – Patrick Roberts Jul 25 '17 at 16:48
  • @UlysseBN I could include that information if you want, but that's sort of tangent to the issue of whether specifically using the `import` / `export` syntax in itself incurs a performance boost. Do you see what I'm saying? – Patrick Roberts Jul 25 '17 at 16:52
  • I'm not sure I fully understand your point.. Mine is that, _for now_, import and export are widely depending on module bundlers (and babel). Anyway according to OP's question, and supposing you are using a bundler that performs tree-shaking. Then **it is better** to import a single method from lodash than the whole package, in practice. – Ulysse BN Jul 25 '17 at 17:01
  • 1
    `the named import will only load what is required to provide indexOf`, that's not true. ES import/export still requires loading and executing all imported files, since any file may have side-effects. Dead code elimination is slightly easier with named imports, but tools could still see that only `_.indexOf` is the only property used on the namespace object, but that is outside the scope of the ECMA specs. – loganfsmyth Jul 25 '17 at 17:03
  • @UlysseBN okay, _that_ I agree with. It's more recommended to be more specific with the `import` than more broad. My point was that the argument you were making was based on tree-shaking performed by bundlers, and I was saying that the tree shaking was performed regardless of whether the CommonJS syntax or ES2015 module syntax was used, it just depends on how you write the module in either case, and it's less about specifically using ES2015 modules. – Patrick Roberts Jul 25 '17 at 17:04
  • @loganfsmyth Sorry, I guess what I should have said is that the specification for named imports allows this optimization to occur while remaining within compliance to the specification. – Patrick Roberts Jul 25 '17 at 17:06
  • Fair, even then though, unless you're using computed properties on the namespace object, or it is being passed around as an misc object, you can do the same analysis looking at the properties used from the namespace object. It isn't required that you use named imports to get that optimization. – loganfsmyth Jul 25 '17 at 17:09
  • Alright, I think I've addressed everyone's concerns with this edit. Thanks for the feedback and let me know if anything else seems off, or if I missed anything. Thanks @Bergi for the links. – Patrick Roberts Jul 25 '17 at 17:15