はじめに
Reactに爆速で入門する1~3までで、React自体に対する理解はできてきました。(第1回はこちら)
しかし、入門1~3では、1つのファイルで、しかもReactやBabelの読み込みをscriptタグでCDNで行っていました。
実際のフロントエンド開発においては、この方式はまず採用されていなくて、大体はWebpackやBrowserifyやらを使用して、トランスパイル&バンドルするのが一般的ですよね。
ということで、今回は現状最も人気があると思われる(主観)Webpackを使用して、第3回までに作ったファイルを分割して見やすく、その分割したファイルをトランスパイル&バンドルするということをやっていこうと思います。
ベースは第3回のリスト表示するコードになりますので、コードを取得していない方はもってきてください。
また、npmを使用するので、とりあえずnodeをインストールしてください。公式ページからDLできます。
必要なプラグインをインストールする
とりあえず、npm initします。
[text] npm init -y
[/text]
次に、ReactとWebpackとBabelをインストールします。
[text] npm install –save react react-dom[/text] [text] npm install –save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react webpack
[/text]
結果のpackage.jsonは下記のような感じになっていると思います。(webpack-dev-serverは除く)
[text] {"name": "react-minimal",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"production": "webpack -p",
"dev": "webpack -d",
"watch": "webpack -d –watch",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"react": "^16.2.0",
"react-dom": "^16.2.0"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-react-hmre": "^1.1.1",
"webpack": "^3.9.1",
"webpack-dev-server": "^2.9.5"
}
} [/text]
WebpackとBabelの設定ファイルを作る
さて、使用する色々なもののインストールが完了したら、webpackとbabelの設定フィルをつくります。
webpackの設定ファイル
webpack.config.jsとしてルートに配置します。とりあえずはコピペでokです。
[text] const path = require(‘path’);module.exports = {
context: path.resolve(__dirname, ‘src’),
entry: {
js: ‘./main.js’
},
output: {
path: path.resolve(__dirname, ‘dist’),
filename: ‘bundle.[name]’,
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: ‘babel-loader’,
query: {
presets: [‘react’, ‘es2015’]
},
}
]
},
plugins: [
],
devServer: {
contentBase: ‘./dist/’,
port: 8080,
inline: true,
historyApiFallback: true,
clientLogLevel: "info",
stats: { colors: true }
}
};
[/text]
srcフォルダのmain.jsを起点としてjsファイルを探していき、出力はdistフォルダ以下にbundle.jsとしてね、的な感じのことを書いてあります。
babelの設定ファイル
.babelrcとしてルートに配置します。
[text] {"presets": ["es2015", "react"] }
[/text]
前回作成したファイルを分割する
第3回で作成したindex.htmlをコンポーネントごとに分割していきましょう。
index.htmlは、/dist/index.htmlとして配置し、それ以外のファイルは/src/以下に配置してください。
/dist/index.html
まずはindex.htmlを。もともとこのファイルに全てがつめこまれていましたが、下記の通りwebpackから生成されるbundle.jsを読み込む部分1つ残して、残り全てはクリアしてしまいます。
[html] <html lang="ja"><head>
<meta charset="UTF-8" />
</head>
<body>
<div id="app"></div>
<script src="./bundle.js"></script>
</body>
</html>
[/html]
/src/main.js
エントリポイントとしてwebpack.config.jsに記述したmain.jsを作ります。
第3回のindex.htmlの、class定義部以外の全てをここにコピーする感じです。
また、React, ReactDOMのimportを忘れずに、また、ListAppをRenderしますのでListAppのimportも行います。
ListAppやMyListコンポーネントは、/src/components/に配置する予定ですのでListAppの読み込み先は./components/ListAppにします。
[javascript] import React from ‘react’;import ReactDOM from ‘react-dom’;
import ListApp from "./components/ListApp";
var my_items = [
{
name: "hoge",
text: "this is hoge text"
},
{
name: "foo",
text: "I’m foo"
},
{
name: "bar",
text: "this is bar"
}
];
ReactDOM.render(
<ListApp items={my_items} />,
document.getElementById("app")
);
[/javascript]
/src/components/ListApp.js
ListAppもmain.jsと同じで、React関連の読み込みとMyListの読み込みをします。
main.jsから参照されますので、export defaultでclass自体をexportするのを忘れずに。
import ReactDOM from ‘react-dom’;
import MyList from "./MyList"
export default class ListApp extends React.Component {
constructor(props){
super(props);
this.state = {
items: props.items
};
}
render(){
return(
<div>
<h3>List App</h3>
<div>
<input id="ListApp-name" placeholder="name" />
<input id="ListApp-text" placeholder="text" />
<button onClick={this.handleClick.bind(this)}>add</button>
<MyList items={this.state.items} />
</div>
</div>
)
}
handleClick(event){
this.setState({
items: this.state.items.concat({
name: document.getElementById("ListApp-name").value,
text: document.getElementById("ListApp-text").value
})
});
}
}
[/javascript]
/src/components/MyList.js
MyList.jsは特筆すべきところはないですね。他と同じです。
[javascript] import React from ‘react’;import ReactDOM from ‘react-dom’;
export default class MyList extends React.Component{
constructor(props){
super(props);
}
render(){
return(
<ul>
{
this.props.items.map((v, i)=> {
return (
<li key={i}>
<p>name:{v.name}</p>
<p>text:{v.text}</p>
</li>
)
})
}
</ul>
)
}
}
[/javascript]
これでファイル分割の準備が完了しました。
ここまでで、ファイル構成は下記のようになっているはずです。
- /
- /src
- /components
- ListApp.js
- MyList.js
- main.js
- /components
- /dist
- index.html
- package.json
- webpack.config.js
- .babelrc
- /src
ビルドする
ビルド用に、下記のコマンドをscriptsに追記します。
[text] "scripts": {<span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>"production": "webpack -p",
"dev": "webpack -d",
"watch": "webpack -d –watch",
"test": "echo \"Error: no test specified\" && exit 1"
},
[/text]
それでは、webpackによるトランスパイル&バンドルの動作確認します。
ルートで下記のコマンドを叩きます。
[text] npm run dev[/text]
成功すれば、/dist/bundle.jsが生成されているはずです。
そして、/dist/index.htmlを開くと下記のように第3回と同じものが表示されます。
これでやっとモダンなフロントエンド開発に近づいてきました。
今回は以上です!