Color Mode

Setting Up Your First Node.js Project

Introduction

This assignment will guide you through setting up your first Node.js project using pnpm. You will learn about the structure and purpose of the package.json file. Additionally, you will add essential packages like express for building web applications and nodemon for efficient development. Finally, you will create a simple web server. Each step is designed to help you understand Node.js fundamentals while encouraging hands-on learning and experimentation.

Assignment Instructions

1. Initialize a New Project

In the last assignment, you created a directory for your project when setting up your GitHub repository. Navigate to this folder in your terminal and run the following command:


        pnpm init
    

This will automatically create a new package.json file in your project directory with default values. This file is essential for managing your project's dependencies and metadata. For a project that is not intended to be deployed as a public package, which is the case for this class, you can simplify the package.json file by including only the essential fields required for your development and build processes. These essential fields typically include:

Since we will be using ECMAScript Modules (ESM) instead of CommonJS, you need to add the "type": "module" field to your package.json file. This will enable support for ESM in your project. If you are unfamiliar with the differences between CommonJS and ESM you should take a moment to review Understanding Import and Modules in JavaScript. At this point your package.json file should contain at least the following fields:


        {
            "name": "cse340-practice-[lastname]",
            "dependencies": {},
            "devDependencies": {},
            "type": "module",
            "scripts": {
                "start": "node server.js"
            }
        }
    
Since this project does not need to be published to the npm registry, you can safely replace the contents of the package.json file with the JSON structure shown above.

If you have previous Node.js experience, you might be wondering why we omitted the main field. The main field specifies the entry point for a module, which is the file that will be loaded when someone imports or requires your package into their own project. For example, if you publish a module to npm or use it locally, when someone installs the package and uses require('your-package') or import 'your-package', Node.js will look for the file specified in the main field. Since we are not publishing a package, we don't need to specify an entry point.

2. Add Express

Express is a popular web framework for Node.js that simplifies building web applications and APIs. To add it to your project, run:


        pnpm add express
    

This will download and add version 5.1.0 (or the latest compatible version within the 5.x range) of Express to your project. You will see Express listed as a dependency in your package.json file.

3. Add Nodemon

Nodemon is a development tool that automatically restarts your Node.js application whenever you make changes to the code. This saves you from having to manually stop and restart the server. To add Nodemon as a development dependency, run:


        pnpm add -D nodemon
    

The -D flag specifies that Nodemon is a development dependency, which means it won't be included in production builds.

4. Configure Nodemon

Create a file called nodemon.json in the root directory of your project repository with the following configuration:


        {
            "ext": "js css ejs env",
            "exec": "node --env-file=.env server.js",
            "ignore": [
                ".git",
                "node_modules"
            ]
        }
    

This configuration tells Nodemon:

5. Create a Simple Server

Create a new file named server.js in your projects root directory and copy the following code into it:


        // Import express using ESM syntax
        import express from 'express';

        // Create an instance of an Express application
        const app = express();

        // Define a route handler for the root URL ('/')
        app.get('/', (req, res) => {
            res.send('Hello, World!');
        });

        // Define the port number the server will listen on
        const PORT = 3000;

        // Start the server and listen on the specified port
        app.listen(PORT, () => {
            console.log(`Server is running on http://127.0.0.1:${PORT}`);
        });
    

Start your server by running:


        node server.js
    

Open your browser and navigate to http://127.0.0.1:3000 to view the "Hello, World!" message from your server. When you are finished testing, you can stop the server by pressing Ctrl + C (Windows/Linux) or Command + C (Mac) in your terminal.

6. Add Environment Variables

Environment variables allow you to store configuration settings securely. Create a file named .env in the root directory of your project and add the following line, replacing Your Name with your actual name:


        NAME="Your Name"
    

Update your server.js file to use the environment variable. You can access environment variables in Node.js using the process.env object. Modify the server.js file to include the following changes:


        import express from 'express';

        const app = express();

        const name = process.env.NAME; // <-- NEW

        app.get('/', (req, res) => {
            res.send(`Hello, ${name}!`); // <-- UPDATED
        });

        const PORT = 3000;
        app.listen(PORT, () => {
            console.log(`Server is running on http://127.0.0.1:${PORT}`);
        });
    

Start your server by running the following modified command from earlier, which loads environment variables from the .env file:


        node --env-file=.env server.js
    

Visit http://127.0.0.1:3000 in your browser and you should see a new message being displayed with your name.

In the past, we used the dotenv package to handle environment variables. However, with the newer --env-file command line flag available in Node.js, we can automatically load environment variables without needing an additional package. This simplifies our setup and reduces dependencies. The process object in Node.js is a global object that provides information about the current Node.js process. It allows us to access environment variables using the process.env property.

Do not do this in Production

Environment variables are typically used to store sensitive information like API keys, database credentials, and other configuration settings. It is important to keep them secure and not expose them in your code or responses. For this assignment, we are using environment variables to demonstrate the concept, but in a real-world scenario, you should never expose sensitive information in this way.

Understanding Development Best Practices

Node.js version 20.6.0 introduced a built-in --env-file flag for loading environment variables. In this course, you will use this native functionality instead of the dotenv package. Submissions using dotenv will be flagged for inappropriate AI assistance.

This teaches an important development principle: be intentional about dependencies. Every package you add increases your application's attack surface and maintenance complexity, so you should have a good reason for including it. When functionality is available natively or is simple enough to write yourself, adding a package is unnecessary.

AI coding assistants are helpful tools, but they often suggest packages or older patterns because those appear frequently in their training data. If you blindly trust AI suggestions, you will end up with code patterns that are easy to recognize as AI-generated. Part of becoming a skilled developer is evaluating suggestions and choosing the best solution for your situation, whether that means using native features, writing a few lines of code yourself, or adding a well-chosen package that solves a real problem.

Make sure you understand every line of code you write. Throughout the semester, you will need to explain your code, advocate for your decisions, and justify your grade. By the end of the term, you should be able to confidently defend every choice you made in your projects.

7. Use Nodemon

Normally, you would have to stop and restart the server every time you make changes to your code for them to take effect. Nodemon automates this process for us. Modify the scripts section of your package.json file to include a dev field. Additionally, modify or add the start field to use the --env-file flag:


        {
            # Other fields...
            "scripts": {
                "dev": "nodemon --env-file=.env server.js",
                "start": "node server.js"
            }
        }
    

Now if you run your server using the following command, Nodemon will automatically restart the server whenever you make changes to your code:


        pnpm run dev
    

We have added two scripts to the scripts section of your package.json file:

You no longer need to start the server with node server.js directly. Instead, you can use the start command for production or the dev command for development.


        // Start the server in production; this will not work locally
        pnpm run start

        // Start the server in development
        pnpm run dev
    

Visit http://127.0.0.1:3000 in your browser. Now change the value of the NAME variable in your .env file. Next, make a change in the server.js file. You can change "Hello, ${name}!" to "Welcome ${name}!". Now go back to the browser and refresh the page. You should see the updated message in your browser without having to restart the server manually.

Experiment and Have Fun

We have covered the basics of setting up a Node.js project, adding packages, creating a simple web server, and using environment variables. Now it's time to experiment and have fun with your project. Try adding new routes or other features to your server. For example, you can add a new route to your server by modifying your server.js file:


app.get('/new-route', (req, res) => {
    res.send('This is a new route!');
});
    

Save the file and visit http://127.0.0.1:3000/new-route to see your new route in action. Moving forward every new concept you learn can be added to this practice project to build a more complex and feature-rich web application.

Conclusion

What you learned in this assignment is the foundation for building web applications with Node.js and Express. In the next assignment we will dive deeper into routing and middleware in Express, the core concepts you practiced today without truly realizing it.