Complete Trailing Slashes Guide for Vue

Learn why trailing slashes matter (or don't), how to implement them correctly in Vue Router, and when you can ignore them entirely.

Introduction

A trailing slash is the "/" at the end of a URL. For example:

  • With trailing slash: /about/
  • Without trailing slash: /about

While trailing slashes don't directly impact SEO rankings, they can create technical challenges:

  1. Duplicate Content: When both /about and /about/ serve the same content without proper canonicalization, search engines have to choose which version to index. While Google is generally good at figuring this out, it's better to be explicit.
  2. Crawl Budget: On large sites, having multiple URLs for the same content can waste your crawl budget.
  3. Analytics Accuracy: Different URL formats can split your analytics data, making it harder to track page performance.

The solution is simple: pick one format and stick to it by redirecting the other and set canonical URLs.

Vue Router Configuration

Enforcing Trailing Slashes

Vue Router has a strict mode that enforces exact path matching:

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    // Define all routes with trailing slashes
    { path: '/about/', component: About },
    { path: '/products/', component: Products },
    { path: '/blog/:slug/', component: BlogPost }
  ],
  strict: true // Enforce exact path matching
})

With strict: true, /about and /about/ are treated as different routes.

Removing Trailing Slashes

To remove trailing slashes consistently:

const router = createRouter({
  history: createWebHistory(),
  routes: [
    // Define all routes without trailing slashes
    { path: '/about', component: About },
    { path: '/products', component: Products },
    { path: '/blog/:slug', component: BlogPost }
  ],
  strict: true
})

Client-Side Redirects

Add a navigation guard to redirect inconsistent URLs:

router.beforeEach((to, from, next) => {
  // Remove trailing slashes
  if (to.path !== '/' && to.path.endsWith('/')) {
    next({ path: to.path.slice(0, -1), query: to.query, hash: to.hash })
    return
  }

  // Or add trailing slashes
  // if (to.path !== '/' && !to.path.endsWith('/')) {
  //   next({ path: to.path + '/', query: to.query, hash: to.hash })
  //   return
  // }

  next()
})

Important: Client-side redirects don't send proper HTTP 301 status codes to search engines. Use server-side redirects for SEO.

Server-Side Redirects

For proper SEO, configure your web server to redirect trailing slash variations:

Nginx

Remove trailing slashes:

rewrite ^/(.*)/$ /$1 permanent;

Add trailing slashes:

rewrite ^([^.]*[^/])$ $1/ permanent;

Apache

Remove trailing slashes:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]

Add trailing slashes:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ $1/ [R=301,L]

Canonical URLs

Set canonical URLs to indicate your preferred URL format:

<script setup>
import { useHead } from '@unhead/vue'

useHead({
  link: [
    {
      rel: 'canonical',
      href: 'https://example.com/about' // or /about/
    }
  ]
})
</script>

Best Practices

  1. Choose One Format: Pick with or without trailing slashes and stick to it site-wide
  2. Server-Side Redirects: Use 301 redirects at the server level, not client-side
  3. Canonical Tags: Always set canonical URLs to your preferred format
  4. Internal Links: Be consistent in your internal linking
  5. Sitemap: Use consistent URLs in your sitemap

What NOT to Do

❌ Don't mix URL formats across your site ❌ Don't rely only on client-side redirects for SEO ❌ Don't ignore the issue on large sites ❌ Don't change your format without proper redirects

Using Nuxt?

If you're using Nuxt, check out Nuxt SEO for built-in SEO features. Nuxt SEO provides automatic trailing slash handling through site config and the <SiteLink> component.

Learn more in Nuxt →