Learn about node modules and their scopes, the npm path lookup, the import/export statements, what can be exported, and destructuring with import.
- [Instructor] To work in a Node project, we first have to understand how the module system work. We bring in a module dependency using an import line. For example, say that we have a config module somewhere. We require it with the import config line. This syntax, however, looks for config as either a core module or an npm installed module in node modules. If we want to place our config.js file somewhere else, we can use a relative path in the string, here.
For example, ./config tells Node to look for config.js on the same level as the current file. We can also use ../ to go up one level if we want to. Let's create a config.js file here on the same level as server.js. And put a simple console.log line in here. Since we're using the new import syntax, we need to use babel-node here to test the server, but we only installed babel-node locally, not globally.
It's available under ./node_modules/.bin/babel-node, and we can invoke it from there directly. However, instead of using the .bin path like this, we can actually make ./node_modules/.bin/ part of the global path variable. All we need is to edit the bash_profile file. This is on Mac, though, so on Windows things will be different. And we want a export path to be the current path adding ./node_modules/.bin just like that.
This is a relative path, so when we go to any node project the ./node_modules/.bin folder will be included in the global path, which is really handy. To reload this file, close and open the terminal. And now babel-node should be available directly here thanks to the relative path we just added. No need to install a global binary. All import calls are cached. This means if we re-import the config, we're not really evaluating the config file content again.
It will just be read from the cache. This is why it's okay to import the same file multiple times from multiple other files, because the cache will be used after the first import. It's important to understand that every module gets its own private scope. So, defining a top-level variable here, for example, env = process.env. This does not mean that we're putting the variable env on the global scope, unlike a browser environment. So, if I try to console.log(env) in server.js, this will not work, because env is undefined on server.js.
It's defined in config.js. So, with node modules we don't have to wrap things in an IIFE to get a new scope. Node actually does the wrapping for us automatically, which is neat. Let's clean that up. I'm actually going to remove the console.log line, and let's actually make this into a constant, because I'm not going to be changing it. Usually when we import something we import it into a variable, just like this. And let me go ahead and console.log(config).
So, right now this config is actually an empty object, because we have not exported anything in config.js. So, let's go ahead and export something. When we import with this syntax, we're importing the default exported object in the config module. For example, let's export default object with a port property, and let's make this property reads from env.PORT and default to 8080. This way we can control the port from the process, but we don't have to.
Now, our import from line places the default export into the config variable so we can read the port property from the server.js file. We can also export other things beside the default object. For example, let's export a constant, nodeEnv. Set that to env.NODE_ENV and default to development. To import a non-default export, we need the destructure syntax, nodeEnv.
And let's go ahead and console.log that as well. And there you go. We can also export functions like this logStar, here. When we import the function, we also need to destructure this, because it's not a default export. We can simply invoke the logStar variable, because it holds a function reference.
- Configuring webpack and Babel
- Working with native Node modules
- Creating an Express server
- Working with React components and JSX
- Loading and working with test mock data
- Fetching data from a remote API
- Working with data in MongoDB
- Isomorphic rendering on the server
- Front-end routing and back-end routing