前提条件
予めnode.jsをインストールしておいてください。
npmの初期化とモジュールのインストール
適当なプロジェクトディレクトリを作ったらnpm initでpackage.jsonを作ります。
$ npm init -y次にWebpack関係のモジュールからインストール
$ npm i -D webpack webpack-cli typescript ts-loaderReact関係をインストール
$ npm i -S react react-domTypeScriptを使用するので定義ファイルもインストールします。
$ npm i -D @types/react @types/react-dompackage.jsonの確認と編集
2020年8月現在インストールされるバージョンは次のようになります。
また、scripts部分に追加して、webpackを実行できるようにします。
{"scripts": { "build": "webpack --mode=production", "start": "webpack -w --mode=development"},"devDependencies": { "ts-loader": "^8.0.2", "typescript": "^4.0.2", "webpack": "^4.44.1", "webpack-cli": "^3.3.12"},"dependencies": { "@types/react": "^16.9.46", "@types/react-dom": "^16.9.8", "react": "^16.13.1", "react-dom": "^16.13.1"},"private": true}TypeScriptの設定ファイル
TypeScriptの設定を記述するファイルを作成します。
$ touch tsconfig.json中は次のようにします。必要に応じて追記してください。
{ "compilerOptions": { "sourceMap": true, "target": "es5", "module": "es2015", "strict": true, "strictNullChecks": true, "noUnusedLocals": true, "noUnusedParameters": false, "noImplicitReturns": true, "moduleResolution": "node", "esModuleInterop": true, "allowSyntheticDefaultImports": true, "jsx": "react", "lib": ["es2020", "dom"] }}Webpackの設定ファイル
次はWebbpackの設定ファイルを作成します。
$ touch webpack.config.js今回は編集ファイルをpublic_html/assets/srcディレクトリにいれて、書き出したディレクトリはpublic_html/assets/distに設定します。
プロジェクトのディレクトリ構成によって変更してください。
const path = require('path')const assetsDir = path.resolve(__dirname, 'public_html/assets');
module.exports = { entry: assetsDir + "/src/app.tsx", output: { path: assetsDir + "/dist", filename: 'app.js' }, module: { rules: [ { test: /\.tsx?$/, use: "ts-loader", }, ], }, resolve: { extensions: [".ts", ".tsx", ".js"] },};これでWebpackの準備は完了です。
ビルドしてみる
簡単なファイルを作ってjsにビルドできるか確認してみましょう。
webpack.config.jsで設定したディレクトリを作成しましょう。
$ mkdir -p public_html/assets/srcエントリーポイントで指定したファイルの作成。
$ touch public_html/assets/src/app.tsxファイルを次のように編集します。
import React from 'react'import { render } from 'react-dom'
const App = () => { return ( <div> <div>Hello React</div> </div> )}
render(<App/>, document.querySelector('#app'))ビルドを実行します。
$ npm run buildstartを実行することでファイルを監視して、編集するたびに自動的にビルドを実行することもできます。
$ npm run startここまで設定できているのであれば、public_html/assets/distディレクトリにapp.jsが生成されているはずです。
次にindex.htmlを作成し、ビルドしたapp.jsを実行してみます。
<!DOCTYPE html><html lang="ja"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>部分React</title></head><body> <div id="app"></div> <script src="assets/dist/app.js" charset="utf-8"></script></body></html>ブラウザでindex.htmlを開いてください。
「Hello React」が表示されていれば成功です。
複数のコンポーネントを扱う
これで好きなディレクトリにソースを配置したり、書き出したりということはできるようになりましたが、ルートのAppコンポーネントを表示しているだけなのでSPAと変わらないですね。
複数のコンポーネントをhtmlで自由に表示したいことがあると思います。
componentsディレクトリを作り表示したいコンポーネントを作成しましょう。
ここではHeader.tsxとFooter.tsxを作成します。
import React from 'react'
const Header = () => { return ( <header> <h1>Header</h1> </header> )}
export default Headerimport React from 'react'
const Footer = () => { return ( <footer> <p>Footer</p> </footer> )}
export default Footerapp.tsxを次のように編集します。
import React from 'react'import { render } from 'react-dom'import Header from './components/Header'import Footer from './components/Footer'
const headerDOM = document.getElementById('header')if (headerDOM !== null) render(<Header />, headerDOM)
const footerDOM = document.getElementById('footer')if (footerDOM !== null) render(<Footer />, footerDOM)これでhtmlファイルでidにheaderやfooterを指定することでコンポーネントを表示することができるようになります。
<body> <div id="header"></div> <div id="footer"></div> <script src="assets/dist/app.js" charset="utf-8"></script></body>React本体をWebpackしない
実際のソースコードは10Kでも、ビルドしたファイルはReact本体(大きいのはReactDOM)を含むので100Kくらいになっていると思います。
SPAとしてならすべて一つのファイルにまとめるのが一般的ですが、この記事の用途だと作成したソースだけビルドしたいとうケースもあると思います。
その場合webpack.config.jsのexternalsにReactとReactDOMを指定します。
const path = require('path')const assetsDir = path.resolve(__dirname, 'public_html/assets');
module.exports = { entry: assetsDir + "/src/app.tsx", output: { path: assetsDir + "/dist", filename: 'app.js' }, module: { rules: [ { test: /\.tsx?$/, use: "ts-loader", }, ], }, resolve: { extensions: [".ts", ".tsx", ".js"] }, externals: { 'react': 'React', 'react-dom': 'ReactDOM', }};この場合、app.jsを読み込む前にReactとReactDOMは別途読み込む必要があります。
<script src="https://unpkg.com/react@16/umd/react.production.min.js" crossorigin></script><script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js" crossorigin></script><script src="assets/dist/app.js" charset="utf-8"></script>React外の関数にアクセスする
すでに運用しているサイトの場合はなんらかのJavaScriptの処理だったりjQueryのプラグインが入っていると思います。
Reactから外部のJavaScriptの関数を実行したいケースもあると思います。
既存のJavaScriptの修正
既存のJavaScriptもそのまま使えるわけではなく、修正の必要があります。
JavaScriptにはwindowというグローバルで使用できるオブジェクトがあるので、Reactで使用したい処理をここに登録しておきます。
window.hoge = function() { // ここに処理を書く console.log('外部のJS');}Reactの修正
次にReact(TypeScript)で実行できるようにインターフェイスを作成します。
interface IWindow extends Window { hoge: () => void}declare const window: IWindowexport default windowあとは使用したいコンポーネントで次のように記述すれば実行できます。
import window from '../../Window'
window.hoge()windowに登録しておけばどこからでもアクセスできますよという例でした。
参考サイト
最新版TypeScript+webpack 4の環境構築まとめ(React, Vue.js, Three.jsのサンプル付き) - ICS MEDIA
既存のウェブサイトに React を追加する
