Ruby on Railsにwebpackを使ってPostCSSを導入してみた【ローカル環境編】
こんにちは、エンジニアの井戸田です。
今回はモダンなCSS環境を構築するために流行っていると言われているPostCSS×webpackをRailsに導入してみました。
今回は開発環境だけですが、次回本番運用に関して書いていきたいと思います。
- 環境
- PostCSSとは
- Railsプロジェクトを作る
- webpack環境のためのディレクトリを作成
- npmで必要なライブラリをインストール
- webpack.config.jsにビルドの設定を書く
- Rails側の設定
- テスト
- PostCSSのプラグインの導入方法
- PostCSSのプラグインの紹介
- We’re hiring!!
環境
PostCSSとは
PostCSSはJSプラグインでスタイルを変換するためのツールです。特徴として下記のことが挙げられます。
- PostCSS自体が変換するのではなくCSSパーサーとASTを操作するためのAPIを提供しているだけで、実際にCSSに変換するのはPostCSSのプラグインが行います。
- Sassでよく使う
mixin
extend
変数($)
などの機能がそれぞれ1つ1つのプラグインになっており、それらを入れることで使用が可能になります。 - メタ言語の中でも特にPostCSSは速度が速いです。
ref) https://github.com/postcss/benchmark
Railsプロジェクトを作る
$ rails new sample-postcss -BJ $ bundle install --path vendor/bundle
とりあえず $ bundle exec rails s -b 0.0.0.0 -p 3000
webpack環境のためのディレクトリを作成
プロジェクトルートに client
というディレクトリを作成。ここがwebpack環境のためのディレクトリになっています。
clientディレクトリの構成については下記のようになります。
client |-- webpack.config.js |-- node_modules |-- package.json └── src |-- images |-- javascripts └── stylesheets
npmで必要なライブラリをインストール
client
ディレクトリに移動し、下記のコマンドを入力して package.json
を生成します。
$ npm init -y
webpackをインストール。webpackでは1系を使用したかった為、バージョンの指定をしています。
$ npm install -D webpack@1.14.0
ローカル環境では下記ことを可能にする webpack-dev-server
が、便利なので使っていきます。 webpack-dev-server
はポート8080を使うNode.jsのexpressサーバーです。
- ファイルの変更を検知して自動でビルドをしたのち、ブラウザを自動でリロードする
- HMR(
Hot Module Replacement
)という編集したモジュールを自動で更新する
$ npm install -D webpack-dev-servser
cssやpostcssに必要な style-loader
css-loader
postcss-loader
モジュールと、CSSをJavaScriptでロードせずにlinkタグでロードさせるため、 extract-text-webpack-text
をインストール。
$ npm install -D style-loader css-loader postcss-loader extract-text-webpack-plugin@1.0.1
webpack.config.jsにビルドの設定を書く
- デバッグ用のSourceMapの設定
- entryポイントの設定
- 出力先を設定
- トランスパイルの設定
exstract-text-webpack-plugin
の設定webpack-dev-server
でファイル変更した際に検知し、自動でビルド、自動でブラウザをリロードしてくれるように設定
client/webpack.config.js
/** * Require basic plugins */ const path = require('path'); const webpack = require('webpack'); /** * webpack plugins */ const ExtractTextPlugin = require('extract-text-webpack-plugin'); module.exports = { devtool: 'inline-source-map', context: path.join(__dirname + '/../client/src'), entry: { application: [ 'webpack-dev-server/client?http://localhost:8080', 'webpack/hot/dev-server', './javascripts/application.js' ] }, output: { filename: '[name].js', publicPath: 'http://localhost:8080/assets/' }, module: { loaders: [ { test: /\.css$/, loader: ExtractTextPlugin.extract('style', 'css!postcss') } ] }, plugins: [ new ExtractTextPlugin('[name].css'), new webpack.HotModuleReplacementPlugin() ], devServer: { headers: { 'Access-Control-Allow-Origin': 'http://localhost:3000', 'Access-Control-Allow-Credentials': 'true' } } };
webpack-dev-serverの起動用にpackage.jsonに追記
client/package.json
{ ... "scripts": { "dev": " ./node_modules/.bin/webpack-dev-server --debug --hot --inline --devtool --public --host 0.0.0.0 --port 8080 --config ./webpack.config.js", ... }, ... }
webpack.config.js
のentryは client/src/javascripts/application.js
なので、 application.js
に client/src/stylesheets/application.css
をrequireさせます。
画像などもwebpackで配信したい場合は、同様に application.js
にrequireさせます。
client/src/javascripts/application.js
/** * Require stylesheets */ require('../stylesheets/application.css');
Rails側の設定
headタグ内のjavascript_include_tag, stylesheet_link_tagを変更
assets部分は webpack-dev-server
から取得するため、 app/views/layouts/application.html.erb
のheadタグの stylesheet_link_tag
と javascript_include_tag
部分を変更。
app/views/layouts/application.html.erb
<!DOCTYPE html> <html> <head> <title>SamplePostcss</title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'http://localhost:8080/application.css', media: 'all' %> <%= javascript_include_tag 'http://localhost:8080/application.js' %> </head> <body> <%= yield %> </body> </html>
Railsの起動設定
rails s
と npm run dev
の2つのコマンドを打てば起動できるのですが、面倒くさいので foreman
というgemを使っていきます。
group :development do gem 'foreman' end
ルートディクトリに Procfile
という名前でファイルを作成し編集していきます。
rails: bundle exec rails server -b 0.0.0.0 -p 3000 webpack: npm --prefix ./client run dev
$ bundle exec foreman start
のコマンドで立ち上がります。
テスト
以上でローカル環境の構築は完了したので、テストしていきましょう。
config/routes.rb
Rails.application.routes.draw do root 'static_pages#about' end
app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController # GET / def about end end
app/views/static_pages/about.html.erb
<h1>about</h1>
client/src/stylesheets/application.css
h1 { color: red; }
http://localhost:3000
にアクセスした結果
h1
タグのcolorが red
になっているのと、 gray
に変更した時に自動でブラウザの更新を行い色が変わりました。
PostCSSのプラグインの導入方法
autoprefixer
というprefixをつけてくれるプラグインを入れていきます。
まず client
ディレクトリに移りnpmで autoprefixer
をインストールします。
$ npm install -D autoprefixer
webpack.config.js
を編集していきます。下記の記述でPostCSSのプラグインを導入することができます。
client/webpack.config.js
... /** * postcss plugins */ const autoprefixer = require('autoprefixer'); module.exports = { ... postcss: [autoprefixer], ... }
それではcssファイルの方に flex
を書いてみます。
client/src/stylesheets/application.css
div { display: flex; }
webpackのビルド後は以下のようになります。
dev { display: -webkit-box; display: -ms-flexbox; display: flex; }
PostCSSのプラグインの紹介
postcss-import
ref) https://github.com/postcss/postcss-import
@import
が使用できるプラグインになっています。postcss-simple-vars
など他のプラグインを使用したファイルをimportした時にエラーになる可能性があるので、config.webpack.js
の postcss
の 方でこちらのプラグインを最初に読み込ませておくようにしましょう。
@import 'componsents/button.css'; @import 'base.css';
postcss-simple-vars
ref) https://github.com/postcss/postcss-simple-vars
SCSSのような $
を使って変数が定義できます。また弊社では変数( $
)はcolorの色を定義時に使用しています。
before
$red-color: #ff0000; $column: 200px; h1 { color: $red-color; } .column-400px { width: calc(2 * column); }
after
h1 { color: #ff0000; } .column-400px { width: calc(2 * 200px); }
postcss-nested
ref) https://github.com/postcss/postcss-nested
SCSSの様にネストを使用できるpluginです。
before
.item { &_title { width: 500px; @media (max-width: 500px) { width: auto; } body.is_dark & { color: white; } } img { display: block; } }
after
.item_title { width: 500px; } @media (max-width: 500px) { .item_title { width: auto; } } body.is_dark .item_title { color: white; } .item img { display: block; }
postcss-mixins
ref) https://github.com/postcss/postcss-mixins
SCSSの様に @mixin
で定義し、 @include
で呼び出す形ではないので注意が必要です。
before
@define-mixin margin-10px { margin: 10px; } .column { @mixin margin-10px; }
after
.column { margin: 10px }
また引数を指定することも可能です。
@define-mixin
引数で 0
を指定しています。 @mixin
の方で $px
の値を指定しなければ 0
になり、指定すればその指定した数値になります。
今回の場合は margin: 10px
となります。
@define-mixin margin $px: 0 { margin: $px } .column { @mixin margin 10px; }
PostCSS Sassy Mixinsと言うプラグインもあり、こちらだとSCSSの時と同じ記法で書けますので検討してみてください。
postcss-extend
ref) https://github.com/travco/postcss-extend
SCSSで使っていたextendと同じ記法で書けます。
before
%padding { padding: 10px; } .margin { margin: 10px; } .item { @extend %padding; @extend .margin; }
after
.item { padding: 10px; margin: 10px; }
いかがでしたでしょうか?
PostCSSのプラグインの種類は豊富で、 mixin
の機能を使いたい思った時には上記で書いた様に、 postcss-mixins
, postCSS-sassy-mixins
など複数ブラグインが存在するので、記法やコードを読んで選んでいく必要がありそうですね。
また拡張しすぎると本来のCSSの記法とかけ離れてしまうため使うプラグインは最小限に抑えるべきだと考えます。
We’re hiring!!
Cluexではエンジニアサイド、ビジネスサイド共にメンバーを募集しています! お気軽にご連絡下さいませ! エンジニアの方、ぜひ情報交換しましょう!