概要
みなさんこんにちはcandleです。
今回はemacsとimport-jsを使って自動的に、componentのパスをインポートしてみたいと思います。
Reactは1ファイル1コンポーネントの書き方を推奨しており、開発が大規模になればなるほど、componentが増えていきます。
もしも1つのContainerで10個のコンポーネントを使うと、10行のimport文を書かなくてはなりません。
そういった面倒な作業を手助けしてくれるのがimport-jsです。
私はreact webではうまく機能しましたが、react nativeではうまくimport-jsがコンポーネントを探すことができませんでした。
恐らく、import-jsの設定が甘いので失敗していると思います。
原因を解明するとともに、分かり次第、記事にします。
前提
React webの環境が整っている。
前の記事に書いたcreate-react-appコマンドで作成したプロジェクトを使う事をおすすめします。
melpaかel-getの環境が整っている
emacsのimport-jsのメジャーバージョンがnodeのimport-js2.2.0に対応していないので、
少しトリッキーな事をしています。
el-getを使う事をお勧めします。
import-jsについて
emacsがimport-jsを使う仕組みはこのようになります。
eslintと同じ方式で、emacsが得意とする外部APIを叩くことでimpot-jsを使っています。
import-jsは自動的にプロジェクトの構造やコンポーネントの位置を把握して、任意のファイルにimport文を挿入します。
さて、import-jsは2.1.0から、かなり仕様が変わりました。
importjsdというデーモンを使って、現在のエディタのプロセスとつなぎ、カーレントディレクトリ以下のモジュールを確認し、cachepathにあるsqlite3のデータベースにパスなどを保存して、エディタに値を渡す事をしています。
emacsのimport-jsプラグインはこの仕様にまだ対応していません( 2017/4/11 )。
そこで、有志のプログラマーが開発しているgithubのリポジトリからソースを持ってきて使う事にします。
nodeのimport-jsをインストールする
最初にnodeのimport-jsをインストールします。
import-jsはnpmでインストールできます。
npm install -g import-js
インストールが終わったら、コマンドが使えるか確認します。
importjs
今回インストールしたimport-jsのバージョンは2.2.0です。
準備okです。
emacs上でinport-jsをインストール
nodeのimport-jsをemacsから使うためのimport-jsをインストールします。
meplaの場合
npmのimport-js2.2.0に対応したemacsのimport-jsはまだmasterに2017/4/14現在マージされておらず、
melpaのパッケージからインストールできません。
そこで、一度、meplaで古いバージョンをインストールして、手動で新しいファイルをダウンロードして対応させます。
「M-x package-list-packages」でemacsパッケージ一覧を表示します。
次に「C-s import-js」でimport-jsを探します。
import-jsのところにカーソルを合わせて「I」と打ち込み「x」でインストールを実行します。
インストールするか確認を求められるので「y」でインストールします。
続いて、2.2.0に対応した.elファイルをダウンロードします。
melpaのディレクトリに移動します。
import-jsのディレクトリ名は時期によって変わります。
cd ~/.emacs.d/elpa/import-js-20161220.508
import-js.elとimport-js.elcを削除します。
rm import-js.el import-js.elc
githubからファイルを持ってきます。
curl -O https://raw.githubusercontent.com/kevinkehl/emacs-import-js/importjsd/plugin/import-js.el
最後に、.emacs.d/init.elを開いて、以下を記述します。
(require 'import-js)
meplaのインストールは以上です。
el-getでインストールする
emacsのimport-jsのメージャーバーションはまだnpmのimport-js2.2.0に対応しいません。
少しトリッキーな方法でimport-jsをインストールします。
.emacs.d/init.elを開いて以下を記述します。
(el-get-bundle import-js :type github :name import-js :pkgname "kevinkehl/emacs-import-js" :branch "importjsd" :load "plugin/import-js.el" :depends (grizzl ))
M-x eval-buffer
でinit.elを再読み込みして、パッケージをインストールします。
el-getでのインストールは以上です。
emacsのimport-jsの設定
import-jsの設定は大きく分けて3つです。
1、import-js-importのショートカットキー
2、importjsdのデーモンを自動起動
3、C-x C-cのEmacs終了時、自動的にデーモンを止める
最初に1と2の設定です。
impor-js-importを実行すると自動的にモジュールのパスがファイルに挿入されます。
C-c iの割り当ては適当です。空いてたので使いました。
上にも書いた様に、import-jsを使うにはimportjsdを起動する必要があります。
もちろん、手動で、「M-x run-import-js」でも起動できますが、面倒なので自動起動にします。
js2-jsx-modeの方
(add-hook 'js2-jsx-mode-hook (lambda () (local-set-key (kbd "C-c i") 'import-js-import) (run-import-js)))
rjsx-modeの方
(add-hook 'rjsx-mode-hook (lambda () (local-set-key (kbd "C-c i") 'import-js-import) (run-import-js)))
次に、このままだと、Emacsを終了するたびに、importjsdのデーモンをころすか聞かれます。
面倒なので、自動的にキルするようにします。
(require 'cl-lib) (defadvice save-buffers-kill-emacs (around no-query-kill-emacs activate) "Prevent annoying \"Active processes exist\" query when you quit Emacs." (cl-letf (((symbol-function #'process-list) (lambda ()))) ad-do-it))
最終的にこういう設定になります。
.importjs.jsファイルをreactプロジェクトの設置する
importjsコマンドはreactプロジェクトのルートにある.importjs.jsを参考にしてあれこれやってくれます。
今回用意したreactプロジェクトはこのような構造になります。
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
└── src
├── App.css
├── App.js
├── App.test.js
├── components
│ └── Input.js
├── index.css
├── index.js
└── logo.svg
.importjs.jsをプロジェクトルートに作成します。
touch .importjs.js
内容はよくわから無いので、githubに上がっているものを参考にしました
https://github.com/Galooshi/import-js/blob/master/.importjs.js
以下を書き込みます。
module.exports = { environments: ['node'], ignorePackagePrefixes: ['lodash.'], declarationKeyword: 'import', logLevel: 'debug', excludes: [ './build/**' ] }
保存します。
実際に使ってみる
ここからは人によってReactの環境が変わってきますが、私は前回の記事の環境でやっています。
src/App.jsはこんな感じのプログラムです。
import React from 'react'; class App extends React.Component{ constructor(){ super(); this.state = { txt: 'hello world' } } update(e){ this.setState({ txt: e.target.value }) } render(){ return( <div> <p>Text: {this.state.txt}</p> <Input onChange={this.update.bind(this)}/> </div> ) } } export default App;
Input componentをcomponents/Input.jsから自動的にimportしてみたいと思います。
emacs上の<Input>jsxの上で「C-c i」か「M-x import-js-import」を実行します。
1度目はimportjsdがそのプロジェクト配下のモジュールを認識していないので、何も出てきません。
もう1度「C-c i」か「M-x import-js-import」を実行します。
すると、自動的にコンポーネントが挿入されると思います。
うまくできました。
まとめ
自動挿入させるまでにはかなり試行錯誤しました。
よいEmacs上でのReact開発を