Shai UI
Shai UI

Reputation: 51976

Using external javascript files in node.js without using export and require

I don't like the whole export/require stuff in node, it takes too long. Let's say I have a file server.js and I want to use functions in whatever.js. in html I just add this to the header:

<script src='whatever.js'></script>

and then I can just use all the functions of whatever.js in my body's script.

But in node, in the server.js file I'd do:

var myobject = require('./whatever.js');

but then I need to set it to myobject, and further I need to go to whatever.js and manually decide what functions I want to export. not to mention that typing myobject.someFunction() is alot longer to write than someFunction() and I need to remember what I exposed/didn't expose.

I wanted something where I could just go:

require('./whatever.js');

and it puts it ALL in global, no bs. like in good old html/javascript. Is there a way to do this in node?

Upvotes: 3

Views: 2748

Answers (2)

jacobq
jacobq

Reputation: 11587

(I realize this is an old thread but wanted to leave a note here for posterity.)

Here in 2022 there are several approaches for executing code from different files with Node.js:

ESM: Use standard ECMAScript modules

At the time of this writing, much of the node ecosystem (i.e. packages on npm) is in the process of transitioning to this paradigm, and there are some associated growing pains (e.g. things like __dirname are only available in CJS not ESM, though the workaround is easy). For most developers, it would be advisable to become comfortable with this standard as it transcends node.js (i.e. is implemented in other runtimes like Deno and web browsers) and has been years in the making.

CJS: Use the original "CommonJS" module mechanism, e.g. require('./some-script.js')

It should be noted, particularly for the OP, that even though the "intended" way to use CJS modules is to export functions, constants, etc. and import them explicitly, it is possible to define everything in global scope using globalThis, though I would not recommend this.

// my-script.js
require('./foo.js');
require('./bar.js');
foo(); // This is foo from <...>foo.js
console.log(`bar = ${bar} (in ${__filename})`); // bar = 123 (in <...>my-script.js)

// foo.js
globalThis.foo = function() {
  console.log(`This is foo from ${__filename}`);
}

// bar.js
globalThis.bar = 123;

If you try omitting globalThis. you'll find that foo and bar are no longer defined in the main script because require "wraps them" in "module scope."

Use eval

In my experience, there are very few legitimate use cases for eval (see Never use eval()!). Nevertheless, the functionality requested in this question is precisely what eval provides: "run some code as if it were written right here" and you can feed it from a file, as explained above by Mehul Prajapati

// include.js 
// Defines a global function that works like C's "#include" preprocessor directive
const { readFileSync } = require('fs');
globalThis.include = function(scriptFile) {
  console.warn('!!! EXTREMELY INSECURE !!!');
  eval(readFileSync(scriptFile, 'utf-8'));
};


// main.js
require('./include.js'); // loads global include

// (I sure hope you completely trust these sources)
include('./foo.js');
include('./bar.js');

Note: Something that has contributed to much of my confusion in the past is that there have been competing standards/conventions/APIs that use some of the same identifiers, namely require, which require.js and other bundlers that support AMD (Asynchronous Module Definition) use with different semantics. So for someone building a web application (using AMD for modules in web browsers) with node.js tooling (using CJS for modules locally) it can be frustrating to keep the functions straight, especially if it's an Electron application, which can expose Node.js APIs to scripts running in the renderer (browser). If you find yourself confused why a module is "not found" in a situation like that, check the stack trace to see which require is being called (and you may have to wrap/rename them on globalThis or something to avoid collisions).

Further reading:

Upvotes: 2

Mehul Prajapati
Mehul Prajapati

Reputation: 1260

This will do the trick,

var fs = require('fs');

eval(fs.readFileSync('whatever.js')+'');
 // here call functions from whatever.js file

Upvotes: 5

Related Questions