Learning Journal Node.js: import modules

Learning Journal Node.js: import modules

Questions

Hello! Welcome to my day-to-day learning of Node.js. :)

  1. How do you import a 3rd party module into the JS file you're working with?

  2. How do you import your own JS file into the file you're working with?

Does require syntax allow for named imports / exports, or does it need to be exported as a default that's then destructured?

How do you import a 3rd party module?

The first step in importing a 3rd party module is to install it using npm.

If we're trying to load in uuid, for example, we would run the command:

npm install uuid

This adds the uuid module as a dependency to the project and loads the module source to the node_modules folder in the project directory's root.

After the module source is loaded into the node_modules directory, the process is the same as with using a native module. If, for example, you have a module called uuid, you would specify a variable to be used as a reference for the module:

const uuid = require('uuid')

const id = uuid.v4()
console.log(id) // 61b702dd-5169-430b-9e73-dcebe914708e

If you need to reference a specific version number of the module, you can use the @ syntax to lock down the version. For example:

npm install uuid@8.2.0

This will add an entry to package.json's dependencies with uuid as the property with ^8.2.0 as the value, and the TAR Archive file reference is added to the package-lock.json.

// package.json
{
  ...
  "dependencies": {
    "uuid": "^8.2.0"
  }
  ...
}
// package-lock.json
{
  ...
    "node_modules/uuid": {
      "version": "8.2.0",
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz",
      "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==",
      "bin": {
        "uuid": "dist/bin/uuid"
      }
    },
  ...
}

Note on versioning

The package.json may contain a different version number for a given module than the package-lock.json. This can be the case when running npm install or when adding new modules to the project, and if the module's version number is not locked down. Generally, I've seen utility to allow for fix versions to flow into the project. It can, however, be problematic if minor versions are allowed to flow into the project and a significant bug is introduced as a result. This can be particularly troubling when you're only anticipating bugs to be introduced by your project rather than an open-source project's module.

How do you import your own JS modules?

Each JS file has its own scope. So any variables you define, for example, in app.js are out of scope in utils.js--even if you import utils.js into app.js. To bring a given reference into scope, the imported file must use the module.exports syntax. This is essentially a default export, that can then be referenced with the require syntax.

For example, if we try to import a single reference:

// utils.js
const name = 'Nathan'

module.exports = name
// app.js
const name = require('./utils.js')

console.log(name) // "Nathan"

The name reference defined in the utils.js file can now be used in the app.js file.

We can also use the module.exports syntax to export a mapped object, containing multiple references:

// utils.js
const name = 'Nathan'
const add = (a, b) => {
  return a + b
}

module.exports = {
  name,
  add,
}
// app.js
const utils = require('./utils.js')

console.log(utils.name) // "Nathan"
console.log(utils.add(3,2)) // 5

Does require syntax allow for named imports / exports?

While it appears that require syntax does not allow for named exports, we can leverage ES6 destructuring syntax to pull out the individual references, and treat the module.exports it like a named import:

// utils.js
const name = 'Nathan'
const add = (a, b) => {
  return a + b
}

module.exports = {
  name,
  add,
}
// app.js
const { name, add } = require('./utils.js')

console.log(name) // "Nathan"
console.log(add(3,2)) // 5