LoginSignup
4
4

More than 3 years have passed since last update.

Nuxt + Typescriptでdevice毎にlayoutを分ける

Last updated at Posted at 2019-09-29

はじめに

Nuxt + Typescriptでアプリケーションを開発している際、device毎(PC, スマホ)で表示するlayoutをそれぞれ分けて作成・表示したかったため、そのために行った内容をまとめます。

環境

  • Nuxt.js 2.8.1
  • Node.js 8.11.4
  • npm 6.4.0

ディレクトリ構成

├── .nuxt
├── node_modules
├── src
│   ├── layouts
│   │   ├── pc
│   │   │   └── default.vue
│   │   └── sp
│   │       └── default.vue
│   ├── pages
│   │   ├── pc
│   │   │   └── index.vue
│   │   └── sp
│   │       └── index.vue
│   ├── server
│   │   └── index.ts
│   └── router.ts
├── nuxt.config.ts
├── package-lock.json
└── package.json

※関連するディレクトリ・ファイルのみ表示

routerをカスタマイズ

Nuxtのrouterをカスタマイズするにあたってnuxt-community/router-moduleというモジュールを利用します。
https://github.com/nuxt-community/router-module
このモジュールは独自のrouterを実装することで、Nuxtアプリケーションのroutingをカスタマイズすることを可能とします。

Use your own router.js to handle your routes into your Nuxt.js application.

router-moduleのインストール

以下のコマンドにてモジュールをインストール。

$ npm install --save @nuxtjs/router

router.tsを作成

インストールが完了したらsrcDirに独自のrouterを作成します。
今回はTypescriptでアプリケーションの開発を行っているため、router.tsを作成しました。

src/router.ts
/* eslint @typescript-eslint/no-explicit-any: 0 */
import Vue from 'vue';
import Router, { RouteConfig } from 'vue-router';
import { createRouter as createDefaultRouter } from '~~/.nuxt/defaultRouter.js';

Vue.use(Router);

const fixRoutes = (
  defaultRoutes: RouteConfig[],
  isMobile: boolean,
): RouteConfig[] => {
  const regex = isMobile ? /^\/sp\/?/ : /^\/pc\/?/;

  return defaultRoutes
    .filter((route: RouteConfig): boolean => regex.test(route.path))
    .map(
      (route: RouteConfig): RouteConfig => ({
        ...route,
        path: route.path.replace(regex, '/'),
      }),
    );
};

export const createRouter = (ssrContext: Record<string, any>): Router => {
  const defaultRouter: Record<string, any> = createDefaultRouter();
  // TODO:mobile判定は後で実装するため、一旦固定でmobile判定
  const isMobile = true;

  return new Router({
    ...defaultRouter.options,
    routes: fixRoutes(defaultRouter.options.routes, isMobile),
  });
};

router.tsではNuxtで生成されたdefaultRouter.jsを再利用することでカスタマイズしております。(defaultRouter.jsの生成方法については後述)
実装したfixRoutes関数では、引数として渡されたmobile判定情報を元にspもしくはpcディレクトリのどちらかをroutingのpathとして採用し、defaultのroute情報をベースとして新たなrouteを生成します。
それにより、device毎それぞれ別々のroutingが生成され、PCでアクセスした際は/pages/pc/を、スマホでアクセスした際は/pages/sp/を表示することが可能となります。

また、device判定の実装については後述とし、ここでは一旦固定で定義しています。

modulesの設定を追加

router.tsを作成したらnuxt.config.tsのmodulesに@nuxtjs/routerの設定を追加します。

nuxt.config.ts
// ・・・省略
const nuxtConfig: NuxtConfiguration = {
  mode: 'universal',
  srcDir: 'src/',
  // ・・・省略
  modules: [
    ['@nuxtjs/router', { fileName: 'router.ts', keepDefaultRouter: true }],
  ],
  // ・・・省略

optionsとしてはpathfileNamekeepDefaultRouterの指定が可能です。
fileNameに関してはdefault値がrouter.jsなため、今回はtsファイル(router.ts)を指定。
keepDefaultRouterはtrueを設定すると.nuxtディレクトリにdefaultRouter.jsとしてNuxtのデフォルトrouterが保持され、独自に作成したrouterからアクセスし再利用することが可能となります。

deviceの判定

routerのカスタマイズまで完了したら、次にdeviceの判定処理を実装します。
deviceの判定にはhgoebl/mobile-detect.jsというライブラリを利用しました。
https://github.com/hgoebl/mobile-detect.js

このライブラリはUserAgentをもとに、deviceの判定を行います。

mobile-detect.jsのインストール

$ npm install --save mobile-detect

deviceの判定処理実装

インストールが完了したら最後にTODOとしていたdeviceの判定処理を実装します。

src/router.ts
// ・・・省略
import MobileDetect from 'mobile-detect';

Vue.use(Router);

const isMobile = (ssrContext: Record<string, any>): boolean => {
  const ua = ssrContext
    ? ssrContext.req.headers['user-agent']
    : window.navigator.userAgent;

  const md: MobileDetect = new MobileDetect(ua);

  return !!md.mobile();
};

// ・・・省略

export const createRouter = (ssrContext: Record<string, any>): Router => {
  const defaultRouter: Record<string, any> = createDefaultRouter();

  return new Router({
    ...defaultRouter.options,
    routes: fixRoutes(defaultRouter.options.routes, isMobile(ssrContext)),
  });
};

isMobile関数を実装し、固定でtrueを定義していたisMobile変数と置き換えます。
isMobile関数の中ではmobile-detectライブラリを用いたmobile判定が行われており、MobileDetectインスタンス生成の際にUserAgentを渡すことで判定が可能になります。(mobile判定の他にもtabletやos、iPhoneであるかどうかなど様々な判定が可能)

以上によりUserAgentの情報を元にdevice毎それぞれlayoutを分けることが可能となりました。

参考にしたサイト

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4