炸蝦碎碎念。

[Notes, GNU/Linux, Open Source, Ruby on Rails, Computer Science, Archlinux]

Web入門:使用Sinatra

緣起

常常被問,想學做網站,要從什麼開始學?不會XXX可以學OOO嗎?通常我遇到的都是原本有電資背景(會寫點C語言之類的),但是對Web Development沒有什麼概念的人。這篇趁這個Sinatra讀書會的機會,來介紹一下整個Web的概念,還有前端、後端到底在說什麼?以Sinatra來當範例,這樣介紹起來更具體。

Internet與World Wide Web

現在的人說「上網」,通常是用網頁瀏覽器看網站。不過Internet(網際網路)的概念,跟World Wide Web(常見於網紙的www)是兩個不同的概念。Internet指的是網路架構本身,全世界不同的區域網路(交大宿網、Hinet、TANET等等)連在一起,這樣我們就可以跟許多國家的伺服器交換資訊。www是建基於Internet的其中一種服務。其他還有telnet、smtp、imap、ftp等等其他協議。www是一種透過網際網路,存取放在遠端伺服器上的檔案的一種服務,正式的協議名稱叫做HTTP(HyperText Transfer Protocol 超文本交換協議)。所謂的超文本,就是html這個Markup Language,來呈現豐富的內容,而不是純文字。還透過超連結讓大家可以上網連來連去。這裡只是簡單介紹,維基百科跟其他各個地方都有詳細介紹。

URL

URL(Uniform Resource Locator),就是在網址列上的那行字串,大概包含以下:(以交大資工網站 https://www.cs.nctu.edu.tw/cswebsite/ 為例)

  1. 協議,通常是http或https,後者是經過SSL加密的HTTP協議。
  2. 域名,網址的/之前的那串(www.cs.nctu.edu.tw),也就是主機名稱,代表要到哪個伺服器獲得資源。
  3. port號,預設的port 80(http)跟port 443(https)不會在URL中顯示,如果要用預設之外的port,比如說localhost:3000,就在域名之後加上去就好。
  4. 路徑,資源的路徑,這裡是cswebsite,就是跟伺服器說我要cswebsite的這個東西。有點像檔案跟資料夾的概念,如果沒有加上檔案名稱,通常就是index.html、index、main.index等等,這裡就是到cswebsite底下找到index.php)
  5. 後面還會有一些參數,比如說錨(#開頭的tag)還有一些給伺服器的參數,通常以問號開頭,如?blablabla

介紹HTTP

所以,我們上網的過程是這樣的:我們打開瀏覽器,輸入URL,這時候發生的事情如下:

  1. 瀏覽器向DNS Server解析URL中的域名,轉換成IP位址。
  2. 瀏覽器向得到的IP位址,傳送HTTP Request到80 port(http服務的標準port),告訴遠端伺服器,透過URL我要什麼資源
  3. 伺服器傳HTTP Response回瀏覽器,就是你看到的網站。可以用Firebug或Firefox、Chrome內建的除錯工具,觀察Requests跟Responses。

Firebox Screenshot

HTTP Request有GET、POST、PUT、PATCH、DELETE等等幾個常見的Verb。最常見到的是GET跟POST。

GET

GET顧名思義就是從伺服器獲取指定資源,此資源就以URL指定,因此相關的參數都會寫在網址上。

1
2
3
4
5
require 'sinatra'

get '/hello' do
  "Hello, world!"
end

在這範例中,當使用者GET了server上/hello這個資源,就會回傳hello, world!。

Hello Screenshot

這裡再來示範一下URL parameter。

1
2
3
4
5
6
7
get '/hello' do
  if params[:name]
    return "hello, #{params[:name]}"
  end

  return "hello"
end

GET Param Screenshot

POST

POST則用於上傳資訊到伺服器上,通常配合html表單使用。例如登入、填寫個人資訊、購物等等。以下是個簡單的範例,當然,真正的使用者驗證沒有那麼簡易。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
require 'sinatra'

get '/login' do
'
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Form Test</title>
    <meta charset="utf-8">
  </head>
  <body>
    <form action="/login" method="post">
      <label for="username">Username</label>
      <input type="text" name="username"></input>
      <br>
      <label for="password">Password</label>
      <input type="password" name="password"></input>
      <br>
      <button type="submit">Submit</button>
    </form>
  </body>
</html>
'
end

post "/login" do
  if params[:username] = "foo" and params[:password] == "bar"
    return "You are successfully logged in."
  end

  return "incorrect username or password."
end

post screenshot 1

post screenshot 2

post screenshot 3

其他HTTP Verbs

其他的HTTP verbs可以參考這幾篇文章

HTTP Verbs: 談 POST, PUT 和 PATCH 的應用

重新認識HTTP請求方法

Web的前端、後端

常常聽到寫Web的人說,我是前端工程師(Frontend)、我是後端(Backend)工程師,甚至也有全端(Full Stack)工程師的說法。所謂Web的前端後端是什麼意思呢?

(雖然現在常常用frontend developer、backend developer來略稱Web [front,back]end developer,但是我覺得除了在Web相關討論之外,還是不要略稱。jserv表示:我都寫compiler的frontend跟backend,可不可以去應徵全端工程師 XD)

Frontend

所謂Frontend,就是網站中,在瀏覽器上跑的部份,也就是在Client端執行。所以只有包含前端資料,而沒有跟伺服器後端動態互動的網站,就叫做Static Website,只要簡單的檔案存取就可以提供服務了。基本元件包含了Html、Javascript、CSS等。網站的樣式、特效、動畫、設計,都可以算在前端的部份。這幾年Javascript的蓬勃發展,讓前端可以做的事情越來越多。

除了html、Javascript、CSS本身之外,前端也包含很多幫助寫前端的語言,可以compile成html、javascript、CSS。常見的有

  1. html的haml、slim等等。
  2. CSS的sass、scss、less等等。
  3. Javascript的coffee script、Livescript等等。

前端也有很多framework或工具幫助開發:

  1. javascript framework: jQuery、prototype.js
  2. UI Framework: jQuery UI、jQuery mobile、react.js
  3. CSS Framework: boostrap、Semantic UI
  4. Frontend Framework: angular.js、Ember.js

還有很多各種javascript的library,需要什麼功能可以先google一下看有沒有現成的工具幫助開發,通常都是開放原始碼的。如果有能力,也可以把程式貢獻給社群。

逐一介紹這些元件:

html

html全名是hypertext markup language,是網站不可或缺的一部分。所有頁面的組成都是html,一般來說現在的觀念是,html負責內文、段落編排、分區等等,不要做樣式在上面。html以tag來當作基本元件,想要學習的話可以上codecademy或者是mozilla developer’s network學學看。

一個html文件的架構如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>
<head lang="en">
    <!-- this is a comment -->
    <title>Page title goes here</title>
    <meta charset="utf-8">
    <script src="/scripts/jquery.min.js"></script>
    <script>
        console.log("hey");
    </script>
    <link rel="stylesheet" type="text/css" href="bootstrap.min.css">
</head>
<body>
    <h1>hello</h1>
    <div id="foo" class="container">
        <a href="https://www.google.com">google</a>
        <img src="/test.png" style="width: 100%; height:auto;">
    </div>
    <div id="bar" class="container">
    </div>
</body>
</html>

有些tag需要打開跟關起來(通常是區塊的tag),有些不用。所有屬性都用雙引號包住,等號兩邊不留留空。style盡量寫在附加的檔案,盡量不要寫在html元素中。這裡就不贅述html本身,網路上資料很多。

每個元素可以有id跟class作為識別,id是唯一的,而class可以拿來分類元件。

css

html不負責樣式,樣式就給CSS(Cascading Style Sheet)來搞定。CSS利用html個元件的class跟id屬性來定義頁面的樣式。比如說顏色、尺寸、位置、字型、效果等等豐富的功能。

CSS以selector的方式指定元件的style。可以用元件名稱、id、class來指定。每個屬性結尾用分號結束,用冒號指定內容。

1
2
3
4
5
6
7
8
.container {
    background-color: blue;
}

#foo {
    width: 1000px;
    padding: 10px;
}

javascript

html跟css只提供靜態的外觀跟內文,在Client端要作到的邏輯部份,就由javascript負責。從按點某個按鈕會跳出某選單的簡易功能,到圖片編輯器、聊天室、非同步的與伺服器溝通(免重整)、檢查資料正確性、字串自動完成、程式碼高亮度、動畫、3D遊戲(可以利用WebGL)甚至數學運算跟顯示公式等等複雜的功能,都可以透過javascript完成。

也因為這些豐富功能讓瀏覽器的效能變成問題,於是瀏覽器業者間的效能競爭,主要是圍繞javascript引擎的速度,javasript的效能可說是各個直譯式語言的佼佼者。於是就有人把javascript延伸到一般的機器上,走出瀏覽器,加上一般語言會有的IO、process等功能,就便成了最近流行的node.js。除了拿來當後端開發之外,還可以開發一般的系統程式。

另外,javascript跟java在本質上並沒有關係,只是javascript在一些語法上是C-like,也就是長的有點像java,又當初java正潮的時候,發明javascript的netscape公司為了吸引目光就取了這個名字。

Javascript的語句結尾一樣要加上分號。一般來說javascript習慣使用camelCase的命名慣例,也就是變數名稱的單字,以大寫來分隔,而不是底線。第一個字母習慣是小寫。

javascript是個非常靈活的語言,這裡只隨便做一個簡單的範例,畢竟我也還剛開始認真學javascript。

1
2
var foo = document.getElementById("foo");
foo.innerHTML="<p>hello javascript</p>";

Backend

相對於前端,後端就是在Server端執行的程式,處理http request,對資料庫存取資料等等。因為是在Server上直接執行,所以沒有限定語言,所以幾乎常見的程式語言都有辦法做後端開發。後端的歷史悠久,先來介紹一下。

後端程式開發通常包含了backend framework或程式語言,以及一個配合的資料庫程式(mysql、sqlite、postgresql、mssql、mongodb、oracle db等等)。後端程式把資料存在資料庫裡,當然也可以存在檔案文件裡,不過在現在已經比較少見了。

CGI

CGI指的是Common Gateway Interface,是最早的動態網頁技術。不是一個程式語言,而是提供了一個共通的API讓各個程式語言可以開發動態網頁。那時最流行的是用perl或bash來寫CGI。不過網路上應該也找的到很多用C寫的範例。

動態網頁語言

這些語言的的代表是開源的php、微軟的asp與sun的jsp。這些語言允許開發者可以簡單的撰寫專門給web使用的程式,而不用處理繁雜的底層問題。這些語言到現在都還在應用中,不過現在除了小網站程式之外,通常會配合一個framework來做事,而不是一個page一個page的寫這些程式。

後端框架

這是現在比較流行的方式,利用做好的框架來寫程式。這樣做出來的程式比較樣式統一、好維護,而且不用重複製造輪子,可以從現有的東西擴充。

流行的框架,列出一些我常聽到的:

  1. Ruby的Ruby on Rails、Sinatra..
  2. php的Code ignitor、zend..
  3. node.js的express.js、meteor…
  4. python的django
  5. 微軟的ASP.net
  6. 一些JVM-based的,通常是java、scala等等語言的框架
  7. GO語言也有一些

後端框架可以讓開發網站更容易快速。其中有些提供的功能比較完整,比如說Rails,他的哲學就是Convention over configuration、DRY(Don’t Repeat Yourself)。可以快速的建立網站,也有很多附加擴充。

也有比較簡易的Framework,像我這裡用的Sinatra。提供功能少不代表不好,而是每個app需要的功能不一樣,需要的規模也不一樣。我這裡是覺得Rails雖然很方便,但對於初學者來說學習曲線過陡。我認為如果以ruby來說,先學習sinatra來建立web概念,等到差不多熟悉的時候再上手rails,學習他的框架還有美學。學完Rails之後,我認為到其他許多framework都可以寫出好的程式,因為已經習慣rails裡好的convention了。

最後,想要學Sinatra的話,我們讀書會另一個成員的blog有簡單的安裝教學:

Sinatra “Hello, world!” for every environment

Reference Links

Mozilla Developer Network

Codecademy

Sinatra README

Ruby on Rails Guide

jQuery

Bootstrap

Comments