DEVELOPMENT
目次
RiotとWebPackを使う目的
うーちゃん家のWebサイトは、以前、サーバー上のRailsで動いてましたが、そんだけのために、Webサーバーを使ってるのがもったいなく感じてきたので、webpackを使いstaticな静的ファイルを生成してWebサーバーを使うのをやめようということで、モダンなjsで代表的なのはReactですが、(Angularはどうだろう)、今回はちゃちゃっと済ましたいので、Riotを使ってみることにしました。
環境作り
- webpackでプレコンパイルして、staticな形で出力する
- riot は.tagファイルで記述し読む
- materializeを全体的に使いたい
- 自作スタイルシートはsassで記述したいけど、js中でmoduleで読むのは面倒なので、cssファイルを出力し、タグ中で普通に使いたい
- 画像はHTTPリクエストを最大限に減らすため、base64でコンパイルする
バージョンについて
- webpack 3.8.0
- riot 3.7.3
必要なパッケージを入れる
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部分のファイル名やパスは、必要に応じて変更して下さい。
- jsの方は、riot-loaderと、babelのloaderを指定してます。
- cssは、sassをコンパイルして、cssを履きその内容をタグの中でつかえるようにしました。moduleで読む方法もあるけど、毎回js中でimportするのが面倒なので、この方法をとりました。
- 画像はjsからもcssからも、base64で読むようにurl-loaderをそれぞれで指定してます。そのためpublic以下にわざわざ画像を出力しません。
- .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'
}
ここまで
- scssをプレコンパイル対象に追加したのは、materializeの色をカスタマイズするために、下記で設定するscssファイルが必要だったからです。
- woffとttfなどは、materializeで仕様しているフォントファイル等が必要なためです。
- file-loaderにより、public以下に出力されます。
- url-loaderはmaterializeのcssファイル中から、fontを読めるようにするためです。
設定ファイルを用意
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が適応されました
- materialize-loaderはcssしかロードしてくれないような感じでしたので、jsも適応したいので、materialize-css を直接記述してます。
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>
- scriptタグ中のthis.xxxと定義すると、htmlタグ中で、{xxx}の形で変数を扱えます。
- methodについても、script中で定義したmethodは{xxxx}で扱えます。 わかりやすいですね。
- 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までやるのはちょっとって方にはいいかもしれません。
株式会社UKAI 代表取締役CEO。建築を専攻していたが、新卒でYahoo!Japanにエンジニアとして入社。その後、転職、脱サラ、フリーランスエンジニアを経て、田舎へ移住し、ゲストハウスの開業、法人成り。ゲストハウス2軒、焼肉店、カフェ、食品製造業を運営しています。詳細はこちらから