忙しい人のためのRiot.jsディレクトリ構成
はじめに
最近密かに話題のRiot.jsをご存知でしょうか。そうです。噂のこいつです。
<todo>
<!-- layout -->
<h3>{ opts.title }</h3>
<ul>
<li each={ item, i in items }>{ item }</li>
</ul>
<form onsubmit={ add }>
<input ref="input">
<button>Add #{ items.length + 1 }</button>
</form>
<!-- style -->
<style>
h3 {
font-size: 14px;
}
</style>
<!-- logic -->
<script>
this.items = []
add(e) {
e.preventDefault()
var input = this.refs.input
this.items.push(input.value)
input.value = ''
}
</script>
</todo>
詳しい話は先人達の秀逸な記事に任せるとして、今回は**新しいライブラリを使いたいけど、導入とか構成とか考える時間がない!**って方にオススメのディレクトリ構成のサンプルをご用意しました。
環境
- Riot.js v3.0.1
- ES6
- node.js v6.9.1
- gulp
- (jQuery)
- webpack
- webpack-dev-server
導入
# git clone https://github.com/slont/riot-sample.git
# cd riot-sample
# npm install -g gulp bower # 入れてない人
# npm install
# gulp build
# bower install
# npm start
画面
簡単ですね。
解説
ディレクトリ構成
riot-sample
├ app - components
├ node_modules
├ src ┬ scripts ─ index.js
│ ├ styles ─ index.scss
│ ├ tags ┬ header.tag
│ │ └ card ─ index.tag
│ └ views - index.html
├ .bowerrc
├ .gitignore
├ bower.json
├ gulpfile.js
├ package.json
└ webpack.config.js
var webpack = require('webpack');
module.exports = {
context: __dirname + '/src',
entry: {
'index': './scripts/index.js',
},
output: {
path: __dirname + '/dist',
filename: '[name].min.js'
},
devServer: { // サーバの設定
contentBase: 'app',
port: 3000,
hot: true,
inline: true
},
module: {
preLoaders: [
{
test: /\.tag$/,
exclude: /node_modules/,
loader: 'riotjs-loader',
query: {
type: 'babel'
}
}
],
loaders: [
{
test: /\.js$|\.tag$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015-riot']
}
}
]
},
resolve: {
extensions: ['', '.js', '.tag', '.scss']
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new webpack.ProvidePlugin({
riot: 'riot'
})
]
};
RiotローダーとBabelローダーを用いてwebpackでコンパイルします。presetにes2015-riot
を入れることで、Tag内のES6記法にも対応可能になります。
require('../tags/header')
require('../tags/card') // ディレクトリ指定でindex.tagを読める
riot.mount('*') // これは個々のtagのscript内でマウントしても良いかも
scripts内のjsは基本的にtagの読み込みとコンポーネントの連携管理とし、viewsの構造と合わせてファイルを作成し、画面毎に読み込ませるようにします。
躓いたところ
clickイベント等の登録
Tag内のscriptでは、タグをマウントするまでDOMが生成されないため登録できません。
<todo>
<button id="sample-btn"></button>
<script>
// 上手くいかない
// $("#sample-btn").click(function(e) {...})
// こうする
this.on("mount", function() {
$("#sample-btn").click(function(e) {...})
})
</script>
</todo>
ちなみにES6はコンテクスト気にせずに調子に乗ってアロー関数使ってると死ぬ。
アロー関数の個人的なハマりどころまとめ
WARNING in application.js from UglifyJs
黙ってwebpack.config.jsに以下を指定。
new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } })
Cannot convert a Symbol value to a string
始め、es6-loader
を使っていたのだが、このエラーが出て動かなかったので、babel-loader
に変更した。
ちなみに https://github.com/paulmillr/es6-shim/issues/361ではnode0.12系のバグと書いていたが、時分のは6.9系だったのでわけわかめ。
おわりに
駆け足になりましたが、参考になれば幸いです。