Skip to content

OS Detect

v2.2.1УтилитыVanilla JSVueReact

Лёгкое определение ОС, форм-фактора и рантайм-окружения для браузера, Node.js и SSR — с React-хуками и Vue composables. Без зависимостей.

OS Detect
Начать знакомство →
npm install os-detect@latest
01 — Назначение

Когда это пригодится

navigator.userAgent врёт чаще, чем кажется: iPadOS выдаёт себя за Mac, а наивный парсинг ловит Windows 10 там, где на самом деле Windows 11 — os-detect берёт эти частные случаи на себя вместо самодельного regexp.

Горячие клавиши должны звучать как Cmd, а не Ctrl

Подсказка «Ctrl+K» выглядит нелепо на Mac, а «⌘K» — на Windows. Пакет сам определяет, какая операционная система перед ним, без ручного разбора строки браузера.

iPad выдаёт себя за десктопный Mac

Начиная с iPadOS 13 браузер представляется как «Macintosh», и наивная проверка спутает планшет с ноутбуком. Дополнительная проверка поддержки сенсорного экрана различает их корректно.

Функция доступна не на всех версиях одной ОС

Новая возможность операционной системы работает только в Windows 11 — нужно отличить её от Windows 10 и более старых версий, причём одинаково и в браузере, и на сервере.

Определение ОС не должно ломать серверный рендеринг

Код, который напрямую читает объекты браузера на сервере, просто упадёт при серверном рендеринге — определение ОС остаётся безопасным для такого сценария и само обновляется, когда работа переходит в браузер.

Выбор языка дизайна под платформу, а не только под ОС

Windows должна ощущаться как Fluent, Android — как Material, но телефон и десктопный браузер на одной и той же ОС всё равно хотят разную вёрстку. ОС и форм-фактор вместе отвечают на оба вопроса, вместо того чтобы гадать по ширине экрана.

У гибридного устройства клавиатуру подключают или отключают прямо во время сессии

Ноутбук-трансформер (или складное устройство) может перейти от чисто сенсорного управления к мыши как основному вводу без перезагрузки страницы. Проверка поддержки тача один раз при загрузке этого не заметит — проверка активного типа ввода здесь обновляется сама, вживую.

02 — Фичи

Коротко о главном

Определение ОС и булевы проверки

Определение ОС и булевы проверки

Функция getOS() возвращает идентификатор текущей ОС: iOS, macOS, Android, Windows, Linux, ChromeOS или unknown. Дополнительные булевы функции (detectIsIOS, detectIsWindows и другие) позволяют гибко проверять конкретные системы без лишних зависимостей.

Асинхронное определение Windows 11

Асинхронное определение Windows 11

detectIsWindows11() асинхронно определяет Windows 11 в браузере (через getHighEntropyValues) и в Node.js (через os.release). Возвращает true только для Windows 11, позволяя отличить её от Windows 10 и более старых версий без сложных парсингов.

Форм-фактор, категории устройств и корректная iPadOS

Форм-фактор, категории устройств и корректная iPadOS

isMobileDevice() и isDesktopDevice() дают быструю грубую классификацию, а getFormFactor() идёт дальше — телефон, планшет, десктоп или телевизор, по ОС и физическому размеру экрана, а не по наличию тачскрина. Детектор iOS корректно обрабатывает iPadOS 13+, которая маскируется под Macintosh в userAgent, используя navigator.maxTouchPoints. Отдельные проверки — есть ли вообще сенсорный экран, какой тип ввода сейчас основной, и соотношение физических и логических пикселей.

Готовые хуки для React и Vue

Готовые хуки для React и Vue

useOS(), useFormFactor() и useRuntime() (синхронные), а также useIsWindows11() (асинхронный, с состоянием null) доступны для React и Vue. usePrimaryInput() — единственный по-настоящему реактивный хук из набора: сам обновляется, если у гибридного устройства прямо во время сессии подключили или отключили клавиатуру или мышь. React-хуки используют useState, Vue-композаблы возвращают readonly-рефы. Все они SSR-безопасны.

Определение рантайм-окружения

Определение рантайм-окружения

getRuntime() отличает вкладку браузера от Node.js-скрипта или Web Worker, а отдельные проверки уточняют это дальше: запущено ли приложение внутри Electron (в основном или renderer-процессе), и установлено ли оно и запущено как самостоятельное PWA, а не обычная вкладка браузера.

SSR, Node.js и нулевые зависимости

SSR, Node.js и нулевые зависимости

В Node.js библиотека читает process.platform, и каждая функция кэширует результат после первого вызова — кроме двух, чей ответ может по-настоящему измениться прямо во время сессии (активный тип ввода, соотношение пикселей), они намеренно остаются живыми. Есть сброс кэша для тестов. Пакет не имеет внешних зависимостей, поставляется в ESM, CJS и UMD, а React и Vue — опциональные peer-зависимости.

03 — Быстрый пример

Как это работает

Одна синхронная проверка для браузера, Node и SSR

getOS() и проверки категории устройства кэшируются и работают одинаково в браузере, в Node и на сервере — отдельный серверный код-путь не нужен.

basics.ts
import { getOS, isMobileDevice, isDesktopDevice } from 'os-detect'

getOS() // 'windows' | 'macos' | 'ios' | 'android' | 'linux' | 'chromeos' | 'unknown'
isMobileDevice() // true on iOS or Android
isDesktopDevice() // true on macOS, Windows, Linux, or ChromeOS

// All synchronous and cached — and work identically in the browser, in
// Node, and during SSR, no separate server-only code path needed.

Отличает Windows 11 от Windows 10, а не просто «Windows»

Большинство детекторов ОС смотрят только на userAgent и дальше «Windows» не идут — этот дёргает Client Hints API браузера (или os.release() в Node), чтобы узнать версию по-настоящему.

windows11.ts
import { detectIsWindows11 } from 'os-detect'

const isWin11 = await detectIsWindows11() // true only on Windows 11

// Most OS detectors stop at the userAgent string, which can't tell Windows
// 10 from 11 — this one asks the browser's own Client Hints API (or
// os.release() in Node) to actually know.

Выбор языка дизайна из ОС + форм-фактора вместе

getFormFactor() смотрит на ОС и физический размер экрана, а не на наличие сенсорного экрана — сенсорный ноутбук на Windows всё равно вернёт 'desktop', не 'tablet'.

formfactor.ts
import { getOS, getFormFactor } from 'os-detect'

if (getOS() === 'windows' && getFormFactor() === 'desktop') {
  loadFluentDesignSystem()
} else if (getOS() === 'android') {
  loadMaterialDesignSystem()
}

// getFormFactor() is driven by OS and physical screen size, not touch
// capability — a touchscreen Windows laptop still comes back 'desktop'.