Importing and Exporting
Whether we’re writing code to be run in web browsers, the console, or anywhere else, having a system for sharing code between files is essential for building projects. Imagine needing to write and read thousands of lines of code in a single file, or using multiple files but needing to copy functions to every file where they need to be used. What horror! This lesson is about the import and export system specifically with Node.js, familiarly known as “node”.
Exporting
JavaScript code in our files is never automatically exported. In order to be able to share code from one file to another, we need to explicitly write which code can be shared. Every JavaScript file that is run with node has a hidden variable called module.exports
. If we don’t explicitly set this variable to any value, its value is an empty object {}
. Whatever value we give to module.exports
is what the file is exporting (meaning it can be imported by another file). The reason for the name module.exports
is because node considers every JavaScript file a module. It is most common to export an object because, as we’ve seen, objects allow us to package many things into one value.
Let’s look at an example.
const a = 1;
const b = 2;
.exports = {
modulec: 3
; }
If we have a file with the above code, the file is exporting an object with a single property c: 3
. The variables a
and b
are not being exported, thus they are not being shared with any other file. If we want to share them, we can add them to the exports as well:
const a = 1;
const b = 2;
.exports = {
modulea: a,
b: b,
c: 3
; }
It is common to use shorthand notation in the object for this.
const a = 1;
const b = 2;
.exports = {
module,
a,
bc: 3
; }
Importing
The special function for importing a module in node is require()
. When we call require()
with the name of a module (a JavaScript file), it runs all the code in that module then retrieves the module.exports
value of that module. Now we can look at complete examples. Keep in mind that if you want to try these examples out, you will have to create separate files (suggested file names are given).
// Inside numbers.js:
const a = 1;
const b = 2;
.exports = {
module,
a,
bc: 3
; }
// Inside index.js:
const someNumbers = require('./numbers.js');
console.log(someNumbers.a); // 1
console.log(someNumbers.b); // 2
console.log(someNumbers.c); // 3
In the above example, we want to run the index.js
file, since running numbers.js
will not produce any output. So we run the command: node index.js
. (The name “index” is commonly used for the main file, for historical reasons.) It is important in this example that we write require('./numbers.js')
instead of require('numbers.js')
because we want to import a local file; the latter tells node to import an external module from a different place, which is explained in the next section.
Object destructuring is commonly used when importing because it skips the step of needing to give the export object a name and it allows us to selectively import properties.
// Inside numbers.js:
const a = 1;
const b = 2;
.exports = {
module,
a,
bc: 3
; }
// Inside index.js:
// Import only a and c from the numbers module
const {a, c} = require('./numbers.js');
console.log(a); // 1
console.log(c); // 3
Finally, let’s look at a more realistic example: sharing a little library of functions.
//Inside functions.js:
const fToC = ftemp => (ftemp - 32) / 1.8;
const cToF = ctemp => (ctemp * 1.8) + 32;
const convertTemperature = (temp, conv) => {
if (conv === 'FtoC') {
return fToC(temp);
else {
} return cToF(temp);
};
}
const isEven = x => x % 2 === 0;
const isOdd = (x) => !isEven(x);
.exports = {
module,
convertTemperature,
isEven
isOdd; }
// Inside index.js:
const {
,
isEven
convertTemperature= require('./functions.js');
}
const x = 24;
if (isEven(x)) {
console.log(convertTemperature(x, 'CtoF')); // 75.2
}
It is generally considered good practice to put exports at the bottom of a file and imports at the top of a file.
Built-in Modules
Now that we’ve seen how to import code from a module that we created, let’s look at importing code from a module that we own but didn’t create. Node comes with built-in modules that are available for us to use but only if we import them. One such example is the fs
module, for dealing with the file system. Importing a built-in module is the same as importing a module that we created, except the argument we give to require()
should have the name of the module without the path; node knows where to look for built-in modules on our system.
const {readFileSync} = require('fs'); // No dots or slashes before the module name
const fileContents = readFileSync('my-test-file.txt', 'utf8'); // Read the contents of a file
console.log(fileContents); // Print the file's contents
The above example will read the contents of a file named my-test-file.txt
that exists in the same directory as the JavaScript file we’re running this code from, then print it out.