Fully Verified Tencent Cloud Account Deploy Vue Projects with Nginx Optimization on Tencent Cloud

Tencent Cloud / 2026-05-14 22:17:20

Deploy Vue Projects with Nginx Optimization on Tencent Cloud

So you built a Vue app. It runs beautifully on your laptop, where everything is fast, the weather is perfect, and the only person you need to impress is… yourself. Then you upload it to Tencent Cloud and suddenly your browser is asking questions like: “Why is the initial load taking 8 eternities?” “Why does refreshing a route show a 404?” “Why do fonts look like they escaped a typo?”

Fear not. This guide shows how to deploy your Vue project on Tencent Cloud using Nginx, while optimizing it so your site loads quickly, routing behaves correctly, and visitors don’t immediately decide to go back to their cat videos.

Fully Verified Tencent Cloud Account What We’re Actually Building

A typical Vue production deployment is simple: compile the Vue app into static files (usually in a dist folder), then serve those files via Nginx. However, the “simple” part ends the moment you remember Vue is usually a single-page application (SPA). That means:

  • Your app’s routes (like /dashboard) are handled client-side.
  • When someone refreshes the page or directly visits a deep link, the server must still return index.html instead of a 404.
  • Performance matters: caching, compression, and smart headers can make a huge difference.

We’ll solve all that. Additionally, we’ll set you up with a practical, readable Nginx configuration tailored for Vue SPAs.

Prerequisites

Before we get dramatic with Nginx, make sure you have:

  • A Tencent Cloud instance ready to run Nginx (CVM or similar).
  • Node.js installed locally for building Vue (you build on your machine; Nginx serves on the server).
  • A built Vue project (Vite or Vue CLI works).
  • SSH access to your Tencent Cloud instance.
  • Basic comfort with editing configuration files. (If not, don’t worry. We’ll keep it simple.)

Step 1: Build Your Vue App for Production

You want the production output that Nginx can serve as static assets. Depending on your toolchain:

If You’re Using Vue CLI

Run:

npm run build

This usually generates a dist folder.

If You’re Using Vite

Run:

Fully Verified Tencent Cloud Account npm run build

Vite also outputs to a dist folder by default.

Now you have static files. Your server should serve those files, aggressively and without complaining.

Step 2: Upload the Build Output to Tencent Cloud

Pick your preferred deployment method:

  • SCP/SFTP upload of the dist directory
  • rsync for faster incremental updates
  • Or build directly on the server (not recommended unless you really enjoy waiting for npm to finish like it’s a hobby)

Where should you place the files on the server?

Common choice: a directory like /var/www/your-app. You can adapt this path to match your setup.

Example:

/var/www/vue-app/dist (or just copy the contents of dist directly into /var/www/vue-app)

Just be consistent, because Nginx loves consistency the way cats love knocking things off tables.

Step 3: Install Nginx (If Needed)

If Nginx isn’t installed on your Tencent Cloud instance, install it using your OS package manager. Many common images already include Nginx, but not always.

Typical workflow (you may need to adjust for OS version):

  • Install: apt/yum (depending on system)
  • Start Nginx
  • Enable on boot
  • Open ports 80/443 in security group

Remember: Tencent Cloud security group rules must allow inbound traffic. Your config can be perfect, but if the firewall says “no,” your visitors will see an empty sky.

Step 4: Create an Nginx Server Block for Your Vue SPA

Here’s the key idea: Nginx must serve static assets normally, but for “unknown routes” (like /profile or /settings/account), it should return index.html.

That’s what makes Vue Router behave properly when the user refreshes a route.

Example Nginx Configuration (Recommended Starting Point)

Below is an example configuration you can adapt. It includes:

  • SPA routing fallback to index.html
  • Compression (gzip)
  • Better caching for static assets
  • Security-related headers (reasonable defaults)
  • MIME types included via standard Nginx behavior

Put it in a file like /etc/nginx/conf.d/vue-app.conf or /etc/nginx/sites-available/... depending on your setup.

Fully Verified Tencent Cloud Account server { listen 80; server_name your-domain.com; root /var/www/vue-app; index index.html; # Access log (you can adjust or disable) access_log /var/log/nginx/vue-app_access.log; error_log /var/log/nginx/vue-app_error.log; # 1) Compression gzip on; gzip_min_length 10240; gzip_comp_level 6; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript application/xml application/xml+rss image/svg+xml; gzip_vary on; # 2) Cache strategy # Cache immutable assets (Vue/Vite typically uses content hashes) location ~* \.(?:css|js|map|woff|woff2|ttf|eot|svg|png|jpg|jpeg|gif|webp|ico)$ { expires 365d; add_header Cache-Control "public, max-age=31536000, immutable"; try_files $uri =404; } # 3) Prevent caching of HTML so updates take effect location = /index.html { expires -1; add_header Cache-Control "no-cache, no-store, must-revalidate"; } # 4) SPA fallback: send index.html for routes location / { try_files $uri $uri/ /index.html; } # 5) Security headers (tune based on your needs) add_header X-Content-Type-Options nosniff; add_header X-Frame-Options SAMEORIGIN; add_header Referrer-Policy strict-origin-when-cross-origin; # Optional: HSTS if you enable HTTPS # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; }

Now, why do we use try_files $uri $uri/ /index.html?

  • If the path matches a real file (like /assets/app.abc123.js), serve it.
  • Fully Verified Tencent Cloud Account If not, return /index.html so Vue Router can handle the route.

Fully Verified Tencent Cloud Account Without this, refreshing a client-side route often results in a 404 from Nginx. That’s the classic “works in navigation, breaks on refresh” trap.

Step 5: If You Use HTTPS (Strongly Recommended)

In production, HTTPS is not optional; it’s the bare minimum. With Tencent Cloud, you can use:

  • Cloud Load Balancer with TLS termination
  • Or install certificates directly on your instance (Let’s Encrypt or CA-issued)

If your load balancer handles TLS, your instance may still see traffic on port 80 internally. If you terminate TLS on the instance, you’ll have a separate server block for 443.

Either way, your users will thank you and your browser won’t throw a tantrum.

Quick Note About HSTS

HSTS makes the browser always use HTTPS for your domain. Add it only when you’re confident HTTPS is properly configured. Otherwise, you’ll be locked out like a door with a key you misplaced.

Step 6: Make Sure File Paths and Roots Are Correct

Nginx uses:

  • root to point to the directory containing your built files
  • index to serve index.html

If your build output is in /var/www/vue-app/dist, but your config says root /var/www/vue-app;, Nginx will look for /var/www/vue-app/index.html and might find nothing.

Choose one of these options:

  • Set root /var/www/vue-app/dist;
  • Or copy contents of dist into /var/www/vue-app

Most people choose the second option because it’s simpler: no nested dist confusion.

Step 7: Enable Nginx Optimizations (Beyond the Basics)

We already added gzip and caching. Now let’s go a bit further, still keeping it practical and readable.

Consider Brotli (If You Can)

Gzip is supported everywhere, but Brotli usually gives smaller compressed files. However, Brotli support often requires additional Nginx modules or configuration. On some environments, it’s straightforward; on others, it’s… “let’s see what breaks today.”

If your setup supports Brotli, it can be a nice upgrade. But don’t block your deployment over it. Performance is a marathon, not a midnight rescue mission.

Use a Dedicated Cache Header for Asset Types

For Vue/Vite, your JS/CSS files typically include content hashes in filenames (like app.3f1a9c.css). That means those files are immutable until you deploy new builds.

That’s why caching them for a long time is safe. But HTML should not be cached aggressively, because it changes when you deploy new builds.

The config above handles exactly that: long cache for assets, no cache for index.html.

Step 8: Add Correct Handling for Browser Refresh and Deep Links

Here’s the classic symptom:

  • Clicking a link inside your SPA works.
  • Refreshing that same link shows a 404.

That means Nginx is treating /your-route as a request for a real file, fails to find it, and returns 404.

The fix is the SPA fallback rule:

try_files $uri $uri/ /index.html;

That forces all “not-a-file” requests to return the SPA entry point.

Step 9: Validate Vue Router Base Path (Common Deployment Gotcha)

Vue Router often needs a correct base configuration when deploying under a subpath.

Examples:

  • Your app is served at https://example.com/ (root). Usually no special base needed.
  • Your app is served at https://example.com/myapp/ (subpath). Then you must set base appropriately in the build tool and set router base behavior.

If your routes look correct but assets fail to load, you may have a base-path mismatch. Fixing it means aligning your build configuration and router base.

For Vite, look at base in vite.config.js. For Vue CLI, you might use publicPath. Match it to your actual deployment path.

Step 10: Security Headers Without Breaking Everything

Headers are useful, but they can also break weird edge cases. The config included safe-ish defaults:

  • X-Content-Type-Options nosniff reduces MIME sniffing.
  • X-Frame-Options SAMEORIGIN reduces clickjacking.
  • Referrer-Policy strict-origin-when-cross-origin improves privacy.

If you use third-party widgets or need framing from other origins, you may need to adjust X-Frame-Options. Security is a balancing act—like riding a bicycle while balancing a laptop on your head. Possible, but carefully.

Step 11: Troubleshooting Like a Calm Adult

Even with the perfect config, you might hit issues. Here are common ones and what to check.

Problem: Routes Return 404 on Refresh

  • Confirm you included try_files $uri $uri/ /index.html; in the location / block.
  • Confirm root points to the directory containing index.html.
  • Check if your Vue app uses history mode vs hash mode. The config above supports history mode well.

Problem: CSS/JS Loads Slowly

  • Make sure caching headers are set for asset files.
  • Ensure your build output filenames include hashes. If not, long caching may be unsafe.
  • Check gzip settings. Confirm the browser receives compressed responses.

Problem: Some Assets 404 While Others Work

  • Check base path configuration in your build.
  • Verify your root and file structure on the server.
  • Confirm you copied the entire dist contents, not just index.html.

Problem: Nginx Doesn’t Start After Changes

Don’t panic. Always test your config before restart:

nginx -t

Then restart:

systemctl restart nginx

If there’s a typo, Nginx will usually tell you exactly where it hurts. Treat that output like a doctor’s note, not like a mysterious fortune cookie.

Step 12: Performance Checklist (Quick Wins That Actually Matter)

Here’s a deployment checklist you can reuse every time you ship a Vue project.

  • Build in production mode (npm run build).
  • Fully Verified Tencent Cloud Account Serve the correct dist directory via Nginx root.
  • Use SPA fallback: try_files $uri $uri/ /index.html;.
  • Enable gzip for text and JS/CSS.
  • Cache hashed assets with long TTL and immutable.
  • Disable caching for index.html.
  • Set reasonable security headers.
  • Test deep links: open /some-route, refresh it, and verify it loads.
  • Test mobile network simulation to see if your compression/caching helps.

Ready-to-Adapt “Production-ish” Nginx Config

If you want a slightly more complete config template, here’s a cleaner version that keeps the same core ideas. You can paste it, modify server_name, and adjust the root path.

server { listen 80; server_name your-domain.com; root /var/www/vue-app; index index.html; access_log /var/log/nginx/vue-app_access.log; error_log /var/log/nginx/vue-app_error.log; # Compression gzip on; gzip_vary on; gzip_min_length 10240; gzip_comp_level 6; gzip_types text/plain text/css application/json application/javascript text/javascript application/xml application/xml+rss image/svg+xml; # Long-term caching for static assets location ~* \.(?:css|js|map|woff|woff2|ttf|eot|svg|png|jpg|jpeg|gif|webp|ico)$ { expires 365d; add_header Cache-Control "public, max-age=31536000, immutable"; try_files $uri =404; } # Do not cache HTML location = /index.html { expires -1; add_header Cache-Control "no-cache, no-store, must-revalidate"; } # SPA fallback location / { try_files $uri $uri/ /index.html; } # Helpful headers add_header X-Content-Type-Options nosniff; add_header X-Frame-Options SAMEORIGIN; add_header Referrer-Policy strict-origin-when-cross-origin; }

Bonus: What About the Backend?

This article focuses on deploying the Vue frontend. Usually you’ll also have an API backend (Node, Java, Go, etc.). In a real system, you might want Nginx to:

  • Serve static frontend assets
  • Proxy API calls to your backend at a different upstream

Example conceptually:

  • /api/ requests go to backend (proxy)
  • Everything else goes to Vue static files (SPA)

If you want that, tell me what backend URL and paths you’re using, and I’ll tailor an Nginx config that doesn’t accidentally treat /api/login as a frontend route (Nginx can be very literal; it’s both a strength and a weakness).

Conclusion: Your Vue App, Now Faster and Less Confused

Deploying a Vue project on Tencent Cloud with Nginx doesn’t need to be painful. The main things you must get right are:

  • Serve the correct built output directory
  • Configure SPA fallback so deep links work on refresh
  • Use caching and compression so assets load quickly
  • Add a few reasonable headers for safety

Once those are in place, your site stops feeling like it’s loading through three time zones and a fog machine. Your users will notice. Your future self will also notice, which is the best kind of notification.

If you share your Vue build type (Vite or Vue CLI), router mode (history/hash), and your intended domain/path (root or subpath), I can customize the Nginx config precisely for your scenario.

TelegramContact Us
CS ID
@cloudcup
TelegramSupport
CS ID
@yanhuacloud