今回はLaravelでreactとTypescriptを使えるように開発環境を構築していきます。
初学者なので2週間ぐらいかかってしまいましたが誰かの参考になれば幸いです。
#開発環境
Docker 20.10.5
docker-compose 1.28.5
php 7.3
laravel 6.20.26
Composer 2.0.8
MySQL 8.0
nginx 1.15.12-alpine
Dockerを使っていますがDockerの環境構築は省略させていただいてコンテナ内でlaravelをインストールするところから始めます。
#Laravel&Reactの環境を整える
はじめにappコンテナに入りLaravelをインストールします。
# composer create-project --prefer-dist "laravel/laravel=6.*"
続いてLaravel/uiをインストール。 最新版のLaravel/uiをインストールするとLaravel6ではエラーが出るのでバージョン指定をしています。
# composer require laravel/ui:^1.0 --dev
Reactのスカフォールドをインストール。ついでに認証機能も追加しました。
# php artisan ui react --auth
webコンテナに入りnpmでインストールとビルドをします。(Dockerfileでnodeの設定済み)
# npm install & npm run dev
ここまででローカルサーバーにアクセスしたらちゃんとLaravelのwelcome.blade.phpのビューが表示されていたら成功です。
#Laravel Mixを用いてTypescriptの環境を構築する
webコンテナに入りnpmコマンドでTypescriptで必要なパッケージをインストールします。
ついでにreact-router-domもこのタイミングでインストール。
# npm install ts-loader typescript react-router-dom @types/react @types/react-dom @types/react-router-dom --save-dev
### webpack.mix.jsを編集 TypeScriptとSCSSでビルドできるようにwebpack.mix.jsを編集します。
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.ts('resources/ts/index.tsx', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
.version();
reactをインストールしているのでデフォルトではおそらくmix.react()になっていると思いますがtypescriptをビルドするのでmix.ts()に変更します。
また、.version()を追加しておかないとnpm run dev
をしてもキャッシュが残っていて変更が反映されないことがあるので一応記述します。
tsconfig.jsonを作成
webコンテナ内で以下のコマンドを実行してtsconfig.jsonを作成します。
./node_modules/.bin/tsc --init
オプションが多いので適宜確認するしかないかと... 地味にエラーがよく出るのでエラー内容確認して適宜修正しました。
{
"compilerOptions": {
"outDir": "./built/",
"sourceMap": true,
"strict": true,
"noImplicitReturns": true,
"noImplicitAny": true,
"module": "es2015", //フロント使用予定なのでcommonjsは使用しません
"jsx": "react", // tsxファイルをjsxやjsにコンパイルする際の出力の形式を指定する
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"moduleResolution": "node",
"target": "es6",
"lib": [
"es2016",
"dom"
],
"allowSyntheticDefaultImports": true // エクスポートしないモジュールからのインポートを許可する。これでtypescriptでreactをインポートするときにimport React from 'react';を使えるようになる
},
"include": [
"resources/ts/**/*" // TypeScriptのソース配置場所
]
}
#tsxファイルを作成して表示されるか確認
tsxファイルが正しく表示されるか確認します。
まず、welcome.blade.phpを以下のように編集します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<link rel="stylesheet" href="{{ mix('css/app.css') }}" />
</head>
<body>
<div id="app"></div>
</body>
<script src="{{ mix('/js/index.js') }}"></script>
</html>
次にresources配下にtsフォルダを作成し、その中にindex.tsxを作成します。
index.tsxは以下のように記述してください。
import React from 'react';
import ReactDOM from 'react-dom';
const App: React.FC = () => {
return (
<div>
<p>こんにちは</p>
</div>
)
}
if (document.getElementById('app')) {
ReactDOM.render(<App />, document.getElementById('app'));
}
そしてもう一度npm run dev
を実行しましょう。
# npm run dev
このままローカルサーバーで.index.tsxが表示されればいいのですが、僕の場合はTypeError: loaderContext.getOptions is not a function
というエラーが出ていました。
これはlaravelのバージョン(今回は6系を使用)に対してts-loaderのバージョンが新しすぎるために出るエラーのようです。
ts-loaderを一度アンインストールして古いバージョンを入れましょう。
# npm uninstall ts-loader
# npm install ts-loader@8.2.0 --save-dev
これで最後にもう一度npm run dev
を実行しましょう。
# npm run dev