サンプルページ
tl;dr
- npm install -gはだるいので、npm scripts経由でwebpack呼ぶのがよさそう
- webpackが扱うべきファイルによってloaderがひつよう(
babel-loader
とか)- loaderを書く順番でひっかかって非常にだるかった
- importの拡張子省略はwebpack.configで指定できるっぽい
ReactDOM.render
が評価される時点でrender targetがreadyじゃないといけないの
背景
- なぜReactか
- ちいさいjsの何かをつくるときは、gulpなどタスクランナーの設定が必要無いという点においてAngular(1系)使うのが好きだったんだけど、Angular2がComponentベースだというはなしを聞いて、じゃあええわべつにReact使うし、っていう気持ちになった
- なぜBabelか
- Componentベースで何かを作るとき、Componentごとにファイルを分割したほうが開発効率もよいだろうし、依存関係を明示するためにもES6(ES6ってもう言わない?)の
import
使いたいし、React的にもclass
、extends
も使いたいし、でも実行環境はES5以下を想定するので6to5しましょう
- Componentベースで何かを作るとき、Componentごとにファイルを分割したほうが開発効率もよいだろうし、依存関係を明示するためにもES6(ES6ってもう言わない?)の
- なぜwebpackか
エラー: Illegal import declaration
babel-loaderとjsx-loaderを使ってたので、jsxファイルの中でjsx記法とES6記法をつかっていても問題なくwebpackがビルドしてくれると思っていた。だけどどうやらbabel-loaderのあとに読み込んだjsx-loaderが、babel-loaderによって可能にしたimport
の解釈を食ってた、みたいな挙動にでくわした。さらに、babel-loaderだけ読み込んでおけば、jsx->jsのコンパイルはしてくれるみたいだ、ということを知った。
Babel · The compiler for writing next generation JavaScript
JSX and React Babel has support for JSX and Flow.
エラー: React is not defined
アプリのエントリポイントであるところのapp.js
では、ReactDOM
モジュールしか参照していないので、とうぜん、import ReactDom from 'react-dom'
でじゅうぶんだと思っていた。
import ReactDOM from 'react-dom'; import Foo from './Foo'; ReactDOM.render(<Foo />, document.getElementById('main'));
しかしこれだと掲題のエラーが出る。きっとReactDOM
モジュールの中でReact
っていう名前を参照してるんだろうな、と思いつつも、webpackがimportを解決してくれるんじゃなかったっけって思った。でもそれは誤りで、node_modules
以下にinstallされたreact-dom
っていうのはjs(ES5)で書かれているわけで、依存もimportを書いているわけではないので、webpackを通したところで依存が解決されたjsファイルがビルドされるわけではないんだろう。
+ import React from 'react';
import ReactDOM from 'react-dom';
import Foo from './Foo';
ReactDOM.render(<Foo />, document.getElementById('main'));
エラー: Target container is not a DOM element
これはべつにwebpackの構成の問題ではないんだけど、今回(というか毎回)ぶつかるエラー。とはいえなんも難しい話ではなく、rootなcomponentを最初にレンダリングするときに呼ばれる ReactDOM.render
の第二引数に指定されるrender targetが、まだreadyなDOMではないことに起因してるだけ。
ReactDOM.render(<App />, document.body);
なのでたとえば
setTimeout(function() { ReactDOM.render(<App />, document.body); }, 0);
とするとか
<body onload="initApp()"></body>
とするとか、
<body> <section id="main"><!-- ターゲット --></section> <script src="app.js"></script> </body>
とするとか、いろいろな解決方法が提案できる。
参考
- gulp + webpack + reactの最小構成 - Qiita
- WebPackを使ってJavaScriptを効率的に書くチュートリアル【入門編】 | 株式会社LIG
- ECMAScript6で書こう!WebPackとES6-loaderで環境を作り、ES6を先取り体験する方法 | 株式会社LIG
- https://christianalfoni.github.io/react-webpack-cookbook/Optimizing-rebundling.html
- GitHub - HenrikJoreteg/hjs-webpack: Helpers/presets for setting up webpack with hotloading react and ES6(2015) using Babel.
- webpack module bundler
- Babel · The compiler for writing next generation JavaScript
- A JavaScript library for building user interfaces - React
- 【個人メモ】React Tutorialをちょこっとやってみた - Qiita
- GitHub - petehunt/react-webpack-template
- JSX: Illegal import declaration · Issue #3401 · facebook/react · GitHub
雑感
- hjs-webpackを使えばらくちんという話を聞いたけど、何がなぜ必要でどう動いているのか理解するためには最小構成を自分でつくるという体験は大事だと思うんですよね
DRY
改訂新版JavaScript本格入門 ?モダンスタイルによる基礎から現場での応用まで
- 作者: 山田祥寛
- 出版社/メーカー: 技術評論社
- 発売日: 2016/09/30
- メディア: Kindle版
- この商品を含むブログを見る
- 作者: Azat Mardan
- 出版社/メーカー: Manning Pubns Co
- 発売日: 2017/03/31
- メディア: ペーパーバック
- この商品を含むブログを見る