
前回の記事までで、既存プロジェクトのRails5からRails6へのバージョンアップの説明は終わりましたが、今回はタイトルの通り、Railsのwebpackerを使用せず、バックエンドをRails、フロントエンドをwebpackにそれぞれ役割分担させよう!という趣旨の記事になります。
なぜwebpackerを使用しないで役割分担させる必要があるのかも含めて紹介していきます。
目次
webpacker使わない理由
webpackって何?
Rails6からwebpackerがRailsのjavascriptコンパイラとしてデフォルトとなりました。
私はそもそも「webpackって、なんだよ?」というレベルで知りませんでしたので、少し調べてみたところ、
「Webpackは、オープンソースのJavaScriptモジュールバンドルです。主にJavaScript用のモジュールバンドルですが、対応するローダーが含まれている場合、HTML、CSS、画像などのフロントエンドアセットを変換できます。」(wikipedia)
とありました。
うーむ、全然理解できなかったので、いろいろあさってみたところとこちらの記事がとても参考になりました。
フロントエンドエンジニア必見!JavaScript開発現場で人気の「Webpack」とは?
なるほど、JavaScript・css・画像といったwebページを構成するファイルたちを一つにまとめてくれる変換器といったところでしょうか。
そして、JavaScriptを「モジュール」単位に小分けにして管理することが可能となるのが特徴との事です。
webpackerって何?
ここからはwebpackerについてです。
webpackerは、自前でwebpackをRailsに導入せずとも簡単にwebpackをRailsに取り込んで、Railsの仕様と融合させる(押し付ける?)事が出来るようにする為のGemです。
要は、webpackの事をあまり知らなくてもRailsライクにwebpackを利用できるようにしてくれるという事ですね。
また、JavaScriptファイルを呼び出すためのヘルパーメソッドが変わります。
1 2 3 4 5 |
ヘルパーメソッドが変わる これまで <%= javascript_include_tag 'notebook', 'data-turbolinks-track': 'reload' %> webpacker導入後 <%= javascript_pack_tag 'hoge' %> |
なぜwebpackerを使わない?
ここまでの話だと、「便利で簡単なwebpackerでいいんじゃない?」と感じますが、場合によってはそうでもないのです。
以下の参考記事を読んで、そして私自身思った点から理由を紹介します。
①いろんな制約やしがらみが面倒くさい
webpackには「webpack.config.js」というwebpackの設定を管理するファイルがあります。
ファイルの読み込み、出力先、利用するプラグインなどが管理されています。
そんな「webpack.config.js」ですが、「使い方が分かりづらい」という不名誉な特徴も兼ね備えています。
webpackerでは、自分で設定する「webpack.config.js」の代わりに「environment.js」という設定ファイルが置かれ、webpacker の提供するデフォルトの設定が始めから備わった状態になっています。
(下のpixivさんの参考記事を参照)
デフォルトでいい感じに設定してくれているのは良いことなんですが、カスタマイズをする場合に骨が折れるようです。(私はやったことありませんが)
②パッケージアップデートで支障が出る
各関連パッケージはwebpackerに依存しているので、このバージョンが使いたいと思っていてもパッケージの更新を行うにはwebpackerが対応するまで待つ必要があります。
③何が使われていて使われてないのか分かりづらい
下記pixivさんの参考記事内でも書かれている、
「いったい今プロジェクト内でどういう設定の webpack が動いているのかを把握するのが困難になります。」
という状況になってしまい管理面であまりいい状況ではありません…。
【参考記事】
Webpacker使うなら最低限これだけは知っておいてほしいこと
必ず脱webpackerしなければならないのか?
そういうわけでもありません。
上記した点で不満を抱えている場合は脱webpackerをすることにメリットがありますが、逆に上記点になんの支障もないのであれば、あえてする必要はありません。
Rails機能を重視でJavaScriptはあまり使わない、部分的にvue.jsなどを使うくらいのサービスであればwebpackerのままで問題ないと思います。
Rails6のwebpack導入方法
前置きが長くなりましたが、ここから実際の導入方法を紹介していきます。
やる事は、Railsにバックエンドもフロントエンドも任せるのではなく、
・Rails:バックエンド
・フロントエンド:webpack
のように役割分担させるようにし、お互いのしがらみを出来るだけ取り除きます。
また、フロントエンドはvue.jsを利用した開発に切り替えるため、vue.jsの導入も合わせて行います。
導入方法は基本的にこちらの記事を参考にさせて頂きました。本当に感謝したい!
Rails環境でJS , CSSをwebpackで完全に管理する
やったことはこの記事と内容はほとんど同じなんですが、一部異なる部分があるのでそこだけ具体的に説明していきます。
1.脱Railsのフロントエンド
上の記事を参考に以下を進めてください。
「脱Turbolinks」「脱Sprockets」「脱webpacker」
(脱webpackerは導入している方だけです)
2.フロントエンドを切り分ける
こちらも記事を参考にルートディレクトリ直下に「frontend」フォルダを作成してフォルダ構成を作成してください。
(public/assets以下はバンドルファイルが後で自動で出力されるので空のままでOK)
3.Vue・webpack・webpack-dev-serverの導入
ここからは「node.js」「yarn」が導入されている前提になります。
まだの場合は、前回の記事を参考に導入してみてください。
webpack導入の中で「webpack.config.js」を扱う部分が出てきますが、webpack.config.jsはデフォルトでは存在しません。
自前でRailsプロジェクトルート直下(Gemfileと同じ階層)にファイルを作成してあげる必要があります。
上の記事では後からやっていますが「yarn add webpack-dev-server -D」でweb-pack-dev-serverを導入してしまいます。
そして、私のwebpack.config.jsの設定内容は最終的に以下のようになりました。
主にwebpack4のvue.jsに関する記述を追加しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
const path = require('path') const glob = require('glob') const webpack = require('webpack') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const VueLoaderPlugin = require('vue-loader/lib/plugin') const ManifestPlugin = require('webpack-manifest-plugin') let entries = {} glob.sync('./frontend/pages/**/*.js').map(function (file) { let name = file.split('/')[4].split('.')[0] entries[name] = file }) module.exports = (env, argv) => { const IS_DEV = argv.mode === 'development' return { entry: entries, // devtool: IS_DEV ? 'source-map' : 'none', // HMRが重くなる原因なので外した方がいい。 output: { filename: 'javascripts/bundle/[name]-[hash].js', path: path.resolve(__dirname, './frontend/public/assets') }, plugins: [ new VueLoaderPlugin(), new MiniCssExtractPlugin({ filename: 'stylesheets/bundle/[name]-[hash].css' }), new webpack.HotModuleReplacementPlugin(), new ManifestPlugin({ writeToFileEmit: true }) ], module: { rules: [{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } }, { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.sass$/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { url: false, sourceMap: true, importLoaders: 2 } }, { loader: 'sass-loader', options: { implementation: require('sass'), sassOptions: { fiber: require('fibers'), indentedSyntax: true }, }, } ] }, { test: /\.pug/, loader: 'pug-plain-loader' }, { test: /\.(c|sc)ss$/, use: [{ loader: MiniCssExtractPlugin.loader, options: { publicPath: path.resolve( __dirname, './frontend/public/assets/stylesheets/bundle' ), url: false } }, { loader: 'css-loader', options: { url: false, sourceMap: true, importLoaders: 2 } }, 'sass-loader' ] }, { test: /\.(jpg|png|gif)$/, loader: 'file-loader', options: { name: '[name]-[hash].[ext]', outputPath: 'images/bundle', publicPath: function (path) { return 'images/bundle/' + path } } } ] }, resolve: { alias: { vue: 'vue/dist/vue.js' }, extensions: ['.js', '.scss', 'css', '.vue', '.jpg', '.png', '.gif'] }, optimization: { splitChunks: { cacheGroups: { vendor: { test: /.(c|sa)ss/, name: 'style', chunks: 'all', enforce: true } } } }, devServer: { host: 'localhost', port: 3035, publicPath: 'http://localhost:3035/frontend/public/assets', contentBase: path.resolve(__dirname, './frontend/public/assets'), hot: true, disableHostCheck: true, historyApiFallback: true } } } |
もう一つ違いは、「yarn webpack –mode development –config webpack.config.js」コマンドで「public/assets」以下にバンドルファイルとmainfest.jsを出力させます。
4.自前のJavaScript/css呼び出しヘルパータグの実装
Railsの.html.erbからwebpackで生成されたバンドルファイルを呼び出すためのヘルパーメソッドを自前で用意する必要があります。
上の記事を参考に作成します。
5.foreman
お好みで設定してください。
6.Vueの設定
こちらも上の記事を参考にしていきます。
frontend/pages/の中にコントローラーと同じ名前のフォルダを作成します。
その中に、「index.vue」と「プロジェクト名Index.js」というファイルを作成して管理していきます。
・プロジェクト名Index.js
html.erbからヘルパータグで呼び出すJavaScriptファイル
・index.vue
プロジェクト名Index.jsから呼ばれるコンポーネントファイル
まとめ
バックエンドもフロントエンドも全てRailsで無理に管理するよりも、それぞれ切り分けてあげた方が管理・保守面でスッキリします。
少し長くなってしまいましたので、次回、vue.jsを使った具体的な開発方法と、Railsとの通信方法を紹介したいと思います。