Skip to content

createWebHashHistory Function | Vue Router

createWebHashHistory creates a history instance that uses the hash portion of the URL for routing. This is particularly useful for single-page applications that need to work without server configuration. 🔗

📋 Function Signature

typescript
function createWebHashHistory(base?: string): RouterHistory

🎯 Purpose and Usage

The createWebHashHistory function creates a hash-based routing history manager. Hash-based routing uses the URL fragment (the part after the #) to manage application state, making it ideal for scenarios where you cannot configure server-side routing.

Key Benefits:

  • No Server Configuration Required - Works with any static file server
  • Browser Compatibility - Works in all modern browsers
  • Simple Deployment - Easy to deploy to CDNs and static hosts
  • URL Preservation - Maintains full URLs while using hash routing

🔍 Parameters

base (optional)

  • Type: string
  • Default: '' (empty string)
  • Description: The base URL for the application

The base parameter allows you to specify a base path for your application. This is useful when deploying to a subdirectory.

typescript
// Deployed at https://example.com/my-app/
const history = createWebHashHistory('/my-app/')
// URLs will be: https://example.com/my-app/#/home

💡 Practical Usage Examples

Basic Hash History Setup

typescript
import { createRouter, createWebHashHistory } from 'vue-router'

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About },
    { path: '/user/:id', component: UserProfile }
  ]
})

// Resulting URLs:
// - Home: http://localhost:8080/#/
// - About: http://localhost:8080/#/about  
// - User: http://localhost:8080/#/user/123

With Base Path Configuration

typescript
// For deployment to a subdirectory
const router = createRouter({
  history: createWebHashHistory('/my-app/'),
  routes: [
    { path: '/', component: Home },
    { path: '/dashboard', component: Dashboard }
  ]
})

// URLs will be:
// - Home: https://domain.com/my-app/#/
// - Dashboard: https://domain.com/my-app/#/dashboard

Hash History with Custom Base

typescript
// Dynamic base path based on environment
function getBasePath(): string {
  if (process.env.NODE_ENV === 'development') {
    return '/'
  } else if (process.env.VITE_APP_BASE_PATH) {
    return process.env.VITE_APP_BASE_PATH
  } else {
    return '/production-app/'
  }
}

const router = createRouter({
  history: createWebHashHistory(getBasePath()),
  routes: [/* your routes */]
})

🔧 Advanced Patterns

Hash History with Query Parameters

typescript
// Hash history handles query parameters naturally
const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    { path: '/search', component: SearchResults }
  ]
})

// Navigation with query parameters
router.push({
  path: '/search',
  query: { q: 'vue router', page: '2' }
})

// Resulting URL: /#/search?q=vue+router&page=2

Hash-Based Authentication Flow

typescript
class HashAuthFlow {
  private router: Router
  
  constructor() {
    this.router = createRouter({
      history: createWebHashHistory(),
      routes: [
        { path: '/', component: Home, meta: { requiresAuth: true } },
        { path: '/login', component: Login },
        { path: '/callback', component: AuthCallback }
      ]
    })
    
    this.setupAuthHandling()
  }
  
  private setupAuthHandling() {
    this.router.beforeEach((to, from) => {
      if (to.meta.requiresAuth && !this.isAuthenticated()) {
        // Redirect to login with return URL
        return {
          path: '/login',
          query: { redirect: to.fullPath }
        }
      }
    })
  }
  
  handleAuthCallback() {
    // Process authentication callback in hash fragment
    const hashParams = new URLSearchParams(window.location.hash.slice(1))
    const token = hashParams.get('access_token')
    
    if (token) {
      this.storeToken(token)
      // Redirect to original destination or home
      const redirect = this.router.currentRoute.value.query.redirect as string
      this.router.push(redirect || '/')
    }
  }
}

Hash History for Embedded Applications

typescript
// For applications embedded in other sites
class EmbeddedAppRouter {
  private router: Router
  
  constructor(containerElement: string) {
    this.router = createRouter({
      history: createWebHashHistory(),
      routes: this.getEmbeddedRoutes(),
      scrollBehavior: () => ({ top: 0 }) // No scroll in embedded context
    })
    
    this.mountToContainer(containerElement)
  }
  
  private getEmbeddedRoutes() {
    return [
      {
        path: '/',
        component: EmbeddedDashboard,
        meta: { embedded: true }
      },
      {
        path: '/widget/:id',
        component: WidgetView,
        props: true,
        meta: { embedded: true }
      }
    ]
  }
  
  // External navigation control
  navigateToWidget(widgetId: string) {
    this.router.push(`/widget/${widgetId}`)
  }
  
  getCurrentWidgetId(): string | null {
    const route = this.router.currentRoute.value
    return route.params.id as string || null
  }
}

🚨 Important Considerations

Hash Routing Limitations

typescript
// Hash routing has some limitations to be aware of:

// 1. SEO Impact
// Hash URLs are not crawlable by search engines
// Consider SSR or static generation for SEO-critical pages

// 2. Server-Side Redirects
// Server cannot handle hash-based redirects
// All routing must be client-side

// 3. URL Structure
// Hash URLs can be less clean than path-based URLs
// Example: /#/user/123 vs /user/123

// 4. Bookmarking
// While bookmarks work, the URLs are less standard

When to Use Hash History

typescript
// ✅ Good scenarios for hash history:

// 1. Static file hosting (GitHub Pages, Netlify, Vercel)
const history = createWebHashHistory()

// 2. Legacy browser support
// Hash routing works in older browsers without History API

// 3. Embedded applications
// When your app runs within another website

// 4. Development and prototyping
// Quick setup without server configuration

// ❌ Consider web history for:
// - Production applications with server control
// - SEO requirements
// - Clean URL preferences

📚 Best Practices

Environment-Based History Selection

typescript
function createAppropriateHistory(): RouterHistory {
  // Use hash history for static deployments
  if (import.meta.env.VITE_STATIC_DEPLOYMENT) {
    return createWebHashHistory(import.meta.env.BASE_URL)
  }
  
  // Use web history when server support is available
  if (import.meta.env.SSR || import.meta.env.PROD) {
    return createWebHistory(import.meta.env.BASE_URL)
  }
  
  // Default to hash history for safety
  return createWebHashHistory(import.meta.env.BASE_URL)
}

const router = createRouter({
  history: createAppropriateHistory(),
  routes: [/* your routes */]
})

Hash History with Error Handling

typescript
class RobustHashRouter {
  private router: Router
  
  constructor() {
    this.router = createRouter({
      history: createWebHashHistory(),
      routes: [/* routes */]
    })
    
    this.setupErrorHandling()
  }
  
  private setupErrorHandling() {
    // Handle navigation errors
    this.router.onError((error) => {
      console.error('Navigation error:', error)
      
      // Special handling for hash routing issues
      if (error.message.includes('hash')) {
        this.handleHashRoutingError(error)
      }
    })
    
    // Handle 404 for hash routes
    this.router.addRoute({
      path: '/:pathMatch(.*)*',
      component: NotFound
    })
  }
  
  private handleHashRoutingError(error: any) {
    // Attempt to recover from hash routing issues
    const currentHash = window.location.hash
    if (!currentHash || currentHash === '#/') {
      // Reset to home if hash is corrupted
      this.router.replace('/')
    }
  }
}

Hash URL Utilities

typescript
class HashURLUtils {
  // Extract parameters from hash URL
  static getHashParams(): URLSearchParams {
    return new URLSearchParams(window.location.hash.slice(1))
  }
  
  // Update hash without triggering navigation
  static updateHashParam(key: string, value: string) {
    const params = this.getHashParams()
    params.set(key, value)
    window.location.hash = params.toString()
  }
  
  // Get current hash path (without query parameters)
  static getCurrentHashPath(): string {
    const hash = window.location.hash.slice(1)
    return hash.split('?')[0] || '/'
  }
  
  // Check if we're at a specific hash route
  static isAtHashRoute(routePath: string): boolean {
    return this.getCurrentHashPath() === routePath
  }
}

💡 Pro Tip: While hash routing is convenient for development and static deployments, consider migrating to createWebHistory for production applications when you have control over server configuration. This provides cleaner URLs and better SEO performance.

🚀 Vue Router - 让前端路由变得简单而强大 | 构建现代化单页应用的最佳选择