iT邦幫忙

2022 iThome 鐵人賽

DAY 14
0
Modern Web

Rails,我要進來囉系列 第 14

第十四天:實驗用 Asset Pipeline 打包 js+css+font+image 資源檔

  • 分享至 

  • xImage
  •  

開場白

鼬~~哩賀,我是寫程式的山姆老弟,昨天跟大家一起看了 RailsGuide 的 AssetPipeline,今天來做點實驗,試試看完全用 AssetPipeline 來打包各種資源檔吧,夠夠~

創個實驗用的專案

因為 Rails 6 開始就改成預設使用 webpacker 打包 js 了,我們就時間倒帶,回到 Rails 5 的時代來做這個實驗吧,是說 Rails 5 要用 ruby 2.x 版本才行,麻煩的是 M1 Macbook 已經不是 Intel 平台,而是 ARM 平台,而 ARM 平台要安裝 ruby 2.x 版本需要一點技巧,這邊先不講,總之為了安裝舊版本的 ruby 也是撞了不少牆,幸好有成功破牆,才有這一篇 XD,如果你不是 M1 macbook 的話,恭喜你,這篇很簡單

我這邊使用的是 Rails 5.2.8.1 + ruby 2.6.5

  1. $ rails new test_asset_pipeline

  2. $ bundle install

    這邊我也遇到安裝 sqlite3pg gem 失敗的問題,總之後來我改在本地安裝舊版 postgres 才搞定,我把 workaround 記錄下來,給大家參考

    1. sqlite3 改成 pg

      # Gemfile
      gem 'sqlite3' # 這行不要
      gem 'pg'
      
    2. $ bundle install,安裝到 pg 時報錯

    3. 安裝舊版 postgres: $ brew install postgresql

      ps. 新版 postgres 是 $ brew install postgresql@14

  3. $ rails db:create (我是連我本地的 postgres container)

  4. $ rails db:migrate

  5. 啟動 $ rails s,打開瀏覽器 127.0.0.1:3000,確認基本頁面有沒有出來

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day14-1.png

建立個實驗場地

  1. $ rails g controller home index

  2. home_controllerindex action 改成首頁

    Rails.application.routes.draw do
      root 'home#index'
    end
    

實驗一:用 AssetPipeline 打包 CSS

  1. 檢查 app/views/layouts/application.html.erb 的引用 tag 是否為 stylesheet_link_tagjavascript_include_tag

    <!DOCTYPE html>
    <html>
      <head>
        <title>TestAssetPipeline</title>
        <%= csrf_meta_tags %>
        <%= csp_meta_tag %>
    
        <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
        <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
      </head>
    
      <body>
        <%= yield %>
      </body>
    </html>
    
  2. 重新命名副檔名 app/assets/stylesheets/application.cssapp/assets/stylesheets/application.scss

  3. 然後在剛剛生成的 app/assets/stylesheets/home.scss,新增一點樣式

    // app/assets/stylesheets/home.scss
    
    h1 {
        background-color: green;
    }
    
  4. 啟動 $ rails s,打開瀏覽器 127.0.0.1:3000,確認 h1 有沒有變綠色背景

  5. 成功~

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day14-2.png

實驗二:用 AssetPipeline 打包 JS

  1. 把 Gemfile 的 coffee script 拿掉,只是因為我不喜歡 coffee script

    # gem 'coffee-rails', '~> 4.2'
    
  2. 將一開始生成的 app/assets/javascripts/home.coffee 重新命名改成 app/assets/javascripts/home.js

  3. app/assets/javascripts/home.js 新增一點簡單功能

    console.log('home.js loaded')
    
    function clicked() {
      console.log("Clicked in home.js")
    }
    
  4. app/views/home/index.html.erb 呼叫看看 clicked()

    <h1>Home#index</h1>
    <p>Find me in app/views/home/index.html.erb</p>
    
    <%= button_tag '按我', onclick: 'clicked()' %>
    
  5. 啟動 $ rails s,打開瀏覽器 127.0.0.1:3000,確認按鈕有沒有用

  6. 成功~

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day14-3.png

因為我很好奇,這樣只能在 home.html.erb 呼叫 home.js 裡的程式嗎?所以我做了下面的實驗

實驗三:測試各個 JS 的互通性

  1. 除了原本的 app/assets/javascripts/home.js 之外,再新增兩個 js 檔,並且都取名一樣的 function,想測試看看各個檔案之間的聯通、衝突

    • app/assets/javascripts/other.js

      console.log('other.js loaded')
      
      function clicked() {
        console.log("Clicked in other.js")
      }
      
    • app/assets/javascripts/special/special.js

      console.log('special/special.js loaded')
      
      function clicked() {
        console.log("Clicked in special/special.js")
      }
      
  2. 啟動 $ rails s,打開瀏覽器 127.0.0.1:3000,確認按鈕是呼叫到哪一個

  3. 如果是取名一樣的 function,答案最後一個被 load 的 function 會被執行

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day14-4.png

看來用 AssetPipeline 打包後的 JS,不管放在哪個檔案裡,裡面的內容都可以被 view 使用到的,這樣的特性跟我們前兩天用 webpacker 測出來的結果,真的是差很多,完全是不同的使用情境

實驗四:用 AssetPipeline 打包圖片

  1. 將一張圖片 test-img.jpeg 放到 app/assets/images 資料夾底下

  2. app/views/home/index.html.erb 使用剛剛那張圖片

    <!-- app/views/home/index.html.erb -->
    <h1>Home#index</h1>
    <p>Find me in app/views/home/index.html.erb</p>
    
    <%= button_tag '按我', onclick: 'clicked()' %>
    
    <%= image_tag 'test-img.jpeg', width: 300 %>
    
  3. 啟動 $ rails s,打開瀏覽器 127.0.0.1:3000,確認圖片有沒有顯示出來

  4. 成功~

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day14-5.png

實驗五:用 AssetPipeline 打包字型

  1. 沿用上次 webpacker 實驗用的開源字型,ChenYuluoyan-Thin.ttf,手動建立 app/assets/fonts 資料夾,再把字體放到這資料夾底下

  2. app/assets/stylesheets/home.scss,對 p tag 新增字型的 css

    // app/assets/stylesheets/home.scss
    @font-face {
        font-family: 'ChenYuluoyan';
        src: asset_path('fonts/ChenYuluoyan-Thin.ttf')
    }
    
    p {
        font-family: 'ChenYuluoyan';
    }
    
  3. 啟動 $ rails s,打開瀏覽器 127.0.0.1:3000,確認字型有沒有出現

  4. 成功~

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day14-6.png

後記:後來發現其實 css 中的@font-face 是多餘的 …,我原本是好奇 asset_pathasset_url 的差別,後來直接刪掉整個 @font-face,竟然也能正常運作

實驗六:嘗試以 production 環境來驗證打包結果!

  1. $ RAILS_ENV=production rails assets:precompile

    Yarn executable was not detected in the system.
    Download Yarn at https://yarnpkg.com/en/docs/install
    I, [2022-09-20T22:07:55.736385 #5884]  INFO -- : Writing /Users/unclesam/Projects/fullstack/test_asset_pipeline/public/assets/ChenYuluoyan-Thin-1f04002cc0906d2bda376fb133d4a8160805db0113e92baf6da54aeafde88bd7.ttf
    I, [2022-09-20T22:07:55.739546 #5884]  INFO -- : Writing /Users/unclesam/Projects/fullstack/test_asset_pipeline/public/assets/ChenYuluoyan-Thin-1f04002cc0906d2bda376fb133d4a8160805db0113e92baf6da54aeafde88bd7.ttf.gz
    I, [2022-09-20T22:07:55.742626 #5884]  INFO -- : Writing /Users/unclesam/Projects/fullstack/test_asset_pipeline/public/assets/test-img-783a001450a67aed38acd2b8cadbe0631b4f0280839de1126d49b91478a8e883.jpg
    I, [2022-09-20T22:07:55.767670 #5884]  INFO -- : Writing /Users/unclesam/Projects/fullstack/test_asset_pipeline/public/assets/application-87e3832199ffcf55124fefb14df62d5524cdb2342b18e4c5639c38002711b5fa.js
    I, [2022-09-20T22:07:55.767891 #5884]  INFO -- : Writing /Users/unclesam/Projects/fullstack/test_asset_pipeline/public/assets/application-87e3832199ffcf55124fefb14df62d5524cdb2342b18e4c5639c38002711b5fa.js.gz
    I, [2022-09-20T22:07:55.774531 #5884]  INFO -- : Writing /Users/unclesam/Projects/fullstack/test_asset_pipeline/public/assets/application-013fdab431408ce5410b4b64a703ede8dd70c5977fcc1afdc47a8a08385ac518.css
    I, [2022-09-20T22:07:55.774602 #5884]  INFO -- : Writing /Users/unclesam/Projects/fullstack/test_asset_pipeline/public/assets/application-013fdab431408ce5410b4b64a703ede8dd70c5977fcc1afdc47a8a08385ac518.css.gz
    

    從打包的 log 看起來,有看到 js, css, font, image 的身影,應該是都有包進去

    ps. 注意這邊打包出來是 jpg,而我放進去的是 jpeg,這一個小小的細節,將會造成接下來實驗發生的錯誤

  2. public/ 裡的各個資料夾檢查一下,是不是該包的都有在該放的位置

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day14-7.png

    public/assets 底下有 css、js、圖片、字型檔,看起來好像 OK~

  3. 因為有上次 webpacker 實驗的經驗,以 production 環境啟動,要多帶一個環境變數 $ RAILS_ENV=production RAILS_SERVE_STATIC_FILES=true rails s,打開 127.0.0.1:3000,檢查畫面

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day14-8.png

    結果這時報錯了,回去檢查 log 怎麼寫,$ tail -f -n 50 log/production.log

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day14-9.png

    驚奇的發現,怎麼會沒有 test-img.jpeg 這個圖片檔呢!? 回去看了 public/assets 底下打包後的圖片檔,就看到了打包後自動變成了 test-img-xxx.jpg 的檔案,竟然擅自幫我改副檔名,嘖嘖嘖,所以就只好改成用 jpg 囉

    <!-- app/views/home/index.html.erb -->
    <h1>Home#index</h1>
    <p>Find me in app/views/home/index.html.erb</p>
    
    <%= button_tag '按我', onclick: 'clicked()' %>
    
    <%= image_tag 'test-img.jpg', width: 300 %>
    
  4. 這時候重新啟動 $ RAILS_ENV=production RAILS_SERVE_STATIC_FILES=true rails s,整個畫面就正常了!真是太神奇了山姆

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day14-10.png

    會發現 production 環境使用打包後的 header,就只剩下引用 application-xxx.cssapplication-xxx.js 了,這就是打包後的樣子

總結

該怎麼說呢,這次的實驗還是有點讓我意料之外 XD,第一點是各個 JS 檔案之間竟然是互通的,第二點是圖片的副檔名在打包後竟然會變,下次在部署 production 專案的時候需要再多注意一點,第三點是字型的引用竟然不需要設置 @font-face,做完實驗之後,我還是不懂為什麼可以不用加 @font-face ?,之後再多留點心眼在打包上吧,總之就先這樣拉,我們明天見~


上一篇
第十三天:關於 Asset Pipeline 打包那回事
下一篇
第十五天:用 webpacker 使用第三方前端套件
系列文
Rails,我要進來囉30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言