Deploying Nuxt.js with nginx

Deploying Nuxt.js with nginx

In modern web application development, Nuxt.js has emerged as a popular choice for building high-performance single-page applications (SPAs) thanks to its powerful Server-Side Rendering (SSR) and Incremental Static Regeneration (ISR) capabilities. However, successfully delivering a locally running Nuxt.js service to end users often requires the assistance of a professional reverse proxy server—Nginx. This article delves into how to deploy a Nuxt.js project to a production environment and configure Nginx to ensure users can access your application stably and efficiently.
Before pushing code to the server, the primary task is correct bundling and building. Nuxt.js defaults to using Vite as the build tool (new version) or Webpack (old version), which automatically generate optimized production-ready files. However, before deployment, it is crucial to ensure that necessary optimization options are enabled in the build configuration, such as compressing static resources, removing debug code, and enabling Tree Shaking.

Furthermore, Nuxt.js runtime injects dynamically generated CSS into the HTML head or body footer, while static resources like images are typically placed under the /dist/static/ directory. For Nginx, this means we must explicitly define two key paths: one to handle API requests and JS/CSS files (i.e., index.html), and another specifically mapping to the static resource directory to support CDN acceleration or large file transfers.

Nginx Core Configuration Details

The core configuration file for Nginx is typically located at /etc/nginx/sites-available/your-app-name.conf. Below is the standard configuration structure tailored for a Nuxt.js project, encompassing reverse proxy settings, caching strategies, and security measures.

server {
    listen 80;
    server_name your-domain.com www.your-domain.com;

    # Redirect HTTP to HTTPS (Recommended for production environments)
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com www.your-domain.com;

    # SSL Certificate configuration path
    ssl_certificate /etc/letsencrypt/live/your-domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain/privkey.pem;
    
    # Nuxt.js main application entry file (usually located at dist/index.html)
    location = / {
        try_files $uri $uri/ /index.html;
    }

    # Proxy API and route requests to the Node.js service
    location /api/ {
        proxy_pass http://localhost:3000/api/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

    # Proxy JS, CSS, and font files, enabling caching strategies
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires max;
        add_header Cache-Control "public, immutable";
        proxy_pass http://localhost:3000/;
    }

    # Direct mapping for static resource directories (e.g., dist/static), bypassing Node.js processing
    location /static/ {
        alias ./dist/static/; 
        expires max;
        add_header Cache-Control "public, immutable";
    }

    # Logging configuration
    access_log /var/log/nginx/your-app-access.log;
    error_log /var/log/nginx/your-app-error.log;
}

Key Configuration Points and Best Practices

There are several key points in the above configuration that require special attention:

  • SPA Route Support: Since Nuxt.js is a single-page application (SPA), accessing non-root paths should not directly return a 404 error. The line try_files $uri $uri/ /index.html; is critical as it ensures that regardless of which link the user clicks, Nginx forwards the request to the Node.js service to render the corresponding page content.
  • Caching Strategy: For static resources such as JS, CSS, and images, setting expires max and Cache-Control: public, immutable can significantly reduce server load and improve user loading speeds. Especially when code has been optimized through the build process, the content of these files does not change within the release cycle (immutable), allowing for the use of maximum cache duration.
  • API Proxy: Nuxt.js API routes are typically located under /api/. The configuration explicitly specifies proxy_pass http://localhost:3000/api/;, ensuring that the backend service can correctly receive requests and return JSON data to the frontend.

Deployment Process and Verification

After completing the configuration file, execute the following steps to apply changes to the server:

  1. Test Configuration Syntax: Before applying the new configuration, it is essential to run nginx -t to check for any syntax errors.
  2. Reload Nginx: If the test passes, use the sudo nginx -s reload command to reload the configuration file without interrupting existing connections.
  3. Start Node.js Service: Ensure that your production build files (e.g., /usr/local/bin/your-app-name) have execution permissions and are running in the background listening on the specified port.

Upon completion of the deployment, verify page rendering by accessing the domain via a browser and check the Network panel in the developer tools to confirm if static resources hit the caching strategy. If everything is functioning correctly, it indicates that the integration between Nuxt.js and Nginx has been successfully completed, and your application now possesses production-grade service capabilities suitable for large-scale users.