Ruby
webpack
hanami

Hanamiでwebpackを使う方法

Hanamiでwebpackを使う方法を説明していきます。

プロジェクトの作成

mkdir hanami-webpack
cd hanami-webpack
Gemfile
# frozen_string_literal: true
source "https://rubygems.org"

gem "hanami", "1.0.0"
bundle install
bundle exec hanami new .
bundle install

ページの作成

bundle exec hanami g action web page#home
apps/web/config/routes.rb
- get '/page', to: 'page#home'
+ get '/home', to: 'page#home'
apps/web/templates/page/home.html.erb
<h1>Home</h1>

<div id=hello></div>

サーバ起動

bundle exec hanami s

localhost:2300/homeを開けば Homeと表示されるはずです。

Assetsの削除 

Assetsは使わないので削除しましょう。

rm -rf apps/web/assets
apps/web/application.rb
- require 'hanami/assets'

...

- assets do
-   javascript_compressor :builtin
- 
-   stylesheet_compressor :builtin
- 
-   sources << [
-     'assets'
-   ]
- end

...

  configure :production do
-   assets do
-     compile false
-     fingerprint true
-     subresource_integrity :sha256
-   end
  end

webpackの導入

ここから先はapps/webに移動して作業します。
今どこのディレクトリにいるかをよく確認しながら作業してください。

cd apps/web
yarn init
yarn add webpack assets-webpack-plugin --dev
yarn add jquery
apps/web/webpack.config.js
var path = require('path');
var webpack = require('webpack');
var assetsPlugin = require('assets-webpack-plugin');

module.exports = {
  entry: './frontend/application.js',
  output: {
    path: path.resolve(__dirname, '..', '..', 'public'),
    filename: 'bundle_web-[hash].js'
  },
  plugins: [new assetsPlugin()]
};
mkdir frontend
apps/web/frontend/application.js
$ = require('jquery');

$('#hello').after('hello webpack');
webpack

これでプロジェクトファイル直下のpublicにbundle_web-aaaaaaaaa.jsファイルが、
apps/web以下にwebpack-assets.jsonができるはずです。

gitを使う場合はこの段階で.gitignoreを以下のように設定しておくと良いでしょう。

.gitignore
/apps/*/node_modules
/apps/*/webpack-assets.json
/public/bundle*

bundle_web.jsの読み込み

apps/web/views/application_layout.rb
  module Web
    module Views
      class ApplicationLayout
        include Web::Layout
+ 
+       def script_for(bundle)
+         path = Web::Application.configuration.root.join('webpack-assets.json')
+         file = File.read(path)
+         json = JSON.parse(file)
+         json[bundle]['js']
+       end
      end
    end
  end
apps/web/templates/application.html.erb
  <!DOCTYPE html>
  <html>
    <head>
      <title>Web</title>
-     <%= favicon %>
    </head>
    <body>
      <%= yield %>
+
+     <script type="text/javascript" src="#{script_for('main')}" charset="utf-8"></script>
    </body>
  </html>

これでlocalhost:2300/homeを開けば hello webpackと表示されるはずです。

もしもEvalErrorがおきたら

hello webpackと表示されず、ブラウザのコンソールに以下のようなエラーが出ていた場合の対処です。

Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy

apps/web/application.rb
  security.content_security_policy %{
    form-action 'self';
    frame-ancestors 'self';
    base-uri 'self';
    default-src 'none';
-   script-src 'self';
+   script-src 'unsafe-inline';
    connect-src 'self';
    img-src 'self' https: data:;
    style-src 'self' 'unsafe-inline' https:;
    font-src 'self';
    object-src 'none';
    plugin-types application/pdf;
    child-src 'self';
    frame-src 'self';
    media-src 'self'
  }

これで行けるはずです。