はじめての管理画面

会社勤めのソフトウェアエンジニアをしてると管理画面を作る機会が何度かあります。幸いなことに私は作った経験が無いですが欲しい時にシュッと作れるとかっこいいのでrailsとAdminLTEを組み合わせて管理画面のベースを組み立てる手順を記録します。

f:id:kazy1991:20200502232117p:plain
最終的な完成イメージ

とりあえずの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を導入しました。

techlife.cookpad.com

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フレームワークです。

github.com

Installationのセクションには各パッケージマネージャーのコマンドが書かれているのみでなかなか困りものです。途方にくれながら様々なAdminLTEの導入記事をよんでみるとstarter.html なるものがあるらしいのでAdminLTEのレポジトリを探すとプロジェクトルートに見つけました。そこで今回の目標をstarter.html をsimpacker環境で動かすことにしました。ひとまず app/views/layouts/application.html.erb の中身をstarter.htmlに置き換え、rootのアクセスを適当なControllerに割り当てて見た目が破滅していることを確認しました。

f:id:kazy1991:20200502233834p:plain
破滅したstarter.html

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初日は終わったのでこうして日記を書きました。

f:id:kazy1991:20200502232117p:plain
完成したstarter.html