0
0

Rails6 gem serviceworker-rails で PWA化

Last updated at Posted at 2024-09-17

はじめに

WebアプリケーションをネイティブなアプリのようにできるPWA化に憧れて、実装してみました!
紆余曲折しましたがなんとか完成!
忘れないうちにまとめておこうと思います!

おおまかな流れは、こちらのREADMEを参考にしています↓

前提

Ruby 3.1.2
Rails 6.1.7.7

Rails6以降の記事が少なくて…!苦戦しました💦

Serviceworkerの導入

gem導入

Gemfile.
gem 'serviceworker-rails'
$ bundle install

ファイルはコマンドを実行すれば、自動作成してもらえます

$ rails g serviceworker:install
Running via Spring preloader in process 31804
      create  app/assets/javascripts/manifest.json.erb
      create  app/assets/javascripts/serviceworker.js.erb
      create  app/assets/javascripts/serviceworker-companion.js
      create  config/initializers/serviceworker.rb
The file /home/ec2-user/environment/go_out_planning/app/assets/javascripts/application.js does not appear to exist

application.jsはRails 5.x以前だとassets/javascript/に格納されていましたが、現在Rails6のため下記が出力されます

The file /home/ec2-user/environment/go_out_planning/app/assets/javascripts/application.js does not appear to exist

serviceworker-companion.jsの読み込み

app/assets/javascripts/serviceworker-companion.js
のjsファイルをapplication.jsのあるapp/javascript/packsに移動します

スクリーンショット 2024-09-17 13.39.29.png

次に、application.jsでserviceworker-companionを読み込みます

application.js
import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"

import "jquery";
import "popper.js";
import "bootstrap";
import "../stylesheets/application";
// この行を追加
import '../packs/serviceworker-companion';

Rails.start()
Turbolinks.start()
ActiveStorage.start()

設定

Rails.configuration.assets.precompile += %w[serviceworker.js manifest.json]を最終行に追加

config/initializers/assets.rb
# Be sure to restart your server when you modify this file.

# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'

# Add additional assets to the asset load path.
# Rails.application.config.assets.paths << Emoji.images_path
# Add Yarn node_modules folder to the asset load path.
Rails.application.config.assets.paths << Rails.root.join('node_modules')

# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
Rails.application.config.assets.precompile += %w( admin.js admin.css )

# この行を追加
Rails.configuration.assets.precompile += %w[serviceworker.js manifest.json]

こちらは特に触る必要はありませんでした

config/initializers/seviceworker.rb
# frozen_string_literal: true

Rails.application.configure do
  config.serviceworker.routes.draw do
    # map to assets implicitly
    match "/serviceworker.js"
    match "/manifest.json"

    # Examples
    #
    # map to a named asset explicitly
    # match "/proxied-serviceworker.js" => "nested/asset/serviceworker.js"
    # match "/nested/serviceworker.js" => "another/serviceworker.js"
    #
    # capture named path segments and interpolate to asset name
    # match "/captures/*segments/serviceworker.js" => "%{segments}/serviceworker.js"
    #
    # capture named parameter and interpolate to asset name
    # match "/parameter/:id/serviceworker.js" => "project/%{id}/serviceworker.js"
    #
    # insert custom headers
    # match "/header-serviceworker.js" => "another/serviceworker.js",
    #   headers: { "X-Resource-Header" => "A resource" }
    #
    # anonymous glob exposes `paths` variable for interpolation
    # match "/*/serviceworker.js" => "%{paths}/serviceworker.js"
  end
end

serviceworker.js

この状態で一旦サーバーを立ち上げてみます

$ rails s
[Webpacker] Compiling...
Started GET "/service_worker.js" for 180.0.182.32 at 2024-09-17 05:07:08 +0000
Cannot render console from 180.0.182.32! Allowed networks: 127.0.0.0/127.255.255.255, ::1
  
ActionController::RoutingError (No route matches [GET] "/service_worker.js"):

/service_worker.jsに接続できないよーと言われてますね
ということでservice_worker.jsをpublicの中に作成しましょう

なぜpublicの中なのか?
publicの中に配置することにより、Rails のルーティングを介さずに静的ファイルとして提供でき、url/service_worker.jsで接続することが可能になります!

public/service_worker.js
self.addEventListener('install', function(event) {
  console.log('[Service Worker] Installing Service Worker...');
});

self.addEventListener('activate', function(event) {
  console.log('[Service Worker] Activating Service Worker...');
});

self.addEventListener('fetch', function(event) {
  console.log('[Service Worker] Fetching something....', event.request.url);
});

アドレスバーに~.com/service_worker.jsを打ち込むと、
以下のような画面になっていればOK!

スクリーンショット 2024-09-17 14.15.19.png

検証ツールで確認

Application>Service workersを開いてStatusを確認
ちゃんとactivated is a runningになってますね!

スクリーンショット 2024-09-17 14.17.54.png

manifest.json.erb

/assets/javascript/manifest.json.erb
が現在では読み込まれていないいないので、application.html.erbの<head>部分に<link rel="manifest" href="/manifest.json" crossorigin="use-credentials">を追記していきます!

application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>GoOutPlanning</title>
    <link rel="manifest" href="/manifest.json" crossorigin="use-credentials">

  </head>

  <body>
  :
  </body>
</html>

majifest.json.erbを編集

デフォルトの記述がこちら↓

app/assets/javascripts/manifest.json.erb
<% icon_sizes = Rails.configuration.serviceworker.icon_sizes %>
{
  "name": "My Progressive Rails App",
  "short_name": "Progressive",
  "start_url": "/",
  "icons": [
  <% icon_sizes.map { |s| "#{s}x#{s}" }.each.with_index do |dim, i| %>
    {
      "src": "<%= image_path "serviceworker-rails/heart-#{dim}.png" %>",
      "sizes": "<%= dim %>",
      "type": "image/png"
    }<%= i == (icon_sizes.length - 1) ? '' : ',' %>
  <% end %>
  ],
  "theme_color": "#000000",
  "background_color": "#FFFFFF",
  "display": "fullscreen",
  "orientation": "portrait"
}

今回は下記のように編集↓
iconはサイズ別に複数用意しておく(適当な変換サイトでOK)
assets/imagesに入れておこう!

manifest.json.erb
{
  "name": "おでかけプランニング-GoOutPlanning-",
  "short_name": "GoOutPlanning",
  "start_url": "/",
  "icons": [
    {
      "src": "<%= image_path "go_out_planning_logo_36.png" %>",
      "sizes": "36x36",
      "type": "image/png"
    },
    {
      "src": "<%= image_path "go_out_planning_logo_48.png" %>",
      "sizes": "48x48",
      "type": "image/png"
    },
    {
      "src": "<%= image_path "go_out_planning_logo_72.png" %>",
      "sizes": "72x72",
      "type": "image/png"
    },
    {
      "src": "<%= image_path "go_out_planning_logo_96.png" %>",
      "sizes": "96x96",
      "type": "image/png"
    },
    {
      "src": "<%= image_path "go_out_planning_logo_144.png" %>",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "<%= image_path "go_out_planning_logo_192.png" %>",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "<%= image_path "go_out_planning_logo_512.png" %>",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "theme_color": "#3B4674",
  "background_color": "#FFFFFF",
  "display": "standalone",
  "orientation": "portrait",
  "screenshots": [
    {
      "src": "<%= image_path "screenshot-wide_1472x720.png" %>",
      "sizes": "1472x720",
      "type": "image/png",
      "form_factor": "wide"
    },
    {
      "src": "<%= image_path "screenshot-mobile_640x1280.png" %>",
      "sizes": "640x1280",
      "type": "image/png",
      "form_factor": "narrow"
    }
  ]
}

検証ツールで確認

Application>Manifestを開いて内容が反映されていればOK!

スクリーンショット 2024-09-17 14.49.00.png

スクリーンショット 2024-09-17 14.50.06.png

アプリをインストールしてみる

スクリーンショット 2024-09-17 14.54.04.png

アドレスバーにインストールのマークが出ているのでクリックし、インストールする

スクリーンショット 2024-09-17 14.54.45.png

スクリーンショット 2024-09-17 14.56.05.png

これで開発環境のアプリインストールができました!
あとはデプロイして本番環境でも問題なく動作するか確認しましょう!

本番環境での動作確認

最初に本番環境で確認したら反映されていなかったので、もし同じ方がいらっしゃったらassets:precompileを実行してみるといいかもです!

また、一応UIが非表示かされてはいるのですが、本番環境で/service_worker.jsにアクセスできなくなっていたので修正しておきます

/service_worker.jsに接続できないようですね
ちなみに、アドレスバーにgo-out-planning.net/service_worker.jsを打ち込むと、以下のような画面が出てきます!

スクリーンショット 2024-09-17 12.44.32.png

publicにservice_worker.jsを格納しているはずなのに、出てこない!
というのはこれで一発で解消できます!

config/environments/production.rb
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?

を↓に修正するだけ!

config/environments/production.rb
config.public_file_server.enabled = true

config.public_file_server.enabled の設定を true に変更すると、Rails アプリケーションが静的ファイルを自動的に提供するようになります。具体的には、public ディレクトリにある静的ファイル(例: JavaScript、CSS、画像ファイルなど)が、Rails アプリケーションのサーバーを通じて提供されるようになります。

ただ、今回は小規模なアプリケーション開発のため上記をtrueにしていますが、基本的には非推奨のようです…
もっといい方法あれば是非教えてください🙇

実際のアプリ

さいごに

長くなってしまいましたが、以上がRailsアプリをPWA化するために私が行ったことです!

参照サイト

ありがとうございました!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0