###### tags: `筆記`
# 【筆記】 第一個 Fullstack Project - Newsletter Signup Page
## 功能
一個簡單的訂閱畫面,輸入資料(姓名、Email Address),按下 Singup 按鈕,跳轉至「成功」訂閱畫面或是「失敗」訂閱畫面。
利用 Mailchimp 作為收集 Email Address 的後台資料庫。
最後使用 Railway 部署至網路上。
## 連結
1. [GitHub repo](https://github.com/jovi920204/Newsletter-Signup-Page)
2. [網站連結](https://newsletter-signup-page-jovi-chang.up.railway.app)
## 展示畫面
### 訂閱畫面(主畫面)

輸入測試資訊(Bob、Chang、BobChang@email.com)

### 成功訂閱畫面

### 失敗訂閱畫面
點擊「Try again!」按鈕,可以返回主畫面重新訂閱

### Mailchimp 後台數據

## 程式碼解析
1. 初始化
```javascript=
// jshint esversion: 6
const express = require("express");
const bodyParser = require("body-parser");
const request = require("request");
const https = require("https")
const app = express();
app.use(express.static("public"));
app.use(bodyParser.urlencoded({extended: true}));
```
- 當 app 在使用 bodyParser 時,要記得啟用 urlencoded。
2. 導向主畫面
```javascript=
app.get("/", function(req, res){
res.sendFile(__dirname + "/signup.html");
});
```
- `__dirname` 會回傳主機從根目錄到現在這個目錄的路徑,確保在不同 Server 上執行時,路徑都能夠正確。
3. 當表單送出,要做的事情
```javascript=
app.post("/", function(req, res){
// 從表單中擷取使用者輸入的資料
const firstName = req.body.firstName;
const lastName = req.body.lastName;
const email = req.body.email;
// 包裝成 json 格式,這些名稱是根據 mailchimp 所提供的資料
const data = {
members: [
{
email_address: email,
status: "subscribed",
merge_fields: {
FNAME: firstName,
LNAME: lastName
}
}
]
}
// 原先的 json data 要經過 stringify 才能夠發送給 mailchimp
const jsonData = JSON.stringify(data);
// 以下為使用 https request 向 mailchimp 請求
const url = "https://<dc>.api.mailchimp.com/3.0/lists/<LIST_ID>"
const options = {
method: "POST",
auth: "<NAME>:" + "<YOUR API KEY>"
}
// 先宣告 request 為 https.request 函式
const request = https.request(url, options, function(response){
response.on("data", function(data){
// 使用 response.statusCode 得知 requst 的狀態,例如 404 就代表 error、200 代表 OK
const status = response.statusCode;
if (status === 200){
res.sendFile(__dirname + "/success.html");
}
else{
res.sendFile(__dirname + "/failure.html");
}
});
});
// 執行 https.request,並且發送訂閱者的資料
request.write(jsonData);
request.end();
});
```
4. 當 POST 到 "/failure" 這個路徑時,要做的事情
```javascript=
app.post("/failure", function(req, res){
res.redirect("/");
});
```
5. listent
```javascript=
app.listen(process.env.PORT || 3000, function(){
console.log("Server is running on port 3000");
});
```
## 過程中額外學到的事情
1. 使用 Railway 取代 Heroku
現在 Heroku 已經不提供免費的流量及空間部署自己的 Server,在網友的推薦下,我使用 Railway 部署,發現只要把程式碼放到 GitHub 上,就真的是「一鍵部署」。 而且他提供的使用量足夠我這個 Web 開發新手架設自己的伺服器。
2. .env
因為要部署到 Railway 上,那們`app.listen()`就不能把`PORT`固定在 3000,而是交由 Server 空間提供者來自動決定,所以這邊就需要用到`process.env.PORT`,讓程式自動從環境參數中提取對應的資料。
我原先在設定 mailchimp 的 API Key 時,就直接打在程式碼當中,部署沒多久後,就收到 mailchimp 的來信,說我公開了 API Key,所以把那組 Key 值給 Disabled。此時我才發現我做了非常蠢的事情。後來才知道要把這個資訊寫在 .env 裡面,方法是到 Railway 的 Variables 設定頁面中,新增變數,並且在程式碼中修改呼叫 API Key 的方法,我改寫成 `process.env.API`,就大功告成了。

3. 移除 node_modules
在實作專案時,一定會`$ npm install <module>`,然後就會有 module 本體在專案資料夾底下,因為這是小小的專案,所以檔案根本不會很大,但是光看一個 module 裡面的東西,就有很多了,更何況是大專案,再者,因為有`package.json`,在使用 npm 服務時一定要先輸入 `$ npm init`,就會建立此專案的資訊,所以不管是誰拿到你的專案,只要根據這個`package.json`就可以建置相應的環境,執行你的專案。