124

Does the code inside the js file gets run during the import? if yes, then once or each time? e.g.

// a.js
console.log("A");
const a = "a"; 
export default a;

// b.js
import a from "./a"; // => console logs?

// c.js
import a from "./a"; // => console logs again?
Inigo
  • 12,186
  • 5
  • 41
  • 70
mbehzad
  • 3,758
  • 3
  • 22
  • 29

3 Answers3

112

Yes, it does, exactly one time.

See http://www.ecma-international.org/ecma-262/6.0/#sec-abstract-module-records:

Do nothing if this module has already been evaluated. Otherwise, transitively evaluate all module dependences of this module and then evaluate this module

Radu
  • 8,561
  • 8
  • 55
  • 91
  • 1
    i could only test it in combination wit webpack. is the execution the default browser behavior (defines in the specs). and would this be ok to use or is it an anti-pattern? (thanks, i corrected the parenthesis) – mbehzad May 19 '16 at 14:12
  • 4
    @user2520818: *"Do nothing if this module has already been evaluated. Otherwise, transitively evaluate all module dependences of this module and then evaluate this module."* http://www.ecma-international.org/ecma-262/6.0/#sec-abstract-module-records – Felix Kling May 19 '16 at 17:07
  • There's no need for web pack to test this. For instance, you could just run it with babel-node. It's not an anti-pattern. It's just the way it works. It may or not work in your favorite browser at the moment, but any environment that does execute it will execute it this way. –  May 19 '16 at 17:23
  • 7
    There's a difference between "why do you just try and it mess around" vs. "it's guaranteed to have this behavior every single time with no exceptions" ;) – Ryan Taylor Jul 23 '19 at 17:06
  • This is not completely correct. See my answer below. – andyhasit Nov 27 '20 at 16:40
24

A module will only be evaluated once but it is possible to have two copies of the same module installed in a project, in which case that module and the code in it will be executed twice.

Consider the following package structure:

index.js
package.json
node_modules/
├── package_b/
│   └── node_modules/
│       └── package_a/
|           └── index.js
└── package_c/
    └── node_modules/
        └── package_a/
            └── index.js

If the top level index.js imports from package_b and package_c, then package_a will be imported (and therefore evaluated) twice.

Most people are not aware of this behaviour yet probably need to be if they landed on this particular question.

Here is an old but good article on understanding-the-npm-dependency-model with further detail on how and why npm does this.

andyhasit
  • 14,137
  • 7
  • 49
  • 51
  • 4
    I think this answer is misleading and wrong. The applicable spec given the title of the question is ECMAScript 6, not "the npm dependency model". Specifically [Module Semantics](https://262.ecma-international.org/6.0/#sec-module-semantics) and [HostResolveImportedModule](https://262.ecma-international.org/6.0/#sec-hostresolveimportedmodule). And even for `npm`, the linked article speaks of *copies* of modules (e.g. different versions, at different paths, running in their own sandbox). Thus even for `npm` the same module code does not run twice. – Inigo Jan 07 '22 at 04:16
  • 1
    @Inigo ES6 I think you misunderstood the answer, for it is correct, at least with latest versions at time of writing. As for scope, ES6 is predominantly used in a node+npm environment, where the accepted answer is dangerously incorrect, so this is a perfectly valid and helpful answer. Remember the point of this site is to help each other fix or avoid problems ;-) – andyhasit Jan 08 '22 at 17:18
2

In case someone is using TypeScript with "module": "es6" and wondering how to do this, use the globalThis keyword:

function outputMsg(msg: string) : void {
    console.log(msg);
}

// export function for global scope
globalThis.outputMsg = outputMsg;

and then call outputMsg("my console output") as usual in the Chrome DevTools console and it should autocomplete and run your function.

You could also rename your "global export":

globalThis.myCrazyFunc = outputMsg;

and call myCrazyFunc("crazy message") in the console.

balanceglove2
  • 398
  • 5
  • 12