惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cloudbric
Cloudbric
T
Threat Research - Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
AWS News Blog
AWS News Blog
P
Privacy & Cybersecurity Law Blog
H
Help Net Security
云风的 BLOG
云风的 BLOG
G
GRAHAM CLULEY
Spread Privacy
Spread Privacy
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
A
Arctic Wolf
Project Zero
Project Zero
Engineering at Meta
Engineering at Meta
P
Privacy International News Feed
Blog — PlanetScale
Blog — PlanetScale
Stack Overflow Blog
Stack Overflow Blog
M
MIT News - Artificial intelligence
The Register - Security
The Register - Security
Recorded Future
Recorded Future
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
Cisco Blogs
PCI Perspectives
PCI Perspectives
Recent Announcements
Recent Announcements
Martin Fowler
Martin Fowler
A
About on SuperTechFans
W
WeLiveSecurity
GbyAI
GbyAI
V
Vulnerabilities – Threatpost
The GitHub Blog
The GitHub Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Check Point Blog
Y
Y Combinator Blog
月光博客
月光博客
Scott Helme
Scott Helme
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google DeepMind News
Google DeepMind News
F
Fortinet All Blogs
U
Unit 42
G
Google Developers Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Threatpost
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google Online Security Blog
Google Online Security Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Cisco Talos Blog
Cisco Talos Blog
博客园 - 三生石上(FineUI控件)
Hugging Face - Blog
Hugging Face - Blog
MongoDB | Blog
MongoDB | Blog
博客园 - 司徒正美

Echo JS

Desktop apps Introducing mermaid-lint: Stop Shipping Broken Diagrams How We Cut Slow Responses by 80% Migrating to Next.js App Router The quiet problem with unnecessary async - Matt Smith GitHub - ant-design/ant-design-cli: Ant Design on your command line. Query component knowledge, analyze project usage, and guide migrations — fully offline. Uncovering the Magic Behind Playwright React Performance Isn’t About useMemo — It’s About Render Boundaries T2 No Escape Hatches · Prickles GitHub - auto-agent-protocol/auto-agent-protocol: Automotive Agent Protocol GitHub - coactionjs/coaction: Zustand-style state management with built-in render tracking and cached computed state GitHub - williamtroup/Rattribute.js: ❓ A lightweight JavaScript library for automatically changing HTML element attributes based on responsive screen sizes. GitHub - williamtroup/Rink.js: 🔗 A JavaScript library for generating responsive HTML link targets. SVAR Kanban: Interactive Task Board Component for Svelte, React, and Vue Performance Cost of Popular 3rd Party Scripts date-light - Tiny date utilities for JavaScript When React Hooks Stop Scaling: Moving Complex State to Zustand - Oren Farhi GitHub - jskits/loggerjs: A faster, more powerful isomorphic logger Out Loud — Free AI Text to Speech Pocket DB — Embedded single-file NoSQL for Node.js billboard.js 4.0 release: Canvas rendering mode, 94.3% faster! GitHub - thegruber/linkpeek: Secure TypeScript link preview and URL metadata extractor for Open Graph, Twitter Cards, JSON-LD, Node/Bun/Deno/edge. GitHub - evoluteur/healing-frequencies: Play the healing frequencies of various sets of tuning forks: Solfeggio, Organs, Mineral nutrients, Ohm, Chakras, Cosmic octave, Otto, DNA nucleotides... or custom. Animated sine waves - 27 lines of pure JavaScript Framework | Neutralinojs GitHub - AllThingsSmitty/typescript-tips-everyone-should-know: ✅ A curated collection of practical TypeScript patterns that improve safety, readability, maintainability, and developer experience. 🧠 Heat.js : JavaScript Heat Map GitHub - iDev-Games/State-JS: State.js is a CSS‑reactive framework that makes UI state and updates flow through CSS instead of JavaScript logic. GitHub - yankouskia/gameplate: :video_game: Boilerplate for creating game with WebGL & Redux :game_die: GitHub - yankouskia/is-incognito-mode: Identify whether browser is in incognito mode 👀
GitHub - yankouskia/get-browser: 💻 Lightweight tool to identify the browser (mobile+desktop detection)📱
2026-07-09 · via Echo JS

get-browser — lightweight, SSR-safe browser detection

Tiny, typed, SSR-safe browser detection.
One call. One canonical answer. ~1.4 kB min+gzip. Zero dependencies.

npm size CI types MIT

📚 Docs site · 🧪 Playground · 🍳 Recipes · ↗️ v1 → v2


import { detect, getEngine, getOS, isMobile, browsers, engines, oses } from 'get-browser';

if (detect() === browsers.SAFARI && isMobile()) {
  applyMobileSafariFix();
}

if (getEngine() === engines.WEBKIT) applyWebkitScrollFix(); // also catches Chrome-iOS
const shortcut = getOS() === oses.MACOS ? '⌘ K' : 'Ctrl K';

That's the whole pitch. Three canonical questions, three strict unions:

  • detect()'chrome' | 'edge' | 'firefox' | 'safari' | 'opera' | 'ie' | 'android' | 'unknown'who.
  • getEngine()'blink' | 'gecko' | 'webkit' | 'trident' | 'presto' | 'edgehtml' | 'unknown'what renders it (correct on iOS).
  • getOS()'macos' | 'windows' | 'linux' | 'ios' | 'android' | 'chromeos' | 'unknown'where it runs.

A handful of tree-shakeable predicates do the boolean versions.

Install

pnpm add get-browser    # or npm / yarn / bun

No bundler? Drop in the UMD bundle:

<script src="https://unpkg.com/get-browser/dist/umd/get-browser.global.js"></script>
<script>
  if (GetBrowser.isMobile()) document.body.classList.add('is-mobile');
</script>

Why you'd use this

  • 🪶 Tiny — ~1.4 kB min+gzip, zero dependencies, tree-shakeable.
  • 🧠 Typeddetect() returns the Browser union, never string. Exhaustive switches compile.
  • 🏗️ SSR-safe — every detector takes { userAgent }. Works in Node, Next.js, Remix, Astro, Workers, Deno.
  • 🎯 Honest — it answers who, not what. For capability checks use @supports / matchMedia.

Tip

Want to see it in action without installing anything? Open the Playground — paste any user-agent and watch every predicate light up.

Usage

Switch on the browser
import { detect, browsers } from 'get-browser';

switch (detect()) {
  case browsers.CHROME:  loadChromeShim();          break;
  case browsers.SAFARI:  patchSafariScrollBug();    break;
  case browsers.FIREFOX: enableFirefoxOnlyFeature(); break;
  case browsers.UNKNOWN: /* bot or new browser */    break;
}
Booleans — tree-shakes to ~400 bytes per predicate
import { isMobile, isChrome, isSafari } from 'get-browser';

if (isMobile() && !isChrome()) showNonChromeMobileBanner();
if (isSafari() && isMobile()) applyMobileSafariFix();
Server-side — Next.js, Remix, Workers, Deno
// Next.js Edge route — runs on Cloudflare too
export const runtime = 'edge';

import { detect, getOS } from 'get-browser';

export function GET(req: Request) {
  const userAgent = req.headers.get('user-agent') ?? '';
  return Response.json({
    browser: detect({ userAgent }),
    // Prefer Sec-CH-UA-Platform — Chrome's UA Reduction is hollowing
    // out the legacy UA string. Get-browser reads either.
    os: getOS({
      userAgent,
      clientHints: { platform: req.headers.get('sec-ch-ua-platform') ?? undefined },
    }),
  });
}

The library never touches window at import time. Pass an explicit UA and detection becomes a pure function — perfect for tests and SSR. Full framework cookbook in the SSR guide.

Cross-platform UI — shortcuts, downloads, deep links
import { getOS, oses } from 'get-browser';

const os = getOS();

const shortcut    = os === oses.MACOS ? '⌘ K' : 'Ctrl K';
const downloadUrl = os === oses.WINDOWS ? '/dl/app.exe'
                  : os === oses.MACOS   ? '/dl/app.dmg'
                  : os === oses.LINUX   ? '/dl/app.deb'
                  : '/dl/';
const storeUrl    = os === oses.IOS     ? 'https://apps.apple.com/…'
                  : os === oses.ANDROID ? 'https://play.google.com/…'
                  : '/install';
In-app browsers — Instagram, Facebook, TikTok, X, LinkedIn, …
import { isInAppBrowser } from 'get-browser';

// OAuth providers (Google, Apple, Microsoft) block sign-in inside
// most in-app browsers. Bounce to the system browser first.
if (isInAppBrowser()) {
  showOpenInBrowserBanner({
    message: 'Tap ⋯ → "Open in browser" to continue with Google sign-in.',
  });
}

Catches Facebook (FBAN/FBAV/FB_IAB), Instagram, X/Twitter, LinkedIn, TikTok, Snapchat, WeChat, Line, Telegram, Pinterest. Stable token-based matching — version-agnostic.

Rendering engine — correct on iOS, where everything is WebKit
import { detect, getEngine, engines } from 'get-browser';

// One check covers Safari + Chrome-iOS + Firefox-iOS + Edge-iOS.
if (getEngine() === engines.WEBKIT) applyWebkitScrollFix();

// Honest analytics: "who" and "what renders it" are different questions.
analytics.track('page_view', { browser: detect(), engine: getEngine() });

getEngine() reads the engine from the UA, so Chrome-on-iOS reports 'webkit' (what actually paints the page) — not 'blink'. A hand-rolled browser → engine lookup gets that wrong.

API

A small surface — every export pulls its weight.

detect(opts?) Returns one of the browsers values
getEngine(opts?) Returns one of the engines values
getOS(opts?) Returns one of the oses values
isChrome / isEdge / isFirefox / isSafari (opts?) => boolean
isOpera / isIE / isAndroid / isMobile (opts?) => boolean
isInAppBrowser (opts?) => booleantrue inside Instagram, Facebook, TikTok, X, LinkedIn, …
browsers, oses, engines Frozen enums: { CHROME: 'chrome', ... }, { MACOS: 'macos', ... }, { WEBKIT: 'webkit', ... }
Browser, OS, Engine, DetectOptions, ClientHints Type-only exports

opts is { userAgent?: string; vendor?: string; clientHints?: { platform?: string } } — pass userAgent for SSR or tests, pass clientHints.platform (the Sec-CH-UA-Platform header) for the most reliable OS read.

Full API reference →

How it stacks up

Bundle (min+gz) get-browser detect-browser bowser ua-parser-js
🏆 ~1.4 kB ~2 kB ~7 kB ~10 kB

Pick ua-parser-js if you need version numbers or device info. Pick get-browser if you just need the single, lowercase, typed answer to which browser is this? — see the full comparison.

What it detects

Chrome Edge Firefox Safari Opera Safari iOS Android IE

Chrome, Edge (legacy & Chromium), Firefox, Safari (desktop, iOS, iPadOS), Opera (Presto & OPR), Internet Explorer 6-11, Android WebView — including iOS variants (CriOS, FxiOS, EdgiOS) and mobile / tablet user-agents. Coverage details: browser support.

Requirements

  • Node ≥ 20 (active LTS — 20, 22, 24)
  • TypeScript ≥ 5.0 if you use types
  • Browsers — evergreen. UMD bundle is ES2018.

Documentation

The full docs are built with Docusaurus and deployed to GitHub Pages:

📚 Docs 🔌 API 🧪 Playground 🍳 Recipes 🏗️ SSR 🔄 Migration

Run the docs locally:

pnpm install
pnpm run build              # build the library first
pnpm run website:install
pnpm run website:dev        # http://localhost:3000

Contributing & license

PRs welcome — see CONTRIBUTING.md. For security issues, see SECURITY.md (please don't open public issues for vulnerabilities).

MIT © yankouskia and contributors.