LoginSignup
4
7

More than 1 year has passed since last update.

【laravel】laravel+Reactを使ってSPAにしてみる

Last updated at Posted at 2021-09-06

初書:2021/09/06
mac : 11.5.2
php:v8.0.6
laravel:v8.57.0

前書き

最近Reactを知ったのでせっかくならLaravelでも使ってみよう、というメモ。

前提

Laravelインストール済み。
素のPHPしか触ってなかった人がlaravelを触ってみる - Qiita

インストール

まずはuiをインストール

% composer require laravel/ui

その後はuiをreactに変更

% php artisan ui react

インストールとmix

% npm install && npm run dev

もし、Please run Mix again.と言われた場合はもう一度npm run devします。

以上

Typescriptにする

ReactといえばTypescript…と、勝手に思ってるので、Typescriptで書けるように追加していく。

インストール

まずは必要なものをインストール

% npm install --save-dev ts-loader typescript react-router-dom @types/react @types/react-dom @types/react-router-dom

react-router-dom@types/react-router-domはSPAを作る場合。laravel側でルーティングする場合は不要。
でもこの記事では使います。

tsconfig.jsonの設定

% npx tsc --init

これでtsconfig.jsonが生成される。
設定は好みだが、一応今設定しているものを置いておく。

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "lib": [
      "ES2020",
      "DOM",
    ],
    "jsx": "react-jsx",
    "module": "AMD",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  },
  "include": [
    "resources/ts/**/*"
  ]
}

targetES2020を選択。頻繁なアプデを好まない層(IEとか古いiOSとか)がこないサイトなら最新のものでいいと思う。
moduleAMDを選択した。es2020とかとの違いはあんまり分かってない。(非同期で読み込める点?でものちに1ファイルにまとめる・・・。)

各ブラウザの対応状況:ECMAScript 2016+ compatibility table

ページを作成する

今回はメインページとサブページを作る。
laravelでtsを置くのは基本的にresourcesディレクトリなので、この下に作成する。

resources/ts/app.tsx
import ReactDOM from "react-dom";
import { BrowserRouter, Route, Switch } from "react-router-dom";

import main from "./main";
import sub from "./sub";

function App() : JSX.Element {
    return (
        <BrowserRouter>
            <Switch>
                <Route exact path="/" component={main} />
                <Route exact path="/sub" component={sub} />
            </Switch>
        </BrowserRouter>
    );
}

ReactDOM.render(<App />, document.getElementById("root"));
resources/ts/main.tsx
import React from "react";
import { Link } from "react-router-dom";

const element = (): JSX.Element => {
  return (
    <div>
      <p>メインページです。</p>
      <Link to="/sub">サブページへ</Link>
    </div>
  );
};

export default element;
resources/ts/sub.tsx
import React from "react";

const element = (): JSX.Element => {
    return <p>サブページです。</p>;
};

export default element;

React、最近は関数型の書き方の方が良いって聞いたので関数型を使ってみた。

基盤となるapp.tsxとページを表示するmainとsubを作成。
これが出来れば、それを表示するためのwelcome.blade.phpを変更する

resources/views/welcome.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Laravel</title>
    </head>
    <body class="antialiased">
        <div id="root">
        </div>
    </body>
        <script src="{{ mix('js/app.js') }}"></script>
</html>

表示用のdivと、読み込みスクリプトがあれば後は自由。
ページは以上

laravel mixを使う

そのままではapp.jsなるファイルは存在していないので、作成する。
普通にインストールしていると、webpack.mix.jsが既に存在しているので、これを編集する。

webpack.mix.js
const mix = require('laravel-mix');

mix.js('resources/ts/app.tsx', 'public/js')
    .react()
    .webpackConfig({
        module: {
            rules: [
                {
                    test: /\.tsx?$/,
                    loader: 'ts-loader',
                    exclude: /node_modules/,
                },
            ],
        },
        resolve: {
            extensions: ['*', '.js', '.jsx', '.ts', '.tsx'],
        },
   })
   .version();

react()が何するのかよく分かってない。誰か教えてください(他人頼り)

これで、npm run devを実行すると、先ほど作ったapp.tsx関連がapp.jsにまとめられる。

一度アクセスしてみる

これで一度アクセスしてみる。
php artisan serveでサーバーを立て、http://127.0.0.1:8000/にアクセスすると、先程のメインページですが表示されているはず。
また、サブページへを押すと、http://127.0.0.1:8000/subにアクセスされ、サブページですが表示される。

一見これでいいように見えるが、直接http://127.0.0.1:8000/subにアクセスすると、laravel側からurlが存在していないと言われる。
これは、subページがReact内だけで作成されているだけのため。

この先は仕様次第だが、今回はReact側でアクセス処理を任せることにする

全てのアクセスをapp.tsxにまとめる

アクセスはroutes/web.phpで管理しているので、ここを変える

routes/web.php
Route::get('/{any}', function () {
    return view('welcome');
})->where('any', '.*');

元々あった//{any}に変え、条件を全てに変更した。
where文があるのは、/anyに含まれるようにするため。

これで、直接http://127.0.0.1:8000/subにアクセスしても、サブページですが表示される。

終わりに

この後ブラウザとサーバー側でデータのやりとりをするため、APIの設定等をしないといけないが、長くなりそうなので今回は一旦ここで切り上げ。
まだ試行錯誤段階なので、やり方異なってたり、よりいい方法とかあれば更新する…かも。

参考サイト

React.JS + Laravel 8 + MySQL + API REST でCRUDを作ってみた。

【環境構築】LaravelでReactとTypescriptを使う方法 - Qiita

【Typescript×React】tsconfig.jsonの設定項目を詳しく紹介 - Qiita

laravel-mixでtypescript + reactをビルドする - Qiita

4
7
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
7