惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
博客园_首页
量子位
博客园 - 司徒正美
S
SegmentFault 最新的问题
J
Java Code Geeks
小众软件
小众软件
博客园 - 【当耐特】
The Register - Security
The Register - Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Microsoft Azure Blog
Microsoft Azure Blog
G
Google Developers Blog
Blog — PlanetScale
Blog — PlanetScale
T
Tailwind CSS Blog
博客园 - Franky
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
G
GRAHAM CLULEY
Cyberwarzone
Cyberwarzone
腾讯CDC
Apple Machine Learning Research
Apple Machine Learning Research
V
Visual Studio Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Hacker News
The Hacker News
aimingoo的专栏
aimingoo的专栏
V
Vulnerabilities – Threatpost
P
Palo Alto Networks Blog
Scott Helme
Scott Helme
L
LINUX DO - 热门话题
F
Full Disclosure
D
DataBreaches.Net
Martin Fowler
Martin Fowler
Cisco Talos Blog
Cisco Talos Blog
L
LINUX DO - 最新话题
云风的 BLOG
云风的 BLOG
C
Check Point Blog
T
Threatpost
Google DeepMind News
Google DeepMind News
WordPress大学
WordPress大学
W
WeLiveSecurity
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
有赞技术团队
有赞技术团队
Hugging Face - Blog
Hugging Face - Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
L
Lohrmann on Cybersecurity
Last Week in AI
Last Week in AI
T
Tor Project blog
T
Troy Hunt's Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Security Affairs
SecWiki News
SecWiki News

Nic Lin's Blog

謝明真 - 高效領導力的課後筆記 NFT 開發實戰!基礎智能合約入門 (3) NFT 開發實戰!基礎智能合約入門 (2) NFT 開發實戰!基礎智能合約入門 (1) 如何自我檢測 log4j CVE 漏洞 Rails 如何在資料寫入時記錄來源 IP 位置 如何經營工程師 Youtube 頻道 - Part 8 營收篇 如何經營工程師 Youtube 頻道 - Part 7 酸民文化篇 如何經營工程師 Youtube 頻道 - Part 5 設備器材篇 如何經營工程師 Youtube 頻道 - Part 4 後製剪輯篇 如何經營工程師 Youtube 頻道 - Part 3 文案企劃篇 如何經營工程師 Youtube 頻道 - Part 2 設備器材篇 如何經營工程師 Youtube 頻道 - Part 1 制訂頻道方向篇 如何經營工程師 Youtube 頻道 - Part 0 Rails 中避免 race condition 的最佳實踐(二) Rails 中避免 race condition 的最佳實踐(一) 10 分鐘整合 google sheet 做自動化開發功能週報 經營 Side Project 300 天所帶來的收穫及挑戰 我的 Youtube 影片製作流程 API 設計時必須注意的 HTTP header 底線問題 如何提升你的程式可讀性之實務技巧(三) 如何提升你的程式可讀性之實務技巧(二) 如何提升你的程式可讀性之實務技巧(一) Ruby 中使用 freeze 優化效能的時機 避免 React 中的 useEffect 無限 render 如何在區域網路用 Docker 架設有 SSL 的 Gitlab 從被問到問人,那些我常問的面試問題 [Rails] 如何漂亮寫出可維護的 query (Maintainable Rails Query) 在已知長度情況下優化 slice 的性能 [ReactNative] 如何在 iOS APP 上主動要求用戶評分 Rails 的 scope 為什麼用 lambda? Proc 與 lambda 不同之處 淺談 Active Record 的 Lazy load 特性 Rails 專案搭配 Github Actions 進行 RSpec 自動化測試 JavaScript 中 require, import 的差別及效能 React 效能優化基本招 ES6 箭頭函式 (Arrow functions) 2 個月擁有 6000 用戶 Side project 這樣做(一) 如何讓自己成為失敗的軟體工程師 如何用 Rack::Attack 阻擋 DDOS / 惡意流量 用 OpenSSL 自簽開發用 HTTPS SSL 憑證 為機器加上登入訊息,在 ubuntu 設置登入歡迎詞 Ruby Memoization 性能優化之記憶化 淺談 SSH agent forwarding 和 proxy command 的安全風險與應用 [Rails] Service / Library / Concern 的差異 避免過度的 Defensive Programming 防禦性程式設計 1:1 攪亂器,如何用 Ruby 做可逆推序號 Rails 中的欄位及方法命名原則 [Rails] 用 puma-dev 作為本地開發伺服器 (支援 https 自簽憑證) 將 Rails 專案從手動部屬遷移使用 Capistrano 自動化部屬 工程師提昇自己的教學和簡報技術的方法 [筆記] Rails 3.2 升級 Rails 6.beta 經驗分享 Class method 氾濫帶來什麼問題 RDBMS 課程心得與筆記 常用的 Rails 開發規範 Rest-Client 如何做 Basic Authentication 驗證 [Rails] 何為 tld_lebgth? 遵循 Semantic Versioning 軟體開發語意化版本管理 請直接在 MySQL 裡面直接用 utf8mb4 取代 utf8 如何解決在 awesome print 中遇到 ActionController::Parameters unable to convert unpermitted 如何在 Mac 上升級 PostgreSQL 並遷移資料 如何解決 Mysql2::Error: Incorrect string value 讀書心得 - 「信任因子:信任如何影響大腦運作、激勵員工、達到組織目標」 我是如何寫部落格筆記的 讀書心得 - 「先問,為什麼?:顛覆慣性思考的黃金圈理論,啟動你的感召領導力」 [Rails] 解決 Reset Password 帶來的 token 洩漏問題 我的軟體工程師生涯:如何挑選適合你的公司 Rails 中的 delegate 用法 淺述 SSR SPA 優缺點 Rails 非同步工作請用 Global ID [React] Class Component 傳遞 props 的 2 種方式 好用的隱私權政策 URL 自動生成 Rails 5.1 之後的 tag helper Rails 5.2 Encrypted Credentials 最近面試被給的建議和書單 一般架構需要用到 K8S 嗎 透過 commit SHA 找 github Pull request 從零搭建,如何讓 Rails 跑在 Kubernetes(k8s)(二) 從零搭建,如何讓 Rails 跑在 Kubernetes(k8s)(一) React Stateless Functional Components 搞懂 React 中的 state 和 props 物件導向基本原則 SOLID (Ruby Sample) 在以太坊智能合約上是可以預測隨機數的 在台灣租屋必須注意的事 Rails 5 簡單雙向加解密 如何用 ABA 培養自律型員工 不要在 rake task 中定義 method, 請用 RAKE::DSL rails 非hash只想用array輸出page 如何處理陣列裡有重複的值 [Rails] 如何重設你的專案名稱 Ruby on Rails install on Mac 安裝步驟 使用 Friendly_id 與 Babosa 美化你的Rails 網址 Junior Rails 兩個月實戰心得 Devise使用Google實作登入 [iterm2] 如何新增alias 一個新鮮人找尋Rails工作的面試經驗 如何讓兩個資料表建立關聯 routing 的 namespace strong parameter user story 的格式 user story 是什麼?
在 Rails 內輕量使用 Vue Component 的最佳實踐
Nic Lin · 2020-02-22 · via Nic Lin's Blog

在維護一陣子的 Rails 專案上,難免會看到各處擺放的 JavaScript function 或是 jQuery 各種直接操作 DOM 之類的作法。

在這個前端技術大時代,為了因應更複雜的 UI 需求,有更多易於擴充、提升效能的作法能夠選擇,例如 React / Vue 之類的前端框架。

要解決什麼問題

  • 避免直接操作 DOM
  • 更易維護及套件管理
  • UI 易於管理 LifeCycle

在 Rails 5.1 之後,已經對 webpakcer 有相當好的支持性,在後面的 Rails 6 版本也已經變為預設的前端工具了

那麼在 Rails 專案中陳年已久的 jQuery + Asset pipeline,要怎麼樣才能夠跟這些新技術接軌呢

在有限的資源下要整個重寫,或許共存也是一種選擇。

在這篇文章中,我們的目標是將前端框架,以輕量導入的方式和 Rails 共存

這裡使用 Vue 做為示範,你也可以引入其他框架例如 React 來整合前端技術

怎麼不直接做前後端分離

前後端分離要考慮的事情很多,除非產品有強烈的需求,或是在資源狀況足夠的情況下是可以規劃的,不然很容易變成「前後端分裂」

對於 Rails 來說,你的前後端分離可能會遇到這些事情

  1. 原本好用的 session 要另外處理
  2. Server side rendering(SEO?)

以現有專案開始

加入 gem "webpacker"

直接執行指令來安裝 vue 的相依 JS 套件

rails webpacker:install:vue

這時候你會看到新的目錄

/app/javascript
├── app.vue
└── packs
    ├── application.js
    └── hello_vue.js

packs 下面放的檔案可以當作一個「入口點」,也就是和 asset pipeline 中的 Manifest 一樣。

差別在於你在 layout 中引入時語法有些不同

# Webpacker
<%= javascript_pack_tag 'application' %>

# Asset pipeline
<%= javascript_include_tag 'application' %>

我們可以在 app/javascript/packs/application.js 中修改

import Vue from 'vue/dist/vue.esm'

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    el: '[data-behavior="vue-app"]'
  })
})

然後在 app/views/layouts/application.html.erb 中加入 <%= javascript_pack_tag 'application' %>

並且新增 data-behavior="app" 將 Vue 掛載在 DOM element 上(官方不建議掛在 body 上,別這麼懶 XD)

<body>
  <div class="container" data-behavior="vue-app">
    <%= yield %>
  </div>
</body>

打開有用到該 layout 的頁面,應該可以看到瀏覽器 console 顯示 You are running Vue in development mode.

那就可以開始來用 Vue 開發我們的 JS 元件了

Vue component

新增 app/javascript/components/Message.vue

<template>
  <div class="message">
    {{message}}
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      message: "Vue card"
    }
  }
}
</script>

並修改 app/javascript/packs/application.js

import Vue from 'vue/dist/vue.esm'
+ import Message from "../components/Message"

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
+    el: '[data-behavior="vue-app"]',
+    components: { Message }
  })
})

這時候你可以在 .erb 裡面插入 Vue 的 component,例如在 app/views/home/index.html.erb

就可以這樣寫

<message></message>

所以如果元件是 MessageCard,在 .erb 裡面就寫 message-card

也因為這樣,你在 app/javascript/ 下的 vue component 是可以和 rails 共享 CSS 的

所以你可以在 asset pipeline 寫 SCSS,在 webpakcer 裡面寫 JS 是可以共存的

直接從 Rails 給 props

有時候一些 JS 元件在初次渲染時,會沒有預設資料,這時候因為是這種 hybird 的寫法,所以你可以透過 controller 先拿好資料,在 view 的部分直接將 props 給 vue component

Ruby 部分
# Message controller
@message = Message.find(params[:id])

# Message View
<message :message="<%= @message.to_json %>"></message>

因為你拿出來的 @message 是 ruby object,這邊可以直接轉 JSON 餵給 component,要更方便的作法就是直接在 controller 內先 serialize 也是不錯的方向。

JS 部分
<template>
  <div class="message">
    <ul>
      <li>ID: {{ message.id }}</li>
      <li>email: {{ message.user.email }}</li>
      <li>content: {{ message.content }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  props: ["message"],
}
</script>

基本上到這裡,你可以在 Rails 的基礎上,使用前端框架來開發更多的 component,以現在這種 MVVM 雙向綁定加上不用直接操作 DOM 做渲染的方式,在未來協作或管理更複雜的資料流及 UI 都是有一定程度的幫助。

正常來說能寫 ES6 就不會想寫原本的 JS,能有 MVVM 就不想回去自己到處綁 element 了

Hybird 做法的優缺點

優點

這樣一來,可以慢慢抽換原本舊有的作法,不用再擔心因為到處寫 jQuery 來做 UI flow 而導致難以維護的問題

  1. 可以直接餵 props 而不用 API 請求
  2. 可以用 Rails cache
  3. 可以用 Rails session

缺點

1. I18n 處理

大致上兩種作法

  1. 和 JS 放在一起(比較推薦的作法)
  2. 全部寫在 Rails 裡面,然後倒出來用轉 JSON 餵過去,優點是只要維護一套,缺點是如果語系檔很大會非常慢,後期要單獨將前端拆出去時還要擔心語系耦合問題
2. 前後端混在一起寫

你沒辦法直接招前端工程師變成及戰力,除非他也會 Rails,不然就還要花時間帶了 XD

小結

用這種方式將 UI 邏輯丟給更適合解決問題的框架來做更方便,不管是效能或是撰寫方式都更好,不然常常看到 Rails 裡面各種綁 element 然後到處操作 DOM 真的很頭痛。