会社勤めのソフトウェアエンジニアをしてると管理画面を作る機会が何度かあります。幸いなことに私は作った経験が無いですが欲しい時にシュッと作れるとかっこいいのでrailsとAdminLTEを組み合わせて管理画面のベースを組み立てる手順を記録します。
とりあえずのrails new
rails以外のWAF(Web Application Framework)を知らないのでrailsを使います。知らない言語で書いてみたい気持ちはグッと抑えました。包丁を研いでいると人生は終わってしまうのです。
rails new -h
を見ながら直感と好みで色々とskipしていきます。 ところでRails is omakase1 というDHHがうなぎについて熱く語っているエッセイがあります。
rails new admin-console --database mysql --skip-action-mailer --skip-action-mailbox --skip-action-text --skip-active-storage --skip-action-cable --skip-sprockets --skip-turbolinks --skip-spring --skip-javascript
Simpackerを使う
webフロントエンド開発環境を最高にしようとは思ってないですが、素朴で気の利く感じにしたかったのでSimpackerを導入しました。
Simpackerは初めての利用でしたがGithubレポジトリのInstallationセクションに従って問題なく導入できました。
# Add simpacker to Gemfile
rails simpacker:install
# app/views/layouts/application.html.erb <html> <head> <title>MobileConsole</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> + <%= javascript_pack_tag 'application' %> <%= stylesheet_link_tag 'application', media: 'all' %> </head> <body> <%= yield %> </body> </html>
開発のためrailsのプロセスとwebpackのプロセスを同時に起動させる必要があるようなのでForemanを使います。
# Procfile rails: bin/rails s webpack: ./node_modules/.bin/webpack --watch
はじめてのAdminLTE
管理画面はそれっぽさが何よりも大事なのでCSSフレームワークを使って見た目を演出します。せっかくならモダンな見た目がやる気が出るので"2020 admin css framework"などの検索キーワードで検索しましたが気に入るものが見つからなかったのでAdminLTEにしました。AdminLTEは長い間人気のある管理画面向けのCSSフレームワークです。
Installationのセクションには各パッケージマネージャーのコマンドが書かれているのみでなかなか困りものです。途方にくれながら様々なAdminLTEの導入記事をよんでみるとstarter.html
なるものがあるらしいのでAdminLTEのレポジトリを探すとプロジェクトルートに見つけました。そこで今回の目標をstarter.html
をsimpacker環境で動かすことにしました。ひとまず app/views/layouts/application.html.erb
の中身をstarter.htmlに置き換え、rootのアクセスを適当なControllerに割り当てて見た目が破滅していることを確認しました。
simpackerの設定
見た目が破滅している原因はCSS及びJSが読み込まれていないためなので、simpackerを通して参照できるように色々と設定していきます。
# admin-lte本体を追加 npm install --save admin-lte@^3.0 # admin-lte及びbootstrapの動作に必要なもの npm install --save jquery popper.js npm install --save @fortawesome/fontawesome-free # webpackのcssのbundle環境に必要な依存 npm install --save-dev css-loader mini-css-extract-plugin # jsよりtsが書きなれているのでts環境に必要な依存 npm install --sav-dev typescript ts-loader
webpack.config.js
はsimpackerのexmaple集を参考にして最終的に下記のようになりました。
const path = require("path"); const WebpackAssetsManifest = require("webpack-assets-manifest"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const webpack = require('webpack'); const { NODE_ENV } = process.env; const isProd = NODE_ENV === "production"; module.exports = { mode: isProd ? "production" : "development", devtool: "source-map", entry: { application: path.resolve(__dirname, "app/javascript/application.ts") }, output: { path: path.resolve(__dirname, "public/packs"), publicPath: "/packs/", filename: isProd ? "[name]-[hash].js" : "[name].js" }, resolve: { extensions: [".js", ".ts"] }, module: { rules: [ { test: /\.tsx?$/, loader: "ts-loader", options: { transpileOnly: true } }, { test: /\.css$/, use: [MiniCssExtractPlugin.loader, "css-loader"] } ] }, plugins: [ new WebpackAssetsManifest({ publicPath: true }), new webpack.ProvidePlugin({$: 'jquery', jQuery: 'jquery',}), //グローバル領域にjqueryが必要とされるため new MiniCssExtractPlugin({ filename: isProd ? "[name]-[hash].css" : "[name].css" }) ] };
application.ts
は参考にできるものが全く無かったので試行錯誤しましたが、node_modules以下のディレクトリ構造を確認して相対パスを繋ぐといい感じに認識されるようです。この辺りの仕組みは理解していません。
import 'bootstrap/dist/css/bootstrap.min.css'; import 'admin-lte/dist/css/adminlte.min.css'; import '@fortawesome/fontawesome-free/js/all.min.js'; import 'jquery/dist/jquery.js' import 'bootstrap/dist/js/bootstrap.js'; import 'admin-lte/dist/js/adminlte.min.js';
完成
これまでの変更でそれっぽいViewが表示されるので後は適当に画像パスを書き換えると一番最初の画像になります。結局包丁を研いで疲れてしまい昼寝してたらGW初日は終わったのでこうして日記を書きました。