1.0.1 • Published 8 months ago

@riogz/router-plugin-browser v1.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

@riogz/router-plugin-browser

Browser integration plugin for @riogz/router. Provides seamless integration between the router and browser navigation, supporting both HTML5 history API and hash-based routing.

Features

  • HTML5 History API Support - Modern pushState/replaceState navigation
  • Hash-based Routing - Fallback for older browsers or specific requirements
  • Base Path Support - Deploy apps in subdirectories
  • State Preservation - Maintain router state in browser history
  • SSR Compatible - Safe fallbacks for server-side rendering
  • TypeScript Support - Full type definitions included

Installation

npm install @riogz/router-plugin-browser

Basic Usage

import { createRouter } from '@riogz/router'
import browserPlugin from '@riogz/router-plugin-browser'

const routes = [
  { name: 'home', path: '/' },
  { name: 'users', path: '/users/:id' }
]

const router = createRouter(routes)

// Use the browser plugin
router.usePlugin(browserPlugin())

// Start the router
router.start()

Configuration Options

BrowserPluginOptions

interface BrowserPluginOptions {
  forceDeactivate?: boolean    // Force route deactivation during transitions (default: true)
  useHash?: boolean           // Use hash-based routing (default: false)
  hashPrefix?: string         // Prefix after hash symbol (default: '')
  base?: string | null        // Base path for the application (default: '')
  mergeState?: boolean        // Merge with existing browser state (default: false)
  preserveHash?: boolean      // Preserve URL hash during navigation (default: true)
}

Usage Examples

HTML5 History Mode (Default)

// URLs: /users/123, /profile, /settings
router.usePlugin(browserPlugin({
  useHash: false
}))

Hash-based Routing

// URLs: #/users/123, #/profile, #/settings
router.usePlugin(browserPlugin({
  useHash: true
}))

// With prefix: #!/users/123, #!/profile, #!/settings
router.usePlugin(browserPlugin({
  useHash: true,
  hashPrefix: '!'
}))

Application in Subdirectory

// URLs: /myapp/users/123, /myapp/profile
router.usePlugin(browserPlugin({
  base: '/myapp'
}))

State Merging

// Preserve additional properties in history.state
router.usePlugin(browserPlugin({
  mergeState: true
}))

// Now you can add custom data to history
history.replaceState({
  ...history.state,
  scrollPosition: window.scrollY,
  customData: 'value'
}, '', location.href)

Extended Router Methods

The plugin adds several methods to the router instance:

buildUrl(name, params)

Build a complete URL for a route:

// With base path and hash prefix
const url = router.buildUrl('users.profile', { id: '123' })
// Result: /myapp#!/users/123/profile (depending on config)

matchUrl(url)

Match a complete URL against routes:

const state = router.matchUrl('https://example.com/users/123')
if (state) {
  console.log(state.name)   // 'users'
  console.log(state.params) // { id: '123' }
}

replaceHistoryState(name, params, title)

Update browser history without navigation:

// Update URL and history state without triggering route change
router.replaceHistoryState('users.profile', { id: '456' }, 'User Profile')

Browser Abstraction

The plugin uses a browser abstraction layer that provides safe fallbacks for non-browser environments:

import browser from '@riogz/router-plugin-browser/browser'

// Safe to use in any environment
const currentPath = browser.getLocation({ useHash: false, base: '' })
browser.pushState({ name: 'home' }, 'Home', '/home')

Testing

For testing, you can provide a mock browser implementation:

import browserPlugin from '@riogz/router-plugin-browser'

const mockBrowser = {
  getBase: () => '/test',
  pushState: jest.fn(),
  replaceState: jest.fn(),
  addPopstateListener: jest.fn(() => () => {}),
  getLocation: () => '/current/path',
  getState: () => null,
  getHash: () => ''
}

router.usePlugin(browserPlugin({}, mockBrowser))

Advanced Configuration

Custom Hash Prefix

// Google-style hash routing: #!/users/123
router.usePlugin(browserPlugin({
  useHash: true,
  hashPrefix: '!'
}))

Preserve Hash Fragments

// Maintain #section anchors during navigation
router.usePlugin(browserPlugin({
  preserveHash: true  // default
}))

// Navigate from /page1#section1 to /page2#section1
router.navigate('page2')

Force Route Deactivation

// Control route lifecycle during transitions
router.usePlugin(browserPlugin({
  forceDeactivate: false  // Allow routes to stay active when possible
}))

Browser Compatibility

  • Modern Browsers: Full HTML5 history API support
  • Legacy Browsers: Automatic fallback to hash-based routing
  • Internet Explorer: Special handling for hashchange events
  • Server-Side Rendering: Safe no-op implementations

Error Handling

The plugin handles various error scenarios:

  • Navigation Blocking: Respects route guards and canDeactivate hooks
  • Invalid URLs: Graceful fallback to default routes
  • State Conflicts: Prevents duplicate history entries
  • Browser Limitations: Automatic detection and workarounds

Integration with Other Plugins

The browser plugin works seamlessly with other router plugins:

import browserPlugin from '@riogz/router-plugin-browser'
import loggerPlugin from '@riogz/router-plugin-logger'

router.usePlugin(browserPlugin())
router.usePlugin(loggerPlugin())

TypeScript Support

Full TypeScript definitions are included:

import { BrowserPluginOptions, Browser, HistoryState } from '@riogz/router-plugin-browser'

const options: BrowserPluginOptions = {
  useHash: true,
  hashPrefix: '!'
}

const customBrowser: Browser = {
  // Implementation
}

API Reference

Types

  • BrowserPluginOptions - Configuration options for the plugin
  • Browser - Browser abstraction interface
  • HistoryState - Extended router state with browser history data

Functions

  • browserPluginFactory(options?, browser?) - Create a browser plugin instance
  • default export - The browserPluginFactory function

License

MIT © Vyacheslav Krasnyanskiy

1.0.1

8 months ago

1.0.0

8 months ago

0.0.16

8 months ago

0.0.15

8 months ago

0.0.13

8 months ago

0.0.12

8 months ago

0.0.4

8 months ago

0.0.3

9 months ago

0.0.2

9 months ago