codex-lv4-may-2025

Level Navigation: 1 2 3 (4ℹ️) (5ℹ️) 6 7 8 9 10 11 12 13 14⚡ 15⚡ (16ℹ️) 17 18 19 20 21 22 23 24 25 26⚡ 27⚡ 28⚡ 29 30 31 32 33 34 35 36 37 38 39⚡ 40⚡

Level 31: Refactor — Export App and Separate Server Startup

Goal

Refactor your Express server to separate app configuration from server startup. This is a common practice that makes your code more testable, reusable, and better organized.

Why Separate App from Server?

In your current setup, everything is in one file (src/index.js): the app creation, routes, and the app.listen() call. As your project grows, you’ll want to:

  1. Test your app without starting a server: Testing tools like Supertest need access to your Express app, but they don’t need the server to be listening on a port.
  2. Reuse your app: You might want to use the same app configuration in different contexts (testing, development, production).
  3. Better organization: Separating concerns makes your code easier to understand and maintain.

What You’ll Do

  1. Create src/app.js: Move your Express app creation and configuration here, then export it.
  2. Update src/index.js: Import the app and handle server startup (the listen() call).

Step-by-Step Refactor

Step 1: Create src/app.js and Export the App

Create a new file src/app.js and move your Express app setup there:

Show Me: exporting the app from app.js

// src/app.js
import express from 'express';

const app = express();

// Middleware
app.use(express.json());
app.use(express.static('public'));

// Routes
app.get('/', (req, res) => {
  res.send('<h1>Hello Express!</h1><p>Your server is working!</p>');
});

app.get('/happy-birthday', (req, res) => {
  res.json({
    name: 'Alice',
    age: 25,
    greeting: 'Happy Birthday! 🎉'
  });
});

// ... all your other routes ...

// Export the app so it can be imported elsewhere
export default app;

Key changes:

Step 2: Update src/index.js to Import and Start the Server

Update src/index.js to import the app and handle server startup:

Show Me: importing app and starting server in index.js

// src/index.js
import app from './app.js';

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`);
});

Key changes:

Your New Project Structure

After refactoring, your project structure should look like this:

your-project/
├── src/
│   ├── app.js      ← App configuration (middleware, routes)
│   └── index.js    ← Server startup (listen call)
├── public/
│   └── ...
└── package.json

Testing the Refactor

  1. Start your server:
    npm run dev
    
    • The server should start exactly as before
    • All your routes should work the same way
  2. Verify nothing broke:
    • Test your routes in Postman or your browser
    • Make sure all endpoints still respond correctly

Digging Deeper: ES6 Module Exports

Exporting with export default:

Why this pattern is common:

What’s Next?

In the next level, you’ll set up testing. Having the app exported makes it easy to import in your test files without needing to start a server. This refactor sets you up for success with automated testing!

Note: If you’re using TypeScript, the same pattern applies—just use .ts extensions and TypeScript syntax.