Build a Node.js Interactive Web-Based Simple Code Review Tool

In the fast-paced world of software development, code reviews are a critical part of the process. They help catch bugs, improve code quality, and ensure that everyone on the team is on the same page. But often, code reviews involve a lot of back-and-forth, with developers manually copying and pasting code snippets, making it a tedious and time-consuming process. What if there was a better way? Imagine a web-based tool where you could seamlessly review code, add comments, and track changes, all in one place. This tutorial will guide you through building precisely that: a simple, interactive code review tool using Node.js. This project is perfect for beginners and intermediate developers looking to expand their skills and understand how to build practical, collaborative tools.

Why Build a Code Review Tool?

Before diving into the code, let’s explore why building a code review tool is valuable. First and foremost, it streamlines the review process. Instead of relying on emails, instant messages, or separate documents, a dedicated tool centralizes the review workflow. This leads to faster feedback loops and quicker releases. Secondly, it fosters better collaboration. Developers can easily see each other’s changes, understand the context of the code, and engage in meaningful discussions. Finally, it enhances code quality. By providing a platform for detailed feedback, code review tools encourage developers to write cleaner, more maintainable code, reducing the likelihood of bugs and security vulnerabilities.

Project Overview

Our code review tool will have the following features:

  • A user interface for uploading or pasting code.
  • Syntax highlighting to make the code easier to read.
  • A side-by-side comparison view to see changes.
  • The ability to add comments to specific lines of code.
  • A way to track the status of reviews (e.g., open, in progress, resolved).

We’ll use Node.js with Express for the backend, a simple text editor for the code display, and some basic HTML, CSS, and JavaScript for the frontend. We will keep the focus on the core functionality, making it easy to understand and extend.

Setting Up Your Development Environment

Before we begin, you’ll need to set up your development environment. Make sure you have Node.js and npm (Node Package Manager) installed. You can download these from the official Node.js website. Once installed, create a new project directory and navigate into it using your terminal:

mkdir code-review-tool
cd code-review-tool

Next, initialize a new Node.js project:

npm init -y

This command creates a `package.json` file, which manages your project’s dependencies. Now, let’s install the necessary packages:

npm install express highlight.js diff2html
  • `express`: A web application framework for Node.js.
  • `highlight.js`: A library for syntax highlighting.
  • `diff2html`: A library to convert diffs into HTML.

Building the Backend with Node.js and Express

Let’s start by creating the backend. Create a file named `server.js` in your project directory. This file will contain the server-side logic.

Here’s the basic structure of the `server.js` file:

const express = require('express');
const hljs = require('highlight.js');
const Diff2Html = require('diff2html');
const fs = require('fs');
const path = require('path');

const app = express();
const port = 3000;

app.use(express.static('public')); // Serve static files from the 'public' directory
app.use(express.json()); // Middleware to parse JSON request bodies

// API endpoint to process code and diff
app.post('/review', (req, res) => {
  // Implement review logic here
});

app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
});

Let’s break down the code:

  • We import the necessary modules: `express`, `highlight.js`, `diff2html`, `fs`, and `path`.
  • We create an Express app instance.
  • We define the port the server will listen on (3000).
  • `app.use(express.static(‘public’))`: This line serves static files (HTML, CSS, JavaScript) from a directory named ‘public’. We’ll create this directory and add our frontend files later.
  • `app.use(express.json())`: This middleware parses incoming requests with JSON payloads.
  • We define a POST route `/review`. This is where we’ll handle the code review logic.
  • We start the server with `app.listen()`.

Next, let’s add the functionality to handle the code and diff. We will receive the code and the changes to be reviewed. We’ll use `highlight.js` to highlight the code and `diff2html` to generate the HTML for a side-by-side comparison of the changes.

Inside the `/review` route, add the following code:

app.post('/review', (req, res) => {
  const { code, diff } = req.body;

  try {
    // Syntax highlighting
    const highlightedCode = hljs.highlightAuto(code).value;

    // Generate diff HTML
    const diffJson = Diff2Html.parse(diff);
    const diffHtml = Diff2Html.html(diffJson, { drawFileList: true, matching: 'lines' });

    res.json({ highlightedCode, diffHtml });
  } catch (error) {
    console.error('Error processing code:', error);
    res.status(500).json({ error: 'Failed to process code.' });
  }
});

Here’s what this code does:

  • It extracts the `code` and `diff` from the request body.
  • It uses `hljs.highlightAuto()` to highlight the code. This function automatically detects the programming language and applies the appropriate syntax highlighting.
  • It parses the `diff` string using `Diff2Html.parse()`.
  • It generates the HTML for the diff using `Diff2Html.html()`. The `drawFileList: true` option shows a file list, and `matching: ‘lines’` highlights changes line by line.
  • It sends the highlighted code and the diff HTML back to the client as a JSON response.
  • If any error occurs, it logs the error and sends an error response to the client.

Building the Frontend with HTML, CSS, and JavaScript

Now, let’s create the frontend. Create a directory named `public` in your project directory. Inside the `public` directory, create the following files:

  • `index.html`: The main HTML file.
  • `style.css`: The CSS file for styling.
  • `script.js`: The JavaScript file for the frontend logic.

First, let’s create the `index.html` file. This file will contain the basic structure of our web page.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Code Review Tool</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container">
        <h1>Code Review Tool</h1>
        <div class="input-section">
            <textarea id="code" placeholder="Paste your code here"></textarea>
            <textarea id="diff" placeholder="Paste the diff here"></textarea>
            <button id="reviewButton">Review Code</button>
        </div>
        <div class="output-section">
            <h2>Highlighted Code</h2>
            <pre><code id="highlightedCode"></code></pre>
            <h2>Diff View</h2>
            <div id="diffContainer"></div>
        </div>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
    <script src="script.js"></script>
</body>
</html>

This HTML structure includes:

  • A title and meta tags.
  • Links to the Highlight.js stylesheet.
  • A link to `style.css` for custom styles.
  • Two textareas: one for the code and one for the diff.
  • A button to trigger the code review.
  • Sections to display the highlighted code and the diff view.
  • Links to the Highlight.js JavaScript and `script.js`.

Next, let’s add some basic styling to `style.css`:

body {
  font-family: sans-serif;
  margin: 0;
  padding: 0;
  background-color: #f4f4f4;
}

.container {
  max-width: 960px;
  margin: 20px auto;
  padding: 20px;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

h1, h2 {
  text-align: center;
  color: #333;
}

.input-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 20px;
}

textarea {
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-family: monospace;
  resize: vertical;
}

button {
  padding: 10px 15px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s ease;
}

button:hover {
  background-color: #0056b3;
}

.output-section {
  margin-top: 20px;
}

#highlightedCode {
  padding: 10px;
  border-radius: 4px;
  background-color: #f0f0f0;
  overflow: auto;
}

#diffContainer {
  margin-top: 20px;
}

This CSS provides a basic layout and styling for the HTML elements. Finally, let’s add the JavaScript logic to `script.js`:

document.addEventListener('DOMContentLoaded', () => {
  const codeTextarea = document.getElementById('code');
  const diffTextarea = document.getElementById('diff');
  const reviewButton = document.getElementById('reviewButton');
  const highlightedCodeElement = document.getElementById('highlightedCode');
  const diffContainer = document.getElementById('diffContainer');

  reviewButton.addEventListener('click', async () => {
    const code = codeTextarea.value;
    const diff = diffTextarea.value;

    if (!code || !diff) {
      alert('Please enter both code and diff.');
      return;
    }

    try {
      const response = await fetch('/review', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ code, diff }),
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const data = await response.json();
      highlightedCodeElement.innerHTML = data.highlightedCode;
      diffContainer.innerHTML = data.diffHtml;
      hljs.initHighlightingOnLoad(); // Initialize syntax highlighting
    } catch (error) {
      console.error('Error:', error);
      alert('An error occurred while processing the code.');
    }
  });
});

This JavaScript code does the following:

  • It waits for the DOM to be fully loaded.
  • It gets references to the HTML elements.
  • It adds an event listener to the “Review Code” button.
  • When the button is clicked, it retrieves the code and diff from the textareas.
  • It sends a POST request to the `/review` endpoint, sending the code and diff as JSON.
  • It receives the highlighted code and diff HTML from the server.
  • It updates the `highlightedCode` and `diffContainer` elements with the received data.
  • It initializes syntax highlighting using `hljs.initHighlightingOnLoad()`.
  • It handles potential errors.

Running and Testing the Application

Now, let’s run the application. In your terminal, navigate to your project directory and run the following command:

node server.js

This will start the Node.js server. Open your web browser and go to `http://localhost:3000`. You should see the code review tool interface.

To test the tool:

  1. Copy some code into the “Paste your code here” textarea.
  2. Copy a diff (you can generate one using `git diff` or any diff tool) into the “Paste the diff here” textarea.
  3. Click the “Review Code” button.
  4. You should see the highlighted code and the diff view.

Common Mistakes and How to Fix Them

When building this application, you might encounter some common issues. Here are a few and how to resolve them:

  • CORS Errors: If you’re running the frontend and backend on different ports, you might encounter CORS (Cross-Origin Resource Sharing) errors. To fix this, you can install and use the `cors` middleware in your `server.js` file:
const cors = require('cors');
// ...
app.use(cors());
  • Incorrect Paths: Make sure the paths to your static files (CSS, JavaScript) in `index.html` are correct. Also, ensure that the `public` directory is in the correct location relative to your `server.js` file.
  • Syntax Highlighting Not Working: Ensure that you’ve included the Highlight.js stylesheet in your `index.html` and that `hljs.initHighlightingOnLoad()` is called in `script.js` after the content is updated.
  • Diff Not Displaying Correctly: Verify that the diff format is correct and that the `diff2html` library is correctly parsing it. You can also try different options for the `diff2html.html()` function to customize the diff view.
  • Server Not Running: Double-check that your server is running without any errors. Check the console output for any error messages. Make sure you are running the server.js file from the correct directory.

Extending the Tool

This is a basic code review tool, but you can extend it with many features. Here are some ideas:

  • User Authentication: Implement user accounts and login to allow multiple users to use the tool and save their reviews.
  • Comment System: Add a feature for users to add comments to specific lines of code.
  • Version Control Integration: Integrate with Git or other version control systems to fetch code and diffs automatically.
  • Notifications: Implement email or in-app notifications to alert users about new reviews or comments.
  • Code Suggestions: Integrate with code analysis tools (like ESLint or SonarQube) to provide code suggestions.
  • Code Formatting: Add a code formatting feature (like Prettier) to automatically format the code.
  • File Upload: Allow users to upload files instead of pasting code and diffs.

Key Takeaways

Let’s recap the main points of this tutorial:

  • We built a basic code review tool using Node.js, Express, Highlight.js, and Diff2Html.
  • We set up a simple backend to handle the code and diff processing.
  • We created a frontend with HTML, CSS, and JavaScript to display the code and diff.
  • We learned how to handle common issues and extend the tool with new features.

FAQ

Here are some frequently asked questions about this project:

  1. Can I use a different frontend framework? Yes, you can use any frontend framework (React, Vue, Angular, etc.) instead of plain HTML, CSS, and JavaScript.
  2. How can I deploy this tool? You can deploy this tool to a platform like Heroku, AWS, or Google Cloud. You’ll need to configure the platform to run your Node.js application.
  3. Where can I get a diff? You can generate a diff using `git diff` or any other diff tool. Make sure to provide a valid diff format to the tool.
  4. How do I add comments to specific lines? To add comments, you’ll need to modify the diff HTML to include comment sections. You’ll need to add JavaScript to handle the addition of comments. The comments will be associated with specific lines of code.
  5. Can I use this for production code reviews? This tool is a starting point. For production use, you’ll need to add features like user authentication, authorization, and more robust error handling.

Building a code review tool is an excellent way to learn about web development and improve your skills. It allows you to understand how to build collaborative tools that enhance the development process. By following this tutorial, you’ve taken a significant step toward creating your own custom code review solution.