OUTLINE
- 目標:部署由 Express.js, ORM 框架 -- Sequelize 串接資料庫所寫成的 RESTful API。
- 將部署遇到的問題,詳細紀錄下來。
1.情境一:我不小心把 node_modules deploy 到 Heroku 上了
1.1 問題發生的原因
修改 .gitignore
檔案時,把 /node_modules
寫錯了,所以要 git push heroku
時,連同 /node_modules
也 push 上 Heroku 了。
1.2 問題
$ heroku logs --tail
...(略)
2022-05-22T23:09:40.062420+00:00 app[web.1]: Error: /app/node_modules/bcrypt/lib/binding/bcrypt_lib.node: invalid ELF header
1.2 解決問題的過程
參考此篇bcrypt error when deploy on Heroku : invalid ELF header #595,發現可以由以下方法補救:
1.2.1 步驟一:在 .gitignore
上寫上應該被 git 忽略的檔案
// google .gitignore 的 template,並加以修改:
/node_modules
.env
...
1.2.2 步驟二:儲存變更,推到 Heroku 上
$ git rm -r --cached .
$ git add .
$ git commit -m "fixed untracked files"
$ git push heroku
2. 情境二:ERR_INVALID_ARG_TYPE(name, 'string', value);
2.1 問題描述
heroku logs --tail
#### 2.2 問題修改heroku express deployinternal/validators.js:124 throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
我發現在./models/index.js
裡面有引用process.env[var_name]
但沒有引入dotenv
library,所以發生了問題,因此在此檔案內加:require("dotenv").config();
3. 情境三:解決了情境二,但是使用 console.log(process.env[var_name]
,Heroku 仍沒有吃到 .env
的變數
3.1 問題描述
在檔案內印了 process.env
的變數,但 Heroku 在執行時,沒有印出來,應該是沒有吃到 .env 變數。
// console.log('process.env.JWT_EXPIRES_IN', process.env.JWT_EXPIRES_IN)
// console.log('process.env.JWT_SECRET', process.env.JWT_SECRET)
$ heroku logs --tail
2022-05-22T05:56:18.729657+00:00 app[web.1]: Error: secretOrPrivateKey must have a value
2022-05-22T05:56:18.729657+00:00 app[web.1]: process.env.JWT_EXPIRES_IN
process.env.JWT_SECRET
3.2 解決方法:讓 Heroku 吃到 dotenv 的變數
參考此篇 StackOverflow How to set environment variables on Heroku for Node app and connect to the PostgreSQL database?,我發現可以使用 CLI 來設定 config。
$ heroku config // 查詢 Heroku 有哪些環境變數
polar-tor-55391 Config Vars
CLEARDB_DATABASE_URL: mysql://<host>:<pwd>@<host>/<dataBase>?reconnect=true
$ heroku config:set DB_HOST=my_DB // 設定新的環境參數名稱及內容
3.3 方法二:在 Heroku > setting > config Var 上直接新增
這個方法可以直接輸入環境變數名稱及內容,與上述使用 CLI 建立的方法是一樣的。
4. 情境四:如何在 Heroku 上建立 ClearDB MySQL 後該如何連線?
4.1 問題描述
一開始出現了跟資料庫連現有關的問題:
$ heroku logs --tail
2022-05-22T06:22:42.386671+00:00 app[web.1]: Ignoring invalid configuration option passed to Connection: reconnect. This is currently a warning, but in future versions of MySQL2, an error will be thrown if you pass an invalid configuration option to a Connection
4.2 嘗試的方法
在 Heroku 上部署,環境應是 production
,此時打開 ./config/config.js
:
因為我已經在 Heroku 上建立 ClearDB MySQL 了,Heroku 資料庫連線的基本資訊(username, password, host, database)都已經附在 Heroku > settings > Config Vars
內,所以只要加 use_env_variable: "CLEARDB_DATABASE_URL",
這行,並把其他不需要的連線資訊刪除(如下:username, password, host, database)。
const config = {
production: {
- username: "root",
- password: null,
- database: "database_test",
- host: "127.0.0.1",
dialect: "mysql",
+ use_env_variable: "CLEARDB_DATABASE_URL",
},
}
module.exports = config;
5. 情境五:為什麼 Primary key -- id 一次跳 10 的倍數?
5.1 問題描述:
以使用者註冊為例,註冊成功,會成功在 database 建立一筆新資料,其中 id 為 PK,但為什麼 id 都是以十的倍數起跳呢?如: 11, 21, 31, 41?
後來參考了這篇 MySQL autoincrement column jumps by 10- why?
6. 情境六:如何在 heroku 上使用 sequelize-cli db:migrate
?
6.1 問題描述:
Heroku 使用 clearDB 建立了資料庫,但是有沒有指令可以把之前在 local 的建好的 database table 移到 Heroku 上呢?ㄈ
6.2 方法:
在 Heroku 上 run sequelize 建立 Table 的指令。
$ heroku run npx sequelize-cli db:migrate
另外,可以在部署好時,在 package.json 寫指令,使用 sequelize-cli 指令建立:
// package.json
{
"scripts": {
+ "db:migrate": "npx sequelize-cli db:migrate",
+ "start": "npm run db:migrate && node index.js"
- "start": "node index.js"
},
}