葉顆顆
Sudo Ninja
Published in
22 min readAug 20, 2016

--

karote00

AMP

簡單來說,就是加快網頁的 Loading,但除了這個以外,也可以設定想要在 Google Search 所呈現的樣子 ( 範例在這邊 )。

比如說想要在 Google Search 輸入 “Sudo 前端”讓別人看到 Sudo 的前端的職缺,可以在 html 裡面加上 jsonld,如下

<script type="application/ld+json">
{
"@context": "http://schema.org/",
"@type": "Product",
"name": "Front End Engineer",
"image": "https://cdn.com/this_is_image.png",
"description": "Front End Engineer - 好棒棒公司 薪水範圍(年薪): NT$ 600,000 至 900,000 技能要求:javascript,HTML5,CSS3,java,php,AngularJS,Node.js 工作內容:Responsibilities (工作內容)- Be responsible to develop and maintain high quality cons",
"mpn": "925872",
"brand": {
"@type": "Front-End",
"name": "Installments"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.4",
"reviewCount": "89"
},
"offers": {
"@type": "Offer",
"priceCurrency": "USD",
"price": "119.99",
"priceValidUntil": "2020-11-05",
"itemCondition": "http://schema.org/UsedCondition",
"availability": "http://schema.org/InStock",
"seller": {
"@type": "Organization",
"name": "Executive Objects"
}
}
}
</script>

以上是 jsonld 的部分,那剛剛提到的網頁加速呢?那就是要把網頁變成 amp tag 了,不過並不是所有的元件都要改成 amp-xxx 這樣,這裡有 HTML 的 Spec,不過這是第二步,讓我們先回到第一步,也就是先將網站變成支援 amp,很簡單,Copy & Paste就對了,因為這是官方要求一定要有的東西,所以就貼上吧!!

不過 jsonld 和 style 是可以變動的,畢竟不同頁面要用的格式跟樣式不一樣。既然不同頁面要用的東西不一樣,那我們就把東西都拆開吧~~

主頁面的 html 稍微修改一下

<!doctype html>
<html amp lang="en">
<head>
<meta charset="utf-8">
<title>Hello, AMPs</title>
<%= yield :head %>
<%= yield :jsonld_info %>
<style amp-boilerplate>樣式自己隨便放,當作 reset.css 使用比較好</style></noscript>
<script async src="https://cdn.ampproject.org/v0.js"></script>
</head>
<body>
<%= yield %>
</body>
</html>

由以上程式碼可以看到動態區塊有三個: :head, :jsonld_info 和 body 的部分,所以在不同頁面的 html.erb 就可以使用

<!-- head content -->
<% content_for :head do %>

<% end>

<!-- jsonld_info content -->
<% content_for :jsonld_info do %>

<% end>

<!-- body content -->

在不同頁面各自加上要使用的東西,這樣子就不用每個頁面都要做成 amp 了,只在有需要的頁面進行修改即可

好的,到目前為止算是該加的東西都加了,amp 該放的頁面也都放了,那接下來就是要測試了。

測試的時候不可能每次都部署上去,還要上 Google Search 測試,這邊 Google 提供一個簡單的方式,就是在網址後面直接加上 “#development=1”(雙引號請不要跟著加上去!),加了以後重新整理頁面即可,然後就可以到 developer tool 的 console 去看結果了,只要有地方沒有參照 amp 的規則做,通通都會在 console 顯示錯誤,並提示怎樣修改,等全部都修改完之後就大功告成了!!!

ocowchun

How Uber, Airbnb, and Etsy Attracted Their First 1,000 Customers

如果你的平台同時存在者服務方與使用者,你應該優先顧好的對象是服務方 當你的網站上聚集了夠多的好服務方,自然會吸引使用者前來 1. 提高使用者對於服務方的使用體驗,如果你自己都不想使用你平台上的服務方,你怎麼會奢求其他使用者願意去使用這些服務方 2. 對服務方來說,多一個管道曝光來服務,對他來說沒有什麼壞處。 3. 選擇對的地點來擴張你的生意

鳳凰項目

上禮拜看的書,書中談到了尋找工作流中的瓶頸,限制瓶頸的資源使用。在開發軟體專案上,非功能性的需求(安全性,效能,程式碼品質…etc)需要在專案規劃的一開始就納入,如果沒有儘早處理非功能性的需求,計畫外工作(i.e. debug,修機器…)會佔滿你的工作時間。這本書談到不少敏捷與精實的概念,我個人看完這本書的總結是 瓶頸之外的努力都是浪費

Peter

Sketch Measure 改版與應用

image
image

看到有人分享 Sketch Measure 大改版就回鍋使用一番, 發現 Sketch Measure 更新後是一大躍進, 不論是介面或功能都往上提升了一個層級。

image

簡單介紹一下功能:

control + shift + 1: Overlay (疊加圖層)

使用疊加會在圖層上覆蓋一個半透明色塊,主要的目的是要讓元件的 box model 大小更明顯。 這個功能可以與其他標注功能搭配使用。

control + shift + 2:Size (標注長與高)

image
image
image
image

使用後會彈出新版的介面,使用者可以選擇長與高的標注位置。

control + shift + 3:Spacing (標示兩元件之間的空間距離)

image
image
image
image
image
image

選取兩個元件,將會標記出兩元件之間的距離, 這個功能多用標注於子元素於父元素中的位置。 若只選取一個元件操作 spacing, 則會自動以元件和畫布(Artboard)作為測量對象。

control + shift + 4:properties(標注圖層的各種屬性)

image
image

一樣可以勾選想要呈現的屬性,標注的位置。 但要注意,如果是選擇群組的圖層會抓不到子單位的屬性。

image
image

舉例來說: footer 的連結為求排版方便群組起來, 標注連結群組,雖然勾選了顯示全屬性,最後只會呈現 opacity 與 shadow。 選擇群組內的文字圖層,則會顯示所有文字的 properties。

image
image

control + shift + 5:Notes(製作註解)

image
image
image
image

這個功能稍微有點不一樣, 需要先點選一個文字圖層,才會將該文字圖層轉成註解。

control + shift + [:Lite Width

image
image

這個功能讓我有點困惑, 使用之後會讓被選取的元件消失,留下其寬度。

contorl + shift + ]:Lite Height

原理跟 Lite Width 一樣, 只是留下的是高度。

control + shift + C:Name Color

會抓取選取圖層的顏色, 有點類似客製化色票,但是和 property 一樣, 如果選擇的是群組(沒有顏色屬性)會抓不到顏色。

control + shift +E:輸出規格

image
image

這個革新的新功能! 輸出可以選擇想要輸出的畫布, 輸出後會產生一個資料夾,裡面會有 index.html 檔案與切片檔案, 只要在 Sketch 中有製作切片的圖層,都會自動輸出成圖檔。 使用者切片製作的是 png,圖檔就是 png。 切片製作的是 svg,圖檔就是 svg 檔案。

html 檔案在瀏覽器中打開, WOW !介面上可以看到輸出的畫布,切片檔案,可以看到已命名的顏色。 點選元件會顯示尺寸,顯示空間位置。

image
image

是不是很像 Zeplin?其實功能挺相近的, 輸出的方式與 Zeplin 也很相似,而 Zeplin 還自動幫使用者做了許多事。 但我覺得 Sketch Measure 更適合開發協作, 原因在將下面會介紹!

輸出規格的應用

為什麼會輸出成 html 檔案呢? 如果將輸出的資料夾放在 github page上呢?這樣就兼具版本控管, 還可以製作出一個 Zeplin。

問題來了, 一個 Sketch 檔案會輸出成一個資料夾, 資料夾有很多個,而 github page 只會吃到一個 index 檔案, 勢必要在根目錄底下製作一個 index.html 作為索引,

每次更新 mockup 後推上 Github page, 根目錄 的 index.html 不會自動更新, 手動更新雖然不會太麻煩,但如果一次上傳很多不同的 mockups 呢?

解決方案: 請工程師幫忙寫一個非常非常簡陋且髒髒的 npm script, 只要在推上 github page 前跑過 npm script 就會自動爬出所有資料夾, 在根目錄下的 index.html 中新增連結,連到 mockup 資料夾下的 html。

image
image

大功告成! 工程師還貼心地加上了更新時間。

Sketch Measure 應用,結案。 感謝五十嵐古先生提供應用的想法。

Henry

在 React Native 中使用 moment.js 無法載入語系檔案

moment.js 是很常見的日期時間 library,友善的 API 與極佳的執行效率是它的兩大賣點。例如 (new Date()).getFullYear(),如果使用 moment.js 我可以只寫 moment().get(‘year’),可讀性增強許多。

問題

React Native 0.29.x 預設使用 ES6,並支援 import 語法。問題出在如果遵照官方網站的說明去載入語系檔,會發生找不到模組 (cannot find module) 的錯誤。推測可能是 moment.js 從 ES5 移植到 ES6 沒有轉換完全。

import moment from 'moment';
moment.locale('zh-tw'); // 這一行會出錯
console.log(moment.months());

解法

GitHub 上已經有人回報相關錯誤,參考 facebook/react-native#1629 得出以下解法。

import moment from 'moment';
import momentLocale from 'moment/locale/zh-tw'; // 多這一行
moment.updateLocale('zh-tw', momentLocale); // 改這一行
console.log(moment.months());

原理是使用 ES6 的語法將語系檔案手動載入之後使用 updateLocale 手動覆寫。issue 中的 locale([locale_name], [locale_hash]) 已經被 deprecated,必須改用 updateLocale。

當 iTerm 執行完 RSpec 之後彈出通知

問題

我的 Ruby on Rails 專案我都習慣會寫 RSpec,但問題是只要專案一變大,RSpec 就會跑個二到三分鐘,以前我不是傻傻地盯著畫面等它完成,不然就是偷閒跑去看影集,往往把一集看完了才想起來有 RSpec 在執行。

昨天晚上靈機一動,想到之前在學 webpack 時,別人寫的 Yeoman generator 透過 iTerm 的通知功能在 bundle 打包完成通知開發者 (Turbo87/webpack-notifier)。於是我就想,有沒有可能以盡量簡單的方法去解決這樣的問題?

研究

首先,如果可能,我盡可能地不要去寫程式。寫程式的確有它的樂趣,但寫程式不可避免地一定要 debug。如果這些時間成本遠遠地超過問題的複雜度、所造成的困擾,那對我來說沒有任何價值。

於是我第一個想到的是 *iTerm 本身是否有這樣的功能*?StackOverflow 上已經有人提出一樣的問題並也得到了回答 How do I make iTerm terminal notify me when a job/process is complete?,基本上就是設定 Profile > Advanced > Triggers,讓 iTerm 透過 regular expression 比對到特定的字串後觸發通知。

但對於 iTerm Triggers 的介紹到此打住,因為我稍後又針對 RSpec 找到更好的解決方法。

最佳解

twe4ked/rspec-nc — RSpec formatter for Mountain Lion’s Notification Center

原來不只我有這樣的需求,已經有同樣需求的開發者動手寫了一個 gem 來解決這樣的問題。使用方法很簡單,基本上只要照著文件說的安裝就可以直接使用了。

但如果開發的作業系統與部署用的主機不一樣,則還需要一些額外的設定。在將 rspec-nc 加入 Gemfile 時,記得要設定 require: false。在找到 require 這個選項之前,我實驗過好幾個跨平台的解決方案,都沒有成功。不是在 CI 階段失敗,就是在本機跑測試時會發生找不到 formatter 的錯誤 (rspec-nc 以 RSpec formatter 的形式與 RSpec 串接)。

這件事情原作者在 README.md 中沒有特別註明,對此我還特別發送了一個 pull request ([#21 add require option to the line in Gemfile](https://github.com/twe4ked/rspec-nc/pull/21))。

React Native 的升級與排版二三事

React Native 雖然有 React 一詞,但與 React.js 的關係還是僅止於名稱而已。從 0.28.x 開始,flexbox 被調整地更接近 CSS3 標準。在 0.28.x 之前,對一個 <View /> 填上 flex: 1 屬性並不會劇烈地改變 <View /> 的呈現形式。但 0.28.x 之後,flex 屬性開始具備延展性。也就是說,我們不能再隨意地為 <View /> 添加 flex 屬性。*否則在需要 inline 樣式的容器中,所有的元素將被延展*,導致元素與容器一起變形。

[#8691 [0.29] With flexWrap: ‘wrap’, unexpected margin appears between wrapped rows](https://github.com/facebook/react-native/issues/8691)

另外,像標籤這樣需要一個接著一個排成一列的樣式,在 0.28.x 之前只要加上 flexDirection: ‘row’ 與 flexWrap: ‘wrap’ 即可;但 0.28.x 之後,還需要加上 alignItems: ‘left’ (或 alignItems: ‘right’,如果需要靠右對齊的話),在此可以簡單地類比成網頁端的 float: left (或 float: right)。如果不加上這個屬性的話,容器內的元素將會在底部產生成因不明的空白,如 issue 中的截圖所示。

React Native 的觸控區域

樣式上的差異

在 React Native,如果需要觸控區域,我們有兩個選擇:<TouchableWithoutFeedback /> 與 <TouchableHighlight />。根據文件,官方並不希望我們使用前者,原因基於前者不會對觸控產生回饋,會讓使用者對觸控是否有效產生不必要的誤解。

實際使用之後,我發現兩者另外一項區別在於 <TouchableWithoutFeedback /> 沒有預設樣式,實際使用起來就像是一個隱形的容器,包住內部的元素,但又不會與內部的容器互相影響;而 <TouchableHighlight /> 本身則會形成一個區塊,會與內部的元素相互影響。至於之前的版本曾經有使用者提出 <TouchableHighlight /> 可能是為了產生回饋的視覺效果,而有效能上的問題。但在 0.28.x 之後,至少我實際使用到現在還沒有遇到嚴重的效能問題,即使是在最複雜的編輯履歷頁面也沒有。

<View /> 與自訂 component 的規格差異

官方文件建議如果要在 Touchable 系列裡使用多個 component,如以下的形式,直接寫是行不通的。

<TouchableHighlight>
<ChildOne />
<ChildTwo />
</TouchableHighlight>

必須改寫成以下形式。

<TouchableHighlight>
<View>
<ChildOne />
<ChildTwo />
</View>
</TouchableHighlight>

而重點就在這個 <View />。這個 <View /> 在 0.28.x 時不能以自訂的 component 取代。例如以下的程式碼,在 0.28.x 有一定的機率造成 Touchable 失去效果。

const MyComp = ({children}) => (
<View>
{children}
</View>
);

const Touchable = () => (
<TouchableHighlight>
<MyComp>
<ChildOne />
<ChildTwo />
</MyComp>
</TouchableHighlight>
);

如果寫成以上的形式,則 React Native 在執行的時候會展開成以下形式。

const Touchable = () => (
<TouchableHighlight>
<MyComp>
<View>
<ChildOne />
<ChildTwo />
</View>
</MyComp>
</TouchableHighlight>
);

這時候會發生錯誤導致 React Native 無法執行。原因是 <MyComp /> 並不是一個 native component,因此當 Touchable 在為這個 component 注入一些屬性時,會發生某些 <View /> 有定義 function 在自訂 component 中沒有被定義 ([函數名稱] is undefined) 的錯誤。

根據 Direct Manipulation 中的說明,如果要將一個自訂的 component 偽裝 成 native component,則需要實作 setNativeProps 這個 function,然後把 native props 傳遞給要自訂的 component。

但實際測試之後,setNativeProps 的效果並不如預期地是 100% 正常運作。因此建議如果沒有特別的需求,盡量還是直接使用 <View /> 來包裝 child component。

我知道畫面上一堆 <View /> 會讓可讀性變得非常差,否則我們也不需要自己實作自己的 component,但這是目前已知唯一 100% 有效的實作方法。

Kalan

Rails view

最近希望把一些常用的 tag 跟撰寫方式拆成 helper,於是開始去研究 rails 裡面的 view helper method。發現裡面的 helper 撰寫大有學問,這邊跟大家分享:

def link_to(name = nil, options = nil, html_options = nil, &block)
html_options, options, name = options, name, block if block_given?
options ||= {}

html_options = convert_options_to_data_attributes(options, html_options)

url = url_for(options)
html_options['href'] ||= url

content_tag(:a, name || url, html_options, &block)
end

這邊用 link_to 方法舉例,可以看到這邊分成了兩種方式,如果有給定 block 的話,會將傳入的參數作轉換,如果沒有的話,則是將 option 做處理之後,傳給 content_tag 這個方法。注意到這邊的 block_given? 方法,有這個方法我們就可以很容易的判斷是否有傳入 block。

所以在設計 helper 的時候,可以適時包裝這些方法,簡化 helper 的複雜度:

def link_to_with_noopener(name = nil, options = {}, html_options = nil, &block)
html_options.merge!({
:ref => "noopener"
})
if block_given?
link_to(name, options, html_options, &block)
else
link_to(name, options, html_options)
end
end

請參考:About rel=noopener

再來就是 viewhelper 裡面有很多還蠻好用的方法,我們不用再花很大的功夫重造輪子,像是:

不過每次只要一動到 helper 就很容易出包…,但直接用原生的 HTML 不但很醜,又不好維護,所以在撰寫 helper 的時候,為了保險還是寫一下 test 吧!

最近的有個想法是將常用的片段程式碼拆成 partial,*並且用比較統一的方式管理!*,每次接到新的頁面就要先思考哪些會是局部代碼,哪些會是共用代碼。

partial 設計的幾個要點:

經過這次標籤消失的事件,首先先跟顆顆說聲道歉之外,更應該檢討的是以下幾點:

  1. 預設值很重要!
  2. if else 判斷式要思考更全面
  3. 如果害怕沒有預設狀況,就乾脆讓他噴例外

第三點的實作方法如下:

# in component_helper.rb
# ui_component 方法是對 render 的進一步包裝。
def ui_component(url, props = {})
render "components/#{url}", locals: props
end

# in error_helper.rb
def check_required_options!(locals, *options)
options.each do |option|
raise MissingOptionError, %Q{option "#{option.to_s}" is required.} if locals[option].nil?
end
end


private

class MissingOptionError < StandardError
end

然後在 partial 的程式碼裡面:

// in _tags.html.erb
<% check_required_options locals, :propA, :propsB, :propsC %>

這樣如果 locals 裡面的 option 不夠完整,就會在使用的時候噴出例外,不知道這樣的設計夠不夠完整。而且 partial 設計的時候很容易因為時間久的關係,忘記了 locals 裡面的選項,在 partial 裡面養成檢查 locals 的習慣,可以幫助我們補上遺落的 option。不知道這樣的設計夠不夠恰當跟完整?還請顆顆提出意見。 @ocowchun

component 化

這邊的 component 化並不是指全部使用 react 改寫,畢竟我們的頁面也還沒有到這種需求。但是既然 rails 有強大的 partial 機制跟 view heleper 方法,我們可以在撰寫的時候做更進一步的拆分:

<div id="page_id">
<header>
<%= load_component("company_header") %>
</header>
<main>
<aside>
<%= load_component("company_sidebar__header") %>
<%= load_component("company_sidebar__content") %>
</aside>
<%= load_component("company_summary") %>
<%= load_component("company_introduction") %>
<%= load_component("company_section") %>
</main>
<footer>
<%= load_component("company_footer") %>
</footer>
</div>

但其實目前主站的頁面都仍時常變動,所以過早的抽象化反而會浪費更多成本吧!不過未來如果能用這樣的方式來撰寫程式碼,相信應該是非常好維護的!

--

--