概要
Nuxt.js は基本 pages
ディレクトリをリネームできない。
なのでユーザーエージェントやサブドメインで View のパスを切り替えるといった Web Application Framework でたまに欲しくなる機能が Nuxt の基本機能だけでは実現できない。
それをモジュールを用いて実現したのでメモ :pencil:
pages
├── PC
└── MOBILE
こんな感じで PC とスマートフォンを別のディレクトリに置いた上で、URL はそのままにする。
モジュール
モジュール とは Nuxt のコア機能を拡張する仕組みで、ビルド後の Nuxt が必要とする機能を差し込むことができる。
Nuxt Router Module
Nuxt Router Module は Nuxt によって生成される router.js
をまるっと差し替えることができるモジュールであり、これにより自分でカスタムした router を使えるようになる。
また、keepDefaultRouter
オプションを用いるとデフォルトの pages
ディレクトリのツリー構造によるルーティングを defaultRouter.js
として残しておくことができる。
keepDefaultRouter
オプションが追加されたのはこちらのPR → #16 Feature: add option keepDefaultRouter
感謝です
モジュールの追加
$ yarn add @nuxtjs/router
or
$ npm install @nuxtjs/router
でインスコ
Nuxt の設定
nuxt.config.js{
modules: [
['@nuxtjs/router', { keepDefaultRouter: true }]
],
},
Nuxt Router Module の README 通り。
pages ディレクトリを分割する
$ tree pages -L 1
pages
├── PC
└── MOBILE
こんな感じでディレクトリを分ける。Nuxt のデフォルトルーティングと区別するために大文字にしているが、開発者にわかりやすくしているだけなので、別に小文字でも構わない。
カスタム Router の作成
router.jsexport const fixPath = (path, isMobile) => {
const regex = isMobile ? /^\/MOBILE\/?/ : /^\/PC\/?/;
return path.replace(regex, '/');
};
export const fixName = (name, isMobile) => {
const regex = isMobile ? /^MOBILE-?/ : /^PC-?/;
return name.replace(regex, '') || 'index';
};
export const fixRoutes = (defaultRoutes, isMobile) => {
const regex = isMobile ? /^\/MOBILE\/?/ : /^\/PC\/?/;
return defaultRoutes.filter(route => regex.test(route.path)).map(route => ({
...route,
path: fixPath(route.path, isMobile),
name: fixName(route.name, isMobile),
}));
};
export const createRouter = (ssrContext, createDefaultRouter) => {
const defaultRouter = createDefaultRouter(ssrContext);
const isMobile = detectMobile(ssrContext);
return new Router({
...defaultRouter.options,
routes: fixRoutes(defaultRouter.options.routes, isMobile),
});
};
このようにして fixRoutes
内部で defaultRouter.options.routes
の中身を一つずつ書き換えている。
このとき、 SPA によるクライアントの遷移時は ssrContext
が undefined
になることに気をつける。
こうしておくと
<nuxt-link :to="{ name: 'users-id', params: { id: userId } }">hoge</nuxt-link>
こう書いたときに、 pages/PC/users/_id.vue
/ pages/MOBILE/users/_id.vue
へのルーティングとなり、URL も /users/:id
となる。
まとめ
カスタムすればするほど、 設定より規約
という Nuxt の基本思想から離れていくので、カスタムする際に独自の実装をするのではなく、上記のサンプルコードで PC・MOBILE とハードコーディングしてるところも pages
直下階層の大文字ディレクトリ名を抜き出すようにするなどして、新しい規約を追加するような実装にするといいのかもしれない。