Laravel+TypeScript+Reactで開発環境を構築する

JavaScript,Laravel,PHP,React,TypeScript,技術JavaScript,Laravel,React,TypeScript,備忘録

こんばんわ。

家電量販店に行くとキーボード、マウス売り場でテンションが上がってしまうどうもみけぽんです。

 

業務では新しいフロントエンド技術に触る機会があまりないので、個人開発では新しめの技術に意識して触るようにしています。

LaravelとTypeScriptを組み合わせた開発環境を構築しようとして結構詰まってしまったので、備忘録で残しておこうと思います。

 

 

Laravel+TypeScript+Reactで開発環境を構築する

前提

下記は既にインストールしているものとします。

  • Laravel8
  • node.js
  • TypeScript

 

TypeScriptは予め下記コマンドなどでインストールしておいてください。

$ npm install -g typescript

 

globをダウンロードする

Laravelプロジェクト直下にあるwebpack.mix.jsを修正するのですが、デフォルトだとtsディレクトリのファイル一つにつきチェーンメソッドで連結しなければなりません。

mix.ts('resources/assets/js/app.js', 'public/js')
    .ts('resources/assets/js/hoge.js', 'public/js')
    .ts('resources/assets/js/fuga.js', 'public/js')
    .sass('resources/assets/sass/app.scss', 'public/css');

これだと分かりづらい上に冗長になってしまうので、globをインストールしてtsディレクトリ以下をワイルドカード指定できるようにします。

 

$ npm i -D glob

globをnpmコマンドでダウンロードします。

 

const mix = require('laravel-mix');

const glob = require('glob');

glob.sync('resources/ts/**/*').map(function (file) {
    mix.ts(file, 'public/js')
});

glob.sync('resources/sass/**/*.scss').map(function (file) {
    mix.sass(file, 'public/css')
});

globをダウンロードすることによって、tsディレクトリ以下をワイルドカード指定可能になりました。

上記の記述でtsとsassディレクトリ以下の全ファイルはそれぞれpublic/jspublic/cssにコンパイルされます。

 

Reactをダウンロードする

$ npm i -D react react-dom @types/react @types/react-dom

Reactと関連モジュールをダウンロードします。

 

ダウンロードしたモジュールのインストール

$ npm install

npmコマンドでモジュールをインストールします。

 

$ npm run watch

ルートディレクトリにあるpackage.jsonに記述のあるコマンドを実行すると途中でエラーになりますが、package.jsonにtypescriptやsassが追加されます。

 

"devDependencies": {
    "@babel/preset-react": "^7.13.13",
    "@types/react": "^17.0.21",
    "@types/react-dom": "^17.0.9",
    "axios": "^0.21",
    "bootstrap": "^4.6.0",
    "glob": "^7.1.7",
    "jquery": "^3.6",
    "laravel-mix": "^6.0.6",
    "lodash": "^4.17.19",
    "popper.js": "^1.16.1",
    "postcss": "^8.1.14",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "resolve-url-loader": "^3.1.2",
    "sass": "^1.32.11",
    "sass-loader": "^11.0.1",
    "ts-loader": "^9.2.5",
    "typescript": "^4.4.3"
}

package.jsonを開くとダウンロードしたモジュールがインストールされていることが分かります。

 

TypeScriptの設定をする

$ tsc --init --jsx react

上記コマンドの実行でプロジェクトディレクトリにtsconfig.jsonファイルが作成されます。

 

"target": "es5",
↓
"target": "es6"

ちなみに私の場合はtargetの箇所だけ変更しています。

 

Reactの動作確認をする

import React from 'react'
import ReactDOM from 'react-dom'

const App = () => {
    const title: string = 'hoge hoge'
    return (
        <h1>{title}</h1>
    )
}

ReactDOM.render(
    <App />,
    document.getElementById('app')
)

resources/ts/hoge.tsxを作成し、上記の内容で保存します。

globをインストールして'resources/ts/**/*'と記載しているため、resources/ts内の全ファイルはコンパイルの対象になります。

 

$ npm run dev

npmコマンドでresources/ts内のTypeScriptファイルをコンパイルすると、public/js内にhoge.jsが生成されます。

 

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="csrf-token" content="{{ csrf_token() }}">
</head>
<body>
<div id="app"></div>

<!-- Scripts -->
<script src="{{ mix('js/hoge.js') }}"></script>
</body>
</html>

viewファイルにidがappのdiv要素を作成し、public/jsにコンパイルされたhoge.jsをmix関数で読み込みます。

hoge hoge」と表示されれば成功です。

 

グローバル関数を定義する

function message(name: string): void {
    console.log(name + 'さん、こんにちわ!');
}

例えば上記のようなtest.tsファイルでfunction messageを定義した場合、コンパイル後のjsファイルを見てみましょう。

 

/******/ (() => { // webpackBootstrap
/******/ "use strict";
var __webpack_exports__ = {};
/*!*******************************!*\
  !*** ./resources/ts/test.ts ***!
  \*******************************/

function message(name) {
  console.log(name + 'さん、こんにちわ!');
}
/******/ })()
;

function messageがクロージャ―内で定義されてしまっています。

 

<!-- Scripts -->
<script src="{{ asset('js/app.js') }}"></script>
<script src="{{ mix('js/test.js') }}"></script>
<script>
    message('山田');
</script>
</body>
</html>

この状態だとクロージャ―の外で呼び出すことが出来ず、viewファイルでmessage関数を呼び出すとfunction is not definedでエラーになります。

 

function message(name: string): void {
    console.log(name + 'さん、こんにちわ!');
}

(window as any).message = message;

よってtsファイルの末尾でグローバル関数として定義します。

 

/******/ (() => { // webpackBootstrap
/******/ "use strict";
var __webpack_exports__ = {};
/*!******************************!*\
  !*** ./resources/ts/test.ts ***!
  \******************************/

function message(name) {
  console.log(name + 'さん、こんにちわ!');
}

window.message = message;
/******/ })()
;

コンパイル後のjsファイルでもmessage関数がwindow.messageに代入され、グローバルに設定されていることが分かります。

これでviewファイルから関数を呼び出せるようになりました。

 

参考サイト