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
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.
// 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
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/123With Base Path Configuration
// 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/#/dashboardHash History with Custom Base
// 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
// 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=2Hash-Based Authentication Flow
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
// 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
// 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 standardWhen to Use Hash History
// ✅ 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🔗 Related APIs
createWebHistory()- HTML5 history modecreateMemoryHistory()- Memory-based historyRouterHistory- History interface
📚 Best Practices
Environment-Based History Selection
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
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
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
createWebHistoryfor production applications when you have control over server configuration. This provides cleaner URLs and better SEO performance.