TL;DR
create-react-app(以下,CRA)で生成したプロジェクトでESNext構文のデコレータを利用します.CRAではejectすることで内部の設定ファイルを編集することができますが,それはCRAを利用しないのと同義です.一方,CRAでデコレータを利用するためには隠蔽された内部設定を書き換える必要があります.本稿はejectせずにデコレータを有効にする手段を記します.具体的には次の2通りの手段で解決できます.
- customize-craとreact-app-rewiredを利用して,内部設定を書き換えます.
- プロジェクトにTypeScriptを採用します.その場合,
tsconfig.json
に"experimentalDecorators": true
を記載するだけです.
CRAのインストール〜プロジェクト作成
本稿ではyarn
を利用します.まずcreate-react-app
コマンドを利用できるようにします.
インストール後,CRAでプロジェクトを生成します.TypeScriptプロジェクトの場合は--typescript
オプションをつけて実行します.
yarn global add create-react-app
create-react-app hello-decorators
cd hello-decorators
設定を書き換える(JavaScript)
customize-craとreact-app-rewiredとプラグインのインストール
書き換えに必要なツールとデコレータを有効にするためのBabelプラグインをインストールします.
yarn add --dev customize-cra react-app-rewired @babel/plugin-proposal-decorators
package.jsonの編集
package.json
内の実行コマンドを編集します.react-scripts
をreact-app-rewired
に変更します.eject
の行はそのままにしておきます.
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
config-overrides.jsを作成
プロジェクトルート下にconfig-overrides.js
を以下の内容で作成します.
ここで内部設定の修正内容を記載します.
const { override, addDecoratorsLegacy } = require('customize-cra')
// Adds legacy decorator support to the Webpack configuration.
module.exports = override(addDecoratorsLegacy())
確認
作業は以上になります.
実際にデコレータが利用可能か確認します.App.js
を編集してデコレータを記載します.
保存後,yarn start
で開発サーバを起動してください.
import React from 'react'
import './App.css'
// Decorator that passes on a 'message' property to a class.
const addMessage = (str) => (component) => {
component.prototype.message = str
}
@addMessage('Hello world!')
class DecoratorTest extends React.PureComponent {
render() {
return <div>{ this.message }</div>
}
}
function App() {
return (
<div className="App">
<header className="App-header">
<DecoratorTest />
</header>
</div>
)
}
export default App
yarn start
Hello world!
が表示されれば無事完了です.
tsconfig.jsonを編集する(TypeScript)
プロジェクトにTypeScriptを採用する場合,設定ファイルであるtsconfig.json
が内部に隠蔽されていないため容易にデコレータを有効にできます.以下の設定を"compilerOptions"
内に追加します.
"experimentalDecorators": true