Webpack + Riot + Materializeで、Webサイト環境を作った話

目次

RiotとWebPackを使う目的

うーちゃん家のWebサイトは、以前、サーバー上のRailsで動いてましたが、そんだけのために、Webサーバーを使ってるのがもったいなく感じてきたので、webpackを使いstaticな静的ファイルを生成してWebサーバーを使うのをやめようということで、モダンなjsで代表的なのはReactですが、(Angularはどうだろう)、今回はちゃちゃっと済ましたいので、Riotを使ってみることにしました。



環境作り

バージョンについて


必要なパッケージを入れる

node 初期化

$ npm init

node が入ってない場合はbrewか何かで入れて下さい。

Webpack

$ npm install --save-dev webpack

Babel を入れる

$ npm install --save-dev babel-core babel-loader

ec2015

$ npm install --save-dev babel-preset-es2015 babel-preset-es2015-riot

webpack のためのローダー

$ npm install --save-dev riotjs-loader

Riot.js を入れる

$ npm install --save riot

Materialize とsassに必要なもの

$ npm install --save materialize-css
$ npm install --save-dev sass-loader css-loader file-loader url-loader materialize-loader

jquery ※materializeは、jqueryを使ってるため

$ npm install --save jquery


Webpackの設定ファイル

webpack.config.babel.js

    import path from 'path';
    import webpack from 'webpack';
    import ExtractTextPlugin from 'extract-text-webpack-plugin';

    export default [
        {
            context: path.join(__dirname, './source/javascripts'),
            entry: {
                app: './app.js'
            },
            output: {
                path: path.join(__dirname, './public'),
                filename: '[name].js'
            },
            module: {
                rules: [
                    {
                        test: /\.tag$/,
                        exclude: /node_modules/,
                        enforce: "pre",
                        loader: 'riotjs-loader'
                    },
                    {
                        test: /\.js[x]?$|\.tag$/,
                        exclude: /node_modules/,
                        loader: 'babel-loader',
                    },
                    {
                        test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(\?.*)?$/,
                        loader: 'url-loader',
                    },
                ],
            },
            resolve: {
                extensions: ['*', '.js', '.tag']
            },
            plugins: [
                new webpack.ProvidePlugin({
                    riot: 'riot'
                })
            ]
        },
        {
            context: path.join(__dirname, './source/stylesheets'),
            entry: {
                app: './style.sass'
            },
            output: {
                path: path.join(__dirname, './public'),
                filename: '[name].css'
            },
            module: {
                rules: [
                    {
                        test: /\.sass$/,
                        exclude: /node_modules/,
                        use: ExtractTextPlugin.extract({
                            fallback: "style-loader",
                            use: [
                                {
                                    loader: "css-loader",
                                    options: {
                                        url: false,
                                        minimize: true
                                    }
                                },
                                "sass-loader"
                            ]
                        })
                    },
                    {
                        test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(\?.*)?$/,
                        loader: 'url-loader',
                    },
                ]
            },
            plugins: [
                new ExtractTextPlugin({
                    filename: '[name].css'
                })
            ]
        }
    ]

※ entry や output部分のファイル名やパスは、必要に応じて変更して下さい。

.babelrc

{
    "presets": [ "es2015", "es2015-riot", "stage-3" ]
}

これで環境ができました。

あとは、riotとmaterializeを使って書いていきます。


Materialize

設定

webpack.config.babel.js に下記を追加します。

    context: path.join(__dirname, './source/javascripts'),
    entry: {
        app: './app.js'
    },
    .
    .
    .
    ここから
      {
          test: /\.scss$/,
          loader: ExtractTextPlugin.extract('style-loader', 'css-loader?-url&minimize&sourceMap!sass-loader')
      },
      {
          test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
          loader: 'url-loader?limit=10000&mimetype=application/font-woff'
      },
      {
          test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
          loader: 'file-loader'
      }
    ここまで
設定ファイルを用意

source/config ディレクトリを作成し

materialize.config.jsを作成

    module.exports = {
        styles: {
            'materialize': true,
        }
    };

materialize.config.scssを作成

    $primary-color: color("blue-grey", "lighten-2");
    $primary-color-light: lighten($primary-color, 15%);
    $primary-color-dark: darken($primary-color, 15%);

※好きな色を指定する(色をカスタマイズしたいときのみ)

materialize.config.cssを作成

読み込み

app.jsでrequireする

    require('materialize-loader!../config/materialize.config.js');
    require('materialize-css');

これでmaterializeが適応されました

Material icon

$ npm install --save-dev material-design-icons


Riot

試しにカウントアップ・ダウンのサンプルをやってみます source/tags ディレクトリを作成し、 count.tagを作成

    <count>
        <p>カウント: { count }</p>
        <button onclick={ add }>+</button>
        <button onclick={ minus }>-</button>
        <script>
            this.count = 0;
            add() {
                this.count += 1;
            }
            minus() {
                this.count -= 1;
            }
        </script>
    </count>

source/javascripts/app.jsを編集

    import count from '../tags/count'

    riot.mount('count')

mountし、描画される

複数の.tagを読み込む際、何行もimportするのを回避する

source/tags/index.jsを用意

    import count from './count'
    import navigation from './navigation'

※もっといい方法あれば教えてください。

source/tags/navigation.tagsを適当に用意する

そうすると、app.jsでは

    import {count, navigation} from '../tags'

こう書くことができ、一気にたくさんimportできます

これで整いました

まとめ

webpackでの、画像の取扱や、cssのloaderがたくさんあるので、少し戸惑いましたが、理解できてスッキリしました。 riotは視覚的に非常にわかりやすく、モダンにjsを書きたいけど、reactまでやるのはちょっとって方にはいいかもしれません。

U-chan ( Nobuyuki Ukai )

学生時代は建築やデザインを専攻していたが、Yahoo!Japanにエンジニアとして運良く入社し、2年半で波情報を配信する波伝説に転職。3年後、Yahoo!時代の先輩の立ち上げたベンチャーに転職。数年後、伊豆下田に移住し、ゲストハウスを開業しながらリモートでエンジニアを続けたが、焼肉店の開業とともに株式会社UKAIを立ち上げ、法人成り。その後、カフェとゲストハウスをもう一軒開業し、現在は焼肉店、カフェ、ゲストハウス2件目を運営。今季は自社Webサイトの立ち上げ予定!

comments powered by Disqus