mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-03-27 11:01:38 -04:00
feat(curriculum): add Working with npm Scripts theory block (#64221)
Co-authored-by: Tom <20648924+moT01@users.noreply.github.com> Co-authored-by: Kolade Chris <65571316+Ksound22@users.noreply.github.com>
This commit is contained in:
@@ -7467,6 +7467,12 @@
|
||||
"Learn the fundamentals of how web communication works through the HTTP request-response model, explore different types of web assets and responses, and understand how forms handle data submission using various HTTP methods."
|
||||
]
|
||||
},
|
||||
"lecture-working-with-npm-scripts": {
|
||||
"title": "Working with npm Scripts",
|
||||
"intro": [
|
||||
"Learn about npm scripts, publishing packages to the npm registry, and working with CommonJS and ES modules. These lessons cover essential Node.js development tools and module systems."
|
||||
]
|
||||
},
|
||||
"exam-back-end-development-and-apis-certification": {
|
||||
"title": "Back End Development and APIs Certification Exam",
|
||||
"intro": [
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Introduction to the Working with npm Scripts
|
||||
block: lecture-working-with-npm-scripts
|
||||
superBlock: back-end-development-and-apis-v9
|
||||
---
|
||||
|
||||
## Introduction to the Working with npm Scripts
|
||||
|
||||
Learn about npm scripts, publishing packages to the npm registry, and working with CommonJS and ES modules. These lessons cover essential Node.js development tools and module systems.
|
||||
@@ -0,0 +1,354 @@
|
||||
---
|
||||
id: 692ab9f91d74951aeba05c00
|
||||
title: What Are npm Scripts?
|
||||
challengeType: 19
|
||||
dashedName: what-are-npm-scripts
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you'll learn about npm scripts.
|
||||
|
||||
Before we dive in, let's review some important concepts:
|
||||
|
||||
* **npm** is a command-line tool that you can use to install and manage JavaScript packages.
|
||||
|
||||
* A **package** is a directory that groups related code in a logical structure.
|
||||
|
||||
* A **script** is a sequence of instructions or commands written in a scripting programming language.
|
||||
|
||||
|
||||
**npm scripts** are custom commands that you can define in the `package.json` file of your application.
|
||||
|
||||
They are helpful for automating tasks and workflows that you will use repeatedly throughout the development, testing, and deployment phases of your project.
|
||||
|
||||
For example, one use case for npm scripts is customizing `npm start` to start your entire development environment. Instead of manually writing all the commands one-by-one every time you need to start your development environment, you can just run `npm start` and the entire process will be executed.
|
||||
|
||||
You can also use npm scripts to automate linting throughout your codebase and for running test suites, among other use cases.
|
||||
|
||||
They are very powerful, so let's check out their fundamentals.
|
||||
|
||||
## How to Create a package.json File
|
||||
|
||||
To be able to create and run custom npm scripts, you'll need a `package.json` file.
|
||||
|
||||
The `package.json` file is essential for Node.js projects. This file contains the metadata, dependencies, and scripts of the project.
|
||||
|
||||
As a reminder, to create a `package.json` file, you must run the `npm init` command in the root directory of your project. Then you can enter in the package name, version, description, and other details in manually, or leave those fields blank to use the default values.
|
||||
|
||||
Once you finish this process, you'll have a `package.json` file in the root directory of your project.
|
||||
|
||||
If you kept all the default values, you should see these key-value pairs when you open `package.json` in your code editor:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "<project_name>",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": ""
|
||||
}
|
||||
```
|
||||
|
||||
Notice this key-value pair over here:
|
||||
|
||||
```json
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
}
|
||||
```
|
||||
|
||||
This is where you will specify your npm scripts, under the `scripts` key.
|
||||
|
||||
You will see one script there by default, the test script:
|
||||
|
||||
```json
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
```
|
||||
|
||||
This is an example of an npm script defined in `package.json`.
|
||||
|
||||
Here is the basic syntax for defining an npm script:
|
||||
|
||||
```json
|
||||
"<script_name>": "<commands>"
|
||||
```
|
||||
|
||||
To the left of the colon, we find the script name. Common ones include `run`, `start`, `test`, `build`, `dev`, and `lint`. These names act as "shortcuts" for their underlying commands on the right.
|
||||
|
||||
To the right of the colon, we find the underlying commands themselves.
|
||||
|
||||
For example:
|
||||
|
||||
```json
|
||||
"scripts": {
|
||||
"start": "node app.js"
|
||||
}
|
||||
```
|
||||
|
||||
To run the script, enter this in the command line:
|
||||
|
||||
```bash
|
||||
npm run <script_name>
|
||||
```
|
||||
|
||||
And that's how you can run any custom scripts defined in `package.json`.
|
||||
|
||||
Sometimes you can use this shorthand version without the word `run` to execute scripts:
|
||||
|
||||
```bash
|
||||
npm <script_name>
|
||||
```
|
||||
|
||||
But this only works for specific npm scripts named `start`, `test`, `stop`, and `restart`.
|
||||
|
||||
Going back to our example, if we have this in `package.json`:
|
||||
|
||||
```json
|
||||
"scripts": {
|
||||
"start": "node app.js"
|
||||
}
|
||||
```
|
||||
|
||||
To run the npm script, you need to enter `npm run start` in the command line. When you do that, the actual underlying command that's executed is `node app.js`.
|
||||
|
||||
Since this npm script has a shorthand version, you could also use `npm start` and the result would be the same.
|
||||
|
||||
In this case, you're just replacing a simple command, `node app.js`, with another one, `npm start`. But imagine if you had a sequence of complex commands that need to be executed in sequence or in parallel, and you could just use `npm start` to run all of them. That would save you a lot of time, right? That's where the power of npm scripts really shines.
|
||||
|
||||
Here's a quick overview of some of the most commonly used npm scripts:
|
||||
|
||||
* `npm run`: used to run a custom npm script.
|
||||
|
||||
* `npm start`: used to start the main application or development server.
|
||||
|
||||
* `npm lint`: used to run a code style checker to check if your code meets code style standards and best practices.
|
||||
|
||||
* `npm test`: used to run the project's test suite.
|
||||
|
||||
There are many other npm scripts for different purposes, but these are some of the most common ones you'll see.
|
||||
|
||||
Also, a common convention is using a colon to group related scripts under the same namespace. For example, `start:server` and `start:ui`.
|
||||
|
||||
## How to Run Commands Sequentially
|
||||
|
||||
If you need to run multiple commands in a sequence, you have two options. You can either use the logical AND operator (`&&`) or the semicolon (`;`). Let's check out their differences.
|
||||
|
||||
The logical AND operator runs the next command only if the first one runs successfully.
|
||||
|
||||
For example:
|
||||
|
||||
```json
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"start": "npm run build && node server.js"
|
||||
}
|
||||
```
|
||||
|
||||
Notice that there is a logical AND operator in the `start` command:
|
||||
|
||||
```json
|
||||
"start": "npm run build && node server.js"
|
||||
```
|
||||
|
||||
Here, `npm start` will try to run `npm run build` first, and only if this script runs successfully, `node server.js` will be executed.
|
||||
|
||||
This is a very common approach because it ensures reliability and prevents wasting time and resources on subsequent commands that may fail or throw errors if the previous one fails.
|
||||
|
||||
Alternatively, you can use the semicolon operator to run commands sequentially, regardless of whether the previous command was successful or not.
|
||||
|
||||
In our example, this simple change would have an important impact on how the commands will run:
|
||||
|
||||
```json
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"start": "npm run build; node server.js"
|
||||
}
|
||||
```
|
||||
|
||||
Focus on the `start` command again:
|
||||
|
||||
```json
|
||||
"start": "npm run build; node server.js"
|
||||
```
|
||||
|
||||
Now, since we are using a semicolon instead of the `&&` operator, the `node server.js` command will always run after `npm run build`, even if `node server.js` was not successful.
|
||||
|
||||
```json
|
||||
"start": "npm run build; node server.js"
|
||||
```
|
||||
|
||||
## How to Run Commands Concurrently
|
||||
|
||||
If you need to run commands concurrently (in parallel), you can use the `&` operator.
|
||||
|
||||
```json
|
||||
"scripts": {
|
||||
"start:server": "node server/index.js",
|
||||
"start:client": "npm run build:watch",
|
||||
"dev": "npm run start:server & npm run start:client"
|
||||
}
|
||||
```
|
||||
|
||||
However, you should know that this option runs the processes in the background.
|
||||
|
||||
This means that, if you run them in the same terminal session, you may see their combined output, which may be difficult to understand.
|
||||
|
||||
Other options for running commands concurrently include tools like `concurrently` and `npm-run-all`.
|
||||
|
||||
## How to Pass Arguments to npm Scripts
|
||||
|
||||
If you need to pass arguments directly to the command that is being executed within the npm script, you can specify them in the command by writing two hyphens (`--`) followed by the arguments.
|
||||
|
||||
The `--` tells npm that everything after it will be arguments for the underlying commands that the npm script will execute.
|
||||
|
||||
This is the general syntax:
|
||||
|
||||
```bash
|
||||
npm run <script_name> -- <argument_1> <argument_2> <argument_3>
|
||||
```
|
||||
|
||||
For example, let's say that you define this `npm start` script:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "project-example",
|
||||
"scripts": {
|
||||
"start": "node app.js"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
How could you specify the port where you want to run your server if you use `npm start`?
|
||||
|
||||
Let's say that we want to pass the port directly as a command-line argument. You would write this:
|
||||
|
||||
```bash
|
||||
npm start -- 8000
|
||||
```
|
||||
|
||||
In your code, you can access these arguments in the `process.argv` array using indices:
|
||||
|
||||
```bash
|
||||
process.argv[0] # The path to the node executable.
|
||||
process.argv[1] # The script file being executed.
|
||||
process.argv[2] # The first argument (8000).
|
||||
```
|
||||
|
||||
Therefore, you could access and use the port number wherever you need to with `process.argv[2]`. That is the power of command-line arguments combined with npm scripts.
|
||||
|
||||
Like you can see, npm scripts are essential tools for simplifying the development workflow. They help you to automate and transform complex and reusable command sequences into simple and consistent shortcuts that you can use in your daily work.
|
||||
|
||||
# --questions--
|
||||
|
||||
## --text--
|
||||
|
||||
Where are npm scripts defined in a Node.js project?
|
||||
|
||||
## --answers--
|
||||
|
||||
In a `.npmignore` file.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the file that acts as the central manifest for a Node.js project and its executable commands.
|
||||
|
||||
---
|
||||
|
||||
Within the `"dependencies"` object of `package.json`.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the file that acts as the central manifest for a Node.js project and its executable commands.
|
||||
|
||||
---
|
||||
|
||||
Within the `"scripts"` object of `package.json`.
|
||||
|
||||
---
|
||||
|
||||
In a separate `npm-config.json` file.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the file that acts as the central manifest for a Node.js project and its executable commands.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
|
||||
## --text--
|
||||
|
||||
How do you execute an npm script named `build`?
|
||||
|
||||
## --answers--
|
||||
|
||||
`build npm`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the command prefix that tells npm you want to execute one of the custom commands defined in the `"scripts"` section.
|
||||
|
||||
---
|
||||
|
||||
`npm run build`
|
||||
|
||||
---
|
||||
|
||||
`node build`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the command prefix that tells npm you want to execute one of the custom commands defined in the `"scripts"` section.
|
||||
|
||||
---
|
||||
|
||||
`run build`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the command prefix that tells npm you want to execute one of the custom commands defined in the `"scripts"` section.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
2
|
||||
|
||||
## --text--
|
||||
|
||||
What is the purpose of the double hyphen (`--`) when running an npm script like `npm run start -- 5`?
|
||||
|
||||
## --answers--
|
||||
|
||||
It signals that the script should be run in silent mode.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how a complex command utility (like Jest or Webpack) receives its specific flags when run through an npm shortcut.
|
||||
|
||||
---
|
||||
|
||||
It tells npm to pass the remaining arguments to the underlying script command.
|
||||
|
||||
---
|
||||
|
||||
It means the script must be executed with elevated administrative privileges.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how a complex command utility (like Jest or Webpack) receives its specific flags when run through an npm shortcut.
|
||||
|
||||
---
|
||||
|
||||
It indicates that the script should be run in parallel with other defined scripts.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how a complex command utility (like Jest or Webpack) receives its specific flags when run through an npm shortcut.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
2
|
||||
@@ -0,0 +1,326 @@
|
||||
---
|
||||
id: 692aba0978ca391f10455b4a
|
||||
title: How Can You Publish a Package to the npm Registry?
|
||||
challengeType: 19
|
||||
dashedName: how-can-you-publish-a-package-to-the-npm-registry
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Let's learn about the npm registry, where you can share your JavaScript packages with the world.
|
||||
|
||||
The **npm registry** is a database of public and private packages.
|
||||
|
||||
Developers and organizations can publish packages to this registry to share their tools with their communities and team members, and in many cases, with all other Node.js developers.
|
||||
|
||||
Packages can be either public or private. Public packages can be accessed by anyone. Private packages can only be accessed by specific users or members of an organization.
|
||||
|
||||
In the npm registry, you can share what you've built with the world with just a few clicks. Sounds great, right?
|
||||
|
||||
Let's see how you can publish a package step by step.
|
||||
|
||||
## Step 1: Create an Account
|
||||
|
||||
The first step is to create a free npm account. To create your account:
|
||||
|
||||
* Go to [https://www.npmjs.com/signup](https://www.npmjs.com/signup).
|
||||
|
||||
* Fill in the form. You will need to enter your username, email, and password.
|
||||
|
||||
|
||||
Please note that, according to the sign-up page, "your email address will be added to the metadata of packages that you publish, so it may be seen publicly."
|
||||
|
||||
## Step 2: **Log in**
|
||||
|
||||
Once you have an npm account, you will need to log in on your terminal by running this command:
|
||||
|
||||
```bash
|
||||
npm login
|
||||
```
|
||||
|
||||
Then you'll need to authenticate with your account information.
|
||||
|
||||
## **Step 3: Create a** `package.json` file
|
||||
|
||||
Before you publish your package, you will need to create a `package.json` file with this command:
|
||||
|
||||
```bash
|
||||
npm init
|
||||
```
|
||||
|
||||
(If your project already has one, you can go directly to **step 4**).
|
||||
|
||||
You will need to enter this information for your `package.json` file:
|
||||
|
||||
* **name**: This is usually the name of your project/directory. If you are planning to make your package public, this name must be unique, unless you use scopes (we'll cover this in just a moment).
|
||||
|
||||
* **version**: You should start with `"1.0.0"`, the default value. This represents the initial version of your package and you can update it as you make changes to the package.
|
||||
|
||||
* **main**: The entry point of your project. This is `index.js` by default.
|
||||
|
||||
* **author**: You can write your name or preferred handle.
|
||||
|
||||
* **license**: Choose a specific license. Some examples include MIT and ISC.
|
||||
|
||||
* **description**: A brief summary of your package.
|
||||
|
||||
|
||||
When choosing the name of your package, make sure it's not already taken in the npm registry. To do this, you can go to the following URL, replacing `<your-package-name>` with the name of your package:
|
||||
|
||||
```bash
|
||||
https://www.npmjs.com/package/<your-package-name>
|
||||
```
|
||||
|
||||
If there isn't a package at that URL, the package name is available and you can use it.
|
||||
|
||||
However, if the name is already taken and you really want to keep it, you can use what is known as a **scope** to publish it.
|
||||
|
||||
### **Scopes**
|
||||
|
||||
When you create a user or organization account in the npm registry, you are granted a scope with your username or the name of your organization.
|
||||
|
||||
Scopes are helpful to avoid name conflicts because you can publish your package under your scope, even if another package with the same name already exists.
|
||||
|
||||
The name of a scoped package starts with the scope name. For example, in `package.json`, you would find this key-value pair:
|
||||
|
||||
```bash
|
||||
"name": "@<scope-name>/<your-package-name>"
|
||||
```
|
||||
|
||||
You can make this change directly in the file if you need to, or you can create the `package.json` file with the scope from the start by adding `--scope=@<scope-name>` to the `npm init` command.
|
||||
|
||||
```bash
|
||||
npm init --scope=@<scope-name>
|
||||
```
|
||||
|
||||
The scope name can be your username if you are using a personal account, or the name of your organization if you are using an organizational account.
|
||||
|
||||
## Step 4: Create README.md
|
||||
|
||||
The README of your package is a markdown file where you describe what your package does and its intended usage.
|
||||
|
||||
Some examples of important content that you may want to include are:
|
||||
|
||||
* Its purpose.
|
||||
|
||||
* How to install it.
|
||||
|
||||
* Important dependencies and considerations.
|
||||
|
||||
* How to get started.
|
||||
|
||||
* Sample code snippets.
|
||||
|
||||
* Contribution guidelines (if you accept contributions).
|
||||
|
||||
* Link to a changelog file where you track the changes that have been made in different versions.
|
||||
|
||||
|
||||
The structure of the README is flexible, though. You can adapt it to fit your needs.
|
||||
|
||||
## **Step 5:** `.npmignore`
|
||||
|
||||
The `.npmignore` file tells the npm registry what files to include and what files to ignore when publishing your package. It's very important to prevent sharing sensitive information such as private keys, passwords, and personal information.
|
||||
|
||||
In this file, you can write patterns to specify what files, directories, and types of files are ignored. It follows the same pattern-matching rules as the `.gitignore` files.
|
||||
|
||||
If you have worked with Git, you may think that this file sounds very similar to `.gitignore`, right? Well, that's because it is. According to the npm documentation, "If there's no `.npmignore` file, but there is a `.gitignore` file, then npm will ignore the stuff matched by the `.gitignore` file."
|
||||
|
||||
You should also know that npm looks for `.npmignore` and `.gitignore` files in all subdirectories of your package, not just the root directory.
|
||||
|
||||
By default, these paths are automatically ignored, so you don't need to add them to `.npmignore`:
|
||||
|
||||
* `.*.swp`
|
||||
|
||||
* `._*`
|
||||
|
||||
* `.DS_Store`
|
||||
|
||||
* `.git`
|
||||
|
||||
* `.gitignore`
|
||||
|
||||
* `.hg`
|
||||
|
||||
* `.npmignore`
|
||||
|
||||
* `.npmrc`
|
||||
|
||||
* `.lock-wscript`
|
||||
|
||||
* `.svn`
|
||||
|
||||
* `.wafpickle-*`
|
||||
|
||||
* `config.gypi`
|
||||
|
||||
* `CVS`
|
||||
|
||||
* `npm-debug.log`
|
||||
|
||||
|
||||
The `node_modules` directory is also ignored, except bundled dependencies.
|
||||
|
||||
## **Step 6: Publish your package**
|
||||
|
||||
Before publishing your package to the npm registry, you should test it by running this command:
|
||||
|
||||
```bash
|
||||
npm install <full-path-to-package-directory>
|
||||
```
|
||||
|
||||
Once you are ready to publish it, the command will depend on the type of package: scope vs. unscoped.
|
||||
|
||||
If your package is unscoped, run this command:
|
||||
|
||||
```bash
|
||||
npm publish
|
||||
```
|
||||
|
||||
If your package is scoped, it will be published as a private package by default (if this feature is available in your account). If you want to make it public, you will need to add `--access public` to the command.
|
||||
|
||||
```bash
|
||||
npm publish --access public
|
||||
```
|
||||
|
||||
To see your public package, go to this URL:
|
||||
|
||||
```bash
|
||||
https://npmjs.com/package/<your-package-name>
|
||||
```
|
||||
|
||||
You should see an indication of the visibility of your package (public or private) below the package name.
|
||||
|
||||
## **Step 7 (Optional): Install Your Package**
|
||||
|
||||
Now that you are all set up, you can install your package in a Node.js project with this command:
|
||||
|
||||
```bash
|
||||
npm install <your-package-name>
|
||||
```
|
||||
|
||||
## Updating Your Package
|
||||
|
||||
If you need to make changes to your package after publishing it, you can update the package version in `package.json`.
|
||||
|
||||
This is the standard convention for semantic versioning:
|
||||
|
||||
* **First release:** `1.0.0`.
|
||||
|
||||
* **Patch release:** Increment the third digit. For example, updating from `1.0.0` to `1.0.1`.
|
||||
|
||||
* **Minor release:** Increment the middle digit and reset the last digit to zero. For example, updating `1.0.0` to `1.1.0`.
|
||||
|
||||
* **Major release:** Increment the first digit and reset the middle and last digits to zero. For example, updating `1.1.0` to `2.0.0`.
|
||||
|
||||
Great work. Now you know how to publish your package to the npm registry and how to update it to fix bugs and add new features.
|
||||
|
||||
# --questions--
|
||||
|
||||
## --text--
|
||||
|
||||
What is the command used in the terminal to upload a package from your local machine to the npm registry?
|
||||
|
||||
## --answers--
|
||||
|
||||
`npm install <package-name>`
|
||||
|
||||
### --feedback--
|
||||
|
||||
This is the command that finalizes the process, making your package available for others to install.
|
||||
|
||||
---
|
||||
|
||||
`npm start`
|
||||
|
||||
### --feedback--
|
||||
|
||||
This is the command that finalizes the process, making your package available for others to install.
|
||||
|
||||
---
|
||||
|
||||
`npm add`
|
||||
|
||||
### --feedback--
|
||||
|
||||
This is the command that finalizes the process, making your package available for others to install.
|
||||
|
||||
---
|
||||
|
||||
`npm publish`
|
||||
|
||||
## --video-solution--
|
||||
|
||||
4
|
||||
|
||||
## --text--
|
||||
|
||||
What file must be present in a directory to signal to the npm registry that the folder is a complete, installable package?
|
||||
|
||||
## --answers--
|
||||
|
||||
`README.md`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the file that contains all the required metadata, dependencies, and configuration for an npm project.
|
||||
|
||||
---
|
||||
|
||||
`index.js`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the file that contains all the required metadata, dependencies, and configuration for an npm project.
|
||||
|
||||
---
|
||||
|
||||
`package.json`
|
||||
|
||||
---
|
||||
|
||||
`.npmignore`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the file that contains all the required metadata, dependencies, and configuration for an npm project.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
|
||||
## --text--
|
||||
|
||||
Which action should you take to ensure that sensitive information is **not** included when a package is published?
|
||||
|
||||
## --answers--
|
||||
|
||||
Temporarily deleting the files from the project folder before running `npm publish`.
|
||||
|
||||
### --feedback--
|
||||
|
||||
npm uses a specific file to decide what to exclude from the published package.
|
||||
|
||||
---
|
||||
|
||||
Using the `.ignore` file to list the sensitive files.
|
||||
|
||||
### --feedback--
|
||||
|
||||
npm uses a specific file to decide what to exclude from the published package.
|
||||
|
||||
---
|
||||
|
||||
Using the `.npmignore` file to list the sensitive files.
|
||||
|
||||
---
|
||||
|
||||
Setting the `private` field to `true` in `package.json`.
|
||||
|
||||
### --feedback--
|
||||
|
||||
npm uses a specific file to decide what to exclude from the published package.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
@@ -0,0 +1,255 @@
|
||||
---
|
||||
id: 692aba0a78ca391f10455b4b
|
||||
title: How Do Imports and Exports Work with CommonJS Modules?
|
||||
challengeType: 19
|
||||
dashedName: how-do-imports-and-exports-work-with-commonjs-modules
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
In modern web development, you can split your code into multiple files called "modules."
|
||||
|
||||
You can think of a module as a self-contained and reusable code block.
|
||||
|
||||
By importing modules into other modules, you can reuse their functionality while still keeping the code in separate files, which is more maintainable, especially for large and complex web applications.
|
||||
|
||||
In Node.js, each file is considered a module.
|
||||
|
||||
Node has two different systems for working with modules: CommonJS and ES.
|
||||
|
||||
CommonJS is the original and default way of working with packages in Node.js. It loads modules synchronously, which means that it has to wait for a module to be fully loaded before it starts loading the next one or continues running the code.
|
||||
|
||||
It's still widely used, but it's gradually being replaced by the newer ES syntax.
|
||||
|
||||
CommonJS uses the `require()` function to import a module, taking its relative path as an argument.
|
||||
|
||||
For example, let's say that we have a module called `math.js`, where we define basic mathematical operations.
|
||||
|
||||
We'll only use a multiplication function here to keep this example simple and focused:
|
||||
|
||||
```js
|
||||
function multiply(a, b) {
|
||||
return a * b;
|
||||
}
|
||||
```
|
||||
|
||||
How can we reuse this function outside our current module? By default, functions and variables defined in a Node.js module are **private** — other modules can't access them unless we explicitly export them. There are several ways to do this.
|
||||
|
||||
One common way is to assign a value to `module.exports`. This object represents what the module will return when it is imported elsewhere, giving other modules access to the functions, variables, or objects you've chosen to expose.
|
||||
|
||||
In this example, we assign an object with a `multiply` property to `module.exports`. The value of that property is a reference to the `multiply` function we defined earlier. This will export the function, so we can call it from other modules if we need to.
|
||||
|
||||
```javascript
|
||||
function multiply(a, b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
multiply: multiply
|
||||
};
|
||||
```
|
||||
|
||||
Let's say that we try to import the `math.js` module into another module. We call the `require()` function, and pass the relative path as an argument. Then, we assign the object returned by `require()` to the `math` variable.
|
||||
|
||||
```javascript
|
||||
const math = require('./math');
|
||||
```
|
||||
|
||||
Let's check out the value of `math` in the console by printing it with `console.log()`:
|
||||
|
||||
```javascript
|
||||
console.log(math);
|
||||
```
|
||||
|
||||
This is the output. It's an object with a `multiply` property and a function as the value:
|
||||
|
||||
```javascript
|
||||
{ multiply: [Function: multiply] }
|
||||
```
|
||||
|
||||
If we call this function with `math.multiply()`, passing the numbers `6` and `7` as arguments, the output is `42`. The function runs successfully and yet, it's in another file! So our import statement worked correctly.
|
||||
|
||||
```javascript
|
||||
const math = require('./math');
|
||||
|
||||
console.log(math.multiply(6, 7)); // 42
|
||||
```
|
||||
|
||||
But there are other ways to export a function, variable, or object.
|
||||
|
||||
For example, if you only need to export a single function, variable, or object, you can assign it directly as the value of `module.exports`:
|
||||
|
||||
```javascript
|
||||
function multiply(a, b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
module.exports = multiply;
|
||||
```
|
||||
|
||||
If you need to export multiple functions, you just need to add them to the `module.exports` object, separated by a comma.
|
||||
|
||||
Here, you can see that the exported object has two properties: `subtract` and `multiply`. Their values are references to their corresponding functions, so you will have access to both of them in any module that imports `math.js`:
|
||||
|
||||
```javascript
|
||||
function subtract(a, b) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
function multiply(a, b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
subtract: subtract,
|
||||
multiply: multiply
|
||||
};
|
||||
```
|
||||
|
||||
When the `module.exports` object has multiple properties, you will have the option to choose if you want to import everything or import properties individually.
|
||||
|
||||
In this example, we are importing the entire object that was exported by `math.js`, so we will have access to both `subtract` and `multiply`:
|
||||
|
||||
```javascript
|
||||
const math = require('./math');
|
||||
|
||||
console.log(math.subtract(6, 7)); // -1
|
||||
console.log(math.multiply(6, 7)); // 42
|
||||
```
|
||||
|
||||
If we only want to import `multiply` instead, we just need to write its name within curly braces, after the `const` keyword. Basically, you're using the destructuring assignment syntax to get its value from the exported object. Then, we can refer to it directly by its name in our code:
|
||||
|
||||
```javascript
|
||||
const { multiply } = require('./math');
|
||||
|
||||
console.log(multiply(6, 7));
|
||||
```
|
||||
|
||||
This works for multiple elements too. You just need to separate them with a comma within the curly braces. Here, we are importing both the `subtract` and `multiply` functions:
|
||||
|
||||
```javascript
|
||||
const { subtract, multiply } = require('./math');
|
||||
```
|
||||
|
||||
By default, Node.js will treat the following as CommonJS modules:
|
||||
|
||||
* Files with a `.cjs` extension.
|
||||
|
||||
* Files with a `.js` extension when the nearest parent `package.json` file contains a top-level field `"type"` with a value of `"commonjs"`.
|
||||
|
||||
* Files with a `.js` extension or without an extension, when the nearest parent `package.json` file doesn't contain a top-level field `"type"`, or there is no `package.json` in any parent folder.
|
||||
|
||||
* Files with an extension that is not `.mjs`, `.cjs`, `.json`, `.node`, or `.js`.
|
||||
|
||||
|
||||
While ES Modules are gradually replacing CommonJS modules, understanding them is still essential for developers working with existing Node.js codebases and many npm packages.
|
||||
|
||||
# --questions--
|
||||
|
||||
## --text--
|
||||
|
||||
Which function is used to import modules in CommonJS?
|
||||
|
||||
## --answers--
|
||||
|
||||
`import()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which keyword is used to bring in external code in Node.js environments.
|
||||
|
||||
---
|
||||
|
||||
`require()`
|
||||
|
||||
---
|
||||
|
||||
`export()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which keyword is used to bring in external code in Node.js environments.
|
||||
|
||||
---
|
||||
|
||||
`include()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which keyword is used to bring in external code in Node.js environments.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
2
|
||||
|
||||
## --text--
|
||||
|
||||
Which of the following is the primary way to export a module in CommonJS?
|
||||
|
||||
## --answers--
|
||||
|
||||
`export default`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which object is used to define what a module makes available to other files.
|
||||
|
||||
---
|
||||
|
||||
`module.exports`
|
||||
|
||||
---
|
||||
|
||||
`export const`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which object is used to define what a module makes available to other files.
|
||||
|
||||
---
|
||||
|
||||
`import from`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which object is used to define what a module makes available to other files.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
2
|
||||
|
||||
## --text--
|
||||
|
||||
What type of loading does CommonJS use?
|
||||
|
||||
## --answers--
|
||||
|
||||
Asynchronous loading
|
||||
|
||||
### --feedback--
|
||||
|
||||
Does the code wait for a module to fully load before resuming its execution?
|
||||
|
||||
---
|
||||
|
||||
Lazy loading
|
||||
|
||||
### --feedback--
|
||||
|
||||
Does the code wait for a module to fully load before resuming its execution?
|
||||
|
||||
---
|
||||
|
||||
Synchronous loading
|
||||
|
||||
---
|
||||
|
||||
Conditional loading
|
||||
|
||||
### --feedback--
|
||||
|
||||
Does the code wait for a module to fully load before resuming its execution?
|
||||
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
@@ -0,0 +1,179 @@
|
||||
---
|
||||
id: 692aba0a78ca391f10455b4c
|
||||
title: How Do Imports and Exports Work with ES Modules?
|
||||
challengeType: 19
|
||||
dashedName: how-do-imports-and-exports-work-with-es-modules
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now that you understand the CommonJS module system, let's look at the ES module system.
|
||||
|
||||
ES modules, or ECMAScript modules, are the official, standardized module format for JavaScript defined by the ECMAScript specification. They use `import` and `export` statements, and in Node.js, they're loaded asynchronously, which is more efficient.
|
||||
|
||||
Node.js treats files as ES modules in the following cases:
|
||||
|
||||
* Files with an `.mjs` extension.
|
||||
|
||||
* And files with a `.js` extension when the nearest parent `package.json` file contains a top-level `"type"` field with a value of `"module"`.
|
||||
|
||||
|
||||
Here we have the same `multiply` function you've seen before, but now we are going to use the ESM system. For this, we are assigning a `.mjs` extension to both modules.
|
||||
|
||||
To export the `multiply` function from the `math.mjs` module, use the `export` keyword followed by the name of the function, variable, or object that you want to export within curly brackets:
|
||||
|
||||
```javascript
|
||||
function multiply(a, b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
export { multiply };
|
||||
```
|
||||
|
||||
You can also export the function directly by using the `export` keyword before the `function` keyword. This is known as a named export. You can have multiple named exports per module:
|
||||
|
||||
```javascript
|
||||
export function multiply(a, b) {
|
||||
return a * b;
|
||||
}
|
||||
```
|
||||
|
||||
Then, to import this module, use the `import` keyword followed by curly braces. Notice that we are using `import` instead of `require()`. That is one of the key differences between CommonJS and ES modules.
|
||||
|
||||
Within the curly braces, we write the name of the function, variable, or object that we want to import. In this case, it's `multiply`. Then, use the `from` keyword and the relative path to the module. This code will run successfully and the output will be `42`.
|
||||
|
||||
```javascript
|
||||
import { multiply } from './math.mjs';
|
||||
|
||||
console.log(multiply(6, 7)); // 42
|
||||
```
|
||||
|
||||
In the ES system, you can set one default export per module. This way, you don't need to use curly braces to import it.
|
||||
|
||||
Here is an example where we are setting the `multiply` function as the default export for the entire `math.mjs` module:
|
||||
|
||||
```javascript
|
||||
export default function multiply(a, b) {
|
||||
return a * b;
|
||||
}
|
||||
```
|
||||
|
||||
Now we don't need the curly braces, since the function will be imported and assigned by default:
|
||||
|
||||
```javascript
|
||||
import multiply from './math.mjs';
|
||||
```
|
||||
|
||||
If you don't use file extensions or the `package.json` file to tell Node.js explicitly what type of module system you want to use, it will inspect the source code to look for ES module syntax. If that syntax is found, it will run the code as an ES module; otherwise, it will run it as a CommonJS module.
|
||||
|
||||
While CommonJS served as the default standard for Node.js in its early days, as developers increasingly adopt ESM for its efficiency and compatibility with modern JavaScript, it's important to know their differences and how to use both.
|
||||
|
||||
# --questions--
|
||||
|
||||
## --text--
|
||||
|
||||
Which keyword is used to load modules in ES Modules?
|
||||
|
||||
## --answers--
|
||||
|
||||
`require()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which keyword is used to bring in external code in modern JavaScript environments.
|
||||
|
||||
---
|
||||
|
||||
`module.exports`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which keyword is used to bring in external code in modern JavaScript environments.
|
||||
|
||||
---
|
||||
|
||||
`import`
|
||||
|
||||
---
|
||||
|
||||
`include()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which keyword is used to bring in external code in modern JavaScript environments.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
|
||||
## --text--
|
||||
|
||||
Which of the following is a way to export a single value as the primary export in ES?
|
||||
|
||||
## --answers--
|
||||
|
||||
`module.exports`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which export method is used to provide a single, primary value from a module.
|
||||
|
||||
---
|
||||
|
||||
`exports.add`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which export method is used to provide a single, primary value from a module.
|
||||
|
||||
---
|
||||
|
||||
`export default`
|
||||
|
||||
---
|
||||
|
||||
`export const`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which export method is used to provide a single, primary value from a module.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
|
||||
## --text--
|
||||
|
||||
What type of loading does ECMAScript Modules (ES) primarily use?
|
||||
|
||||
## --answers--
|
||||
|
||||
Synchronous loading
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how modern browsers import external JavaScript files.
|
||||
|
||||
---
|
||||
|
||||
Lazy loading
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how modern browsers import external JavaScript files.
|
||||
|
||||
---
|
||||
|
||||
Asynchronous loading
|
||||
|
||||
---
|
||||
|
||||
Conditional loading
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how modern browsers import external JavaScript files.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "Working with npm Scripts",
|
||||
"isUpcomingChange": true,
|
||||
"dashedName": "lecture-working-with-npm-scripts",
|
||||
"helpCategory": "Backend Development",
|
||||
"blockLayout": "challenge-list",
|
||||
"challengeOrder": [
|
||||
{ "id": "692ab9f91d74951aeba05c00", "title": "What Are npm Scripts?" },
|
||||
{
|
||||
"id": "692aba0978ca391f10455b4a",
|
||||
"title": "How Can You Publish a Package to the npm Registry?"
|
||||
},
|
||||
{
|
||||
"id": "692aba0a78ca391f10455b4b",
|
||||
"title": "How Do Imports and Exports Work with CommonJS Modules?"
|
||||
},
|
||||
{
|
||||
"id": "692aba0a78ca391f10455b4c",
|
||||
"title": "How Do Imports and Exports Work with ES Modules?"
|
||||
}
|
||||
],
|
||||
"blockLabel": "lecture"
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
{
|
||||
"dashedName": "node-package-manager",
|
||||
"comingSoon": true,
|
||||
"blocks": []
|
||||
"blocks": ["lecture-working-with-npm-scripts"]
|
||||
},
|
||||
{
|
||||
"dashedName": "http-and-the-web-standards-model",
|
||||
|
||||
Reference in New Issue
Block a user