忙しい人のためのRiot.jsディレクトリ構成

Web開発 11月 28, 2016

はじめに

最近密かに話題の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系だったのでわけわかめ。

おわりに

駆け足になりましたが、参考になれば幸いです。

参考

slont

金融ベンチャーでWebエンジニア。美と酒とTechで生きてる。Vue.jsが至高。Elixir好き。個人事業とWebアプリ案件もやってます。 アプリ→https://app.cullet.me Android→https://play.google.com/store/apps/details?id=net.maytry.cullet.android

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.