UAParser.jsとはユーザーエージェント(User-Agent)からブラウザやエンジン、OS、CPU、デバイスの種類/モデルを検出するJavaScriptライブラリです。
今回はReactおよびNext.jsの環境でUAParser.jsを利用したモバイル判定の方法を紹介します。
なお、Chrome の User-Agent 文字列削減に関する最新情報の発表からもわかるように、ユーザーエージェントの仕様は今後変わっていくと考えられます。
ですので、ユーザーエージェントに関する情報は定期的にウォッチしておくことをオススメします。
UAParser.jsの利用方法
UAParser.jsのインストール方法は以下の通りです。
$ yarn add ua-parser-js
### TypeScript環境の場合
$ yarn add -D @types/ua-parser-js
new UAParser([uastring][,extensions])
もしくはUAParser([uastring][,extensions])
で作成したコンストラクタを参照することで、ユーザーエージェントからデバイスなどの情報を取得できます。
以下では、ChromeのDevToolsでブラウザをiPhoneにエミュレートした際の結果について紹介します。
UAParser([uastring][,extensions])
を利用したコードは以下の通りです。
import { FC, useEffect } from "react";
import { UAParser } from "ua-parser-js";
const App: FC = () => {
useEffect(() => {
const uaParserResult = UAParser(window.navigator.userAgent);
console.log(uaParserResult);
// {
// "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1",
// "browser": {
// "name": "Mobile Safari",
// "version": "13.0.3",
// "major": "13"
// },
// "engine": {
// "name": "WebKit",
// "version": "605.1.15"
// },
// "os": {
// "name": "iOS",
// "version": "13.2.3"
// },
// "device": {
// "vendor": "Apple",
// "model": "iPhone",
// "type": "mobile"
// },
// "cpu": {}
// }
console.log(uaParserResult.device.type);
// mobile
}, []);
return <>App</>;
};
export default App;
new UAParser([uastring][,extensions])
を利用したコードは以下の通りです。
import { FC, useEffect } from "react";
import { UAParser } from "ua-parser-js";
const App: FC = () => {
useEffect(() => {
const userAgent = window.navigator.userAgent;
// Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1
const uaParserInstance = new UAParser().setUA(userAgent);
// UAParser {getBrowser: ƒ, getCPU: ƒ, getDevice: ƒ, getEngine: ƒ, getOS: ƒ, …}
console.log(uaParserInstance.getDevice());
// {
// "vendor": "Apple",
// "model": "iPhone",
// "type": "mobile"
// }
console.log(uaParserInstance.getDevice().type);
// mobile
}, []);
return <>App</>;
};
export default App;
UAParser.jsの活用例: モバイルとPCで適用するCSSクラスを分ける
Next.jsの環境において、UAParser.jsを利用してモバイルとPCで適用するCSSクラスを分ける方法について紹介します。
具体的なコードは以下の通りです。
pages/index.tsx
import * as React from "react";
import type { GetServerSideProps, NextPage } from "next";
import cx from "classnames";
import styles from "../styles/Home.module.css";
import App from "../src/components/App";
import { getIsMobile } from "../src/lib/environmentDetector";
type Props = {
isMobile: boolean;
};
const HomePage: NextPage<Props> = ({ isMobile }) => {
return (
<div className={cx(styles.container, isMobile ? styles.mobile : styles.pc)}>
<main className={styles.main}>
<App isMobile={isMobile} />
</main>
</div>
);
};
export const getServerSideProps: GetServerSideProps = async (ctx) => {
// 行末の"!"は、Non-null assertion operator と呼ばれるもの
const userAgent = ctx.req.headers["user-agent"]!;
const isMobile = getIsMobile(userAgent);
return {
props: {
isMobile
}
};
};
export default HomePage;
src/components/App.tsx
import { FC } from "react";
type Props = {
isMobile: boolean;
};
const App: FC<Props> = ({ isMobile }) => {
return <>This Device is {isMobile ? "Mobile" : "PC"}</>;
};
export default App;
src/lib/environmentDetector.ts
import { UAParser } from "ua-parser-js";
export const getIsMobile = (userAgent: string): boolean => {
const type = new UAParser().setUA(userAgent).getDevice().type;
return type === "mobile";
};
styles/Home.module.css
.container {
padding: 0 2rem;
}
.main {
min-height: 100vh;
padding: 4rem 0;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.mobile {
background-color: lightblue;
}
.pc {
background-color: lightgreen;
}
上記のコードのロジックは以下の通りです。
- getServerSidePropsでリクエストヘッダからユーザーエージェントを取得
- 取得したユーザーエージェントからコンストラクタを生成してモバイル判定を行う
- getServerSidePropsでモバイル判定の結果が保存されたisMobileを返す
- PageでisMobileをPropsとして受け取る
- isMobileの真偽値に応じて付与するCSSクラスを変更する
なお、付与するCSSクラスの出しわけにはclassnamesを利用しています。
CSSクラスの出し分け方法の詳細解説は【React】classNameでよく使う定義方法(複数クラス、条件付きクラス)で紹介しています。
さいごに
Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!