React Tour

ルーティング

Next.jsと似ていますが、Vikeで新しくページを作るには +Page.jsx というファイルを作成します。

// /pages/index/+Page.jsx
// Environment: browser and server
 
import React from "react";
import { Counter } from "../components/Counter";
 
export { Page };
 
function Page() {
  return <>
    This page is rendered to HTML and interactive: <Counter />
  </>;
}

デフォルトでは、Vikeはファイルシステムルーティングを行います。

FILESYSTEM                  URL
/pages/index/+Page.jsx      /
/pages/about/+Page.jsx      /about

また、特定の文字列(例えば/movies/@id)や作成した関数をもとにして、ページのルーティングを定義することもできます。 自分で作成した関数をもとにルーティングを規定できるのは、柔軟性が高く、かゆいところにも手の届くVikeの特徴です。

// /pages/index/+route.js
 
// ルーティング用の関数を作るには `+route.js` を作成します。
// `+route.js` は、ルーティング対象である `+Page.jsx` と同じディレクトリに設置してください。
 
// Route Function
export default pageContext => pageContext.urlPathname === '/';
 
// `+route.js` ファイルを作成しなかった場合は、Vikeは通常通りにファイルシステムルーティングを行います。
 

レンダリングの制御

Next.jsとは異なり、Vikeではページのレンダリングを開発者自身が制御します。

// /renderer/+onRenderHtml.jsx
// Environment: server
 
import ReactDOMServer from "react-dom/server";
import React from "react";
import { escapeInject, dangerouslySkipEscape } from "vike/server";
 
export { onRenderHtml };
 
async function onRenderHtml(pageContext) {
  const { Page, data } = pageContext;
  const viewHtml = ReactDOMServer.renderToString(
    <Page {...data} />
  );
 
  const title = "Vite SSR";
 
  return escapeInject`<!DOCTYPE html>
    <html>
      <head>
        <title>${title}</title>
      </head>
      <body>
        <div id="page-view">${dangerouslySkipEscape(viewHtml)}</div>
      </body>
    </html>`;
}
// /renderer/+onRenderClient.jsx
// Environment: browser
 
import ReactDOM from "react-dom/client";
import React from "react";
 
export { onRenderClient };
 
async function onRenderClient(pageContext) {
  const { Page, data } = pageContext
  ReactDOM.hydrateRoot(
    document.getElementById("page-view"),
    <Page {...data} />
  );
}

このアプローチにより、任意のツール(Redux、GraphQL、Service Worker、Preactなど)を簡単かつ自然に統合することが可能です。

また、onRenderClient.jsx および onRenderHtml.jsx ファイルは /renderer/ ディレクトリにあらかじめ作成されています。これにより、VikeはonRenderHtml() および onRenderClient() フックをすべてのページに適用します。

つまり、Vikeでは詳細なレンダリングの制御も可能であり、そしてその必要がない場合は、+Page.jsx ファイルを定義するだけで新しいページを作成することができます(+route.js ファイルはオプションです)。

さらに /renderer/ 内のファイルは上書き可能です。たとえば、Vueのような全く異なるUIフレームワークを使用して、 一部のページを異なる方法でレンダリングするための onRenderHtml() および onRenderClient() フックを上書きすることもできます。

データの取得

次に、データの取得方法を見てみましょう。

// /pages/star-wars/movie/+Page.jsx
// Environment: browser and server
 
import React from "react";
 
export { Page };
 
function Page(data) {
  const { movie } = data;
  return <>
    <h1>{movie.title}</h1>
    <p>Release Date: {movie.release_date}</p>
    <p>Director: {movie.director}</p>
  </>;
}
// /pages/star-wars/movie/+route.js
// Environment: server
 
// Route String
export default "/star-wars/@movieId";
// /pages/star-wars/movie/+data.js
// Environment: server
 
import fetch from "node-fetch";
 
export async function data(pageContext) {
  // `/star-wars/@movieId` のルートパラメータは `pageContext.routeParams` で利用可能
  const { movieId } = pageContext.routeParams;
 
  // デフォルトでは、`+data.js` ファイルはサーバーサイドでのみロードおよび実行されます。
  // つまり、ここでSQL/ORMクエリを使用できます。
  const response = await fetch(`https://star-wars.brillout.com/api/films/${id}.json`);
  let movie = await response.json();
 
  // 以前に定義したレンダリングおよびハイドレーション関数は `pageContext.data` を
  // ルートReactコンポーネント `Page` に渡します。ここでそれを定義します。
  return {
    movie
  };
}

これでツアーは終わりですが、Vikeのインターフェースのほとんどを既にお見せしています。 Vikeは柔軟性がありながらシンプルに使えるフレームワークです!

$ npm init vike
Run $ npm init vike to scaffold a new Vike app. Or add Vike to your existing Vite app by following the instructions here.