Compatibility & polyfill
Compatibility & polyfill
The Barcode Detection API is part of the Shape Detection family — implemented by some browsers, gated behind a flag in others, and still missing in a few. The composable surfaces this through isSupported, and the wrapper component renders a fallback UI when the API isn't there.
Browser support
The table below is generated from MDN's browser-compat-data (the same dataset behind the MDN compatibility tables) and refreshes on every docs build.
Desktop
| Chrome | 88+ (partial)
|
|---|---|
| Edge | 83+ (partial)
|
| Firefox | No |
| Safari | 17+ (flag)
|
| Opera | 69+ (partial)
|
Mobile
| Chrome Android | 83+ |
|---|---|
| Firefox Android | No |
| Safari iOS | 17+ (flag)
|
| Samsung Internet | 83+ |
| Opera Android | 69+ (partial)
|
barcode-detector polyfill below lifts that limitation.Polyfill
barcode-detector is a drop-in polyfill that uses ZXing compiled to WebAssembly under the hood. The ./polyfill entry only patches globalThis.BarcodeDetector when the API is missing, so native implementations keep winning where they exist.
pnpm add barcode-detector
Vue
Import the polyfill once at app startup, before mounting:
import { createApp } from 'vue'
import App from './App.vue'
if (typeof window !== 'undefined' && !('BarcodeDetector' in window)) {
await import('barcode-detector/polyfill')
}
createApp(App).mount('#app')
The dynamic import() keeps the wasm bundle out of the main chunk for browsers that already have native support.
Nuxt
Use a client plugin so SSR is unaffected:
export default defineNuxtPlugin(async () => {
if ('BarcodeDetector' in window) return
await import('barcode-detector/polyfill')
})
That's how this docs site itself runs — every demo on the site works in Firefox, Safari, and desktop Linux Chromium thanks to the polyfill.
Detecting support at runtime
Both the composable and the wrapper component expose isSupported. Use it to render a fallback UI (file picker, manual entry, etc.) when neither native nor the polyfill is available:
<script setup lang="ts">
import { useBarcodeDetector } from '@orbisk/vue-use-barcode-detection'
const { isSupported } = useBarcodeDetector(null, { immediate: false })
</script>
<template>
<p v-if="!isSupported">
Barcode scanning isn't available in this browser.
<a href="...">Type the code manually</a> instead.
</p>
</template>
isSupported is gated behind useMounted() in the wrapper component, so it's always false on the server — no hydration mismatches.