The Node.js Journey: Crafting Solutions for SEO Page Creator

Go Top RatedGo Top Rated
3 min read

Node.js for Location Pages

The Beginning

It all started with a vision. When we launched SEO Page Creator, we wanted to build a robust system that could dynamically generate location-based pages to enhance our clients' online presence. I have been using Node.js for years, having developed a deep understanding of its asynchronous nature, event-driven architecture, and extensive npm ecosystem. I felt confident that Node.js would be the perfect backbone for our project.

The Challenge

As the project grew, so did its complexity. One afternoon, we encountered a perplexing issue that threatened to derail our progress. Our system was supposed to generate location-specific SEO pages on the fly but intermittently failed. Users from certain locations were met with error messages instead of tailored content, which was unacceptable.

The error logs pointed to a recurring issue: ERR_CONNECTION_TIMEOUT. The server was timing out and unable to handle the requests efficiently. This was a significant problem, as our reputation hinged on providing seamless, location-based SEO services.

Diagnosing the Problem

I delved into the code, seeking the root of the issue. Here’s a snippet of what the problematic code looked like:

// Old Code
const http = require('http');
const url = require('url');
const querystring = require('querystring');

http.createServer((req, res) => {
    const query = url.parse(req.url).query;
    const location = querystring.parse(query).location;

    if (location) {
        // Fetch location-specific data
        fetchLocationData(location, (err, data) => {
            if (err) {
                res.writeHead(500, {'Content-Type': 'text/plain'});
                res.end('Server Error');
                return;
            }
            res.writeHead(200, {'Content-Type': 'text/html'});
            res.end(renderPage(data));
        });
    } else {
        res.writeHead(400, {'Content-Type': 'text/plain'});
        res.end('Bad Request');
    }
}).listen(8080);

function fetchLocationData(location, callback) {
    // Simulate a long database call
    setTimeout(() => {
        callback(null, { title: `Welcome to ${location}`, content: 'Some SEO optimized content' });
    }, 5000); // 5 seconds delay to simulate DB call
}

The use of a 5-second delay to simulate a database call was causing the server to timeout under load. This synchronous blocking was not scaling well with increased traffic.

The Solution

To resolve this, I refactored the code to use asynchronous non-blocking operations, leveraging promises and async/await for better performance. Here’s the improved version of the code:

// New Code
const http = require('http');
const url = require('url');
const querystring = require('querystring');
const fetch = require('node-fetch');

http.createServer(async (req, res) => {
    const query = url.parse(req.url).query;
    const location = querystring.parse(query).location;

    if (location) {
        try {
            const data = await fetchLocationData(location);
            res.writeHead(200, {'Content-Type': 'text/html'});
            res.end(renderPage(data));
        } catch (err) {
            res.writeHead(500, {'Content-Type': 'text/plain'});
            res.end('Server Error');
        }
    } else {
        res.writeHead(400, {'Content-Type': 'text/plain'});
        res.end('Bad Request');
    }
}).listen(8080);

async function fetchLocationData(location) {
    // Simulate a non-blocking database call
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve({ title: `Welcome to ${location}`, content: 'Some SEO optimized content' });
        }, 500); // Reduced delay for simulation
    });
}

function renderPage(data) {
    return `
        <html>
        <head><title>${data.title}</title></head>
        <body>${data.content}</body>
        </html>
    `;
}

The Result

The refactored code significantly improved the performance and reliability of our application. By reducing the simulated database call delay and using async/await, we were able to handle more requests concurrently without timing out. The server's response time improved, and users from all locations started receiving their tailored SEO pages promptly.

Conclusion

The journey with Node.js has been one of continuous learning and improvement. The challenge ERR_CONNECTION_TIMEOUT was a reminder of the importance of scalable, non-blocking code. Through perseverance and a deep understanding of Node.js, we were able to overcome the obstacle and enhance the functionality of SEO Page Creator. This experience not only improved our application but also strengthened my expertise in Node.js, reaffirming why I had chosen it as the cornerstone of our development stack.

0
Subscribe to my newsletter

Read articles from Go Top Rated directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Go Top Rated
Go Top Rated