阅读本文前,你需要大致了解:
✅ Git & Github
✅ JavaScript & React
✅ What is API, API Key & Environment Variables
最近做了某家公司的Online Assessment,内容很有趣,通过和第三方API交互设计并实现一个Web App。同时要求deploy在hosting平台上,比如Heroku, Github Pages, Google Cloud等,让用户可以不需要下载代码,直接在网页端运行。
欢迎大家来玩一下我做好的Web App – WeTalk.ai: https://fun-ai-response.herokuapp.com/ 因为本人的OpenAI的API token过期了,加上heroku开始收钱,本人因为抠门这两样东西都没有续费,所以这个web app已经不能用了。哈哈,但是文章还是有用的。
Web App逻辑并不复杂,第三方API的文档也写得很清楚,所以这部分我自信做得还不错。但问题在于找平台deploy我的Web App时出现了问题:如何在隐藏API key的前提下deploy Web App.
与第三方API交互时,对方会给每个提出请求的用户一个单独的API key,在我们写的代码里,需要用到这个API key才能得到对方的数据。而API key由于是每个用户独一无二的密钥,一旦泄露并被人恶意是用,会给平台和用户带来很多麻烦,甚至有可能给平台造成数据安全问题。
因此,在任何时候都不应该把API key直接写在代码里并上传到任何公开平台,包括Github公开的Repository. 有些第三方平台(比如我用的这个)会主动检测网络上是否有暴露的API key并自动替换,导致我的Web App因为换了密钥无法与第三方再沟通。
这一步我花了很多时间,走了一些弯路,最后在搜索多篇教程+猫咪的一起debug下顺利完成了!还要感谢Discord前端群的群友帮助和象友帮助。
在这篇里我会记录一下这次项目中遇到的有用的教程和踩过的坑,希望给后来人一些参考。
我接下来详细介绍的是Create React App + GitHub + Heroku的workflow. 相信其他的deploy service也是相同的原理。
1. Adding Custom Environment Variables in Create React App
设置方法有很多种,取决于使用的前端framework. 一般来说常常会用到npm的dotenv package. 原理是将API key写在 .env
文件中,并不上传到Github,仅供自己本地使用。
因为我这次用的是React bootstrapped with Create React App,它自带了dotenv library,因此不需要再额外安装。具体可见官方文档关于配置Custom Environment Variables的部分。
有几点摘要如下:
- Custom environment variables should begin with
REACT_APP_
- Any other variables except
NODE_ENV
will be ignored to avoid accidentally exposing a private key on the machine that could have the same name. - Changing any environment variables will require you to restart the development server if it is running.
- access it by
process.env.REACT_APP
in your React app.
Stack Overflow的一个例子:
- .env文件中 –
REACT_APP_BASE_URL=http://localhost:3000
- service.js中 –
const BASE_URL = process.env.REACT_APP_BASE_URL;
2. Hide API Key from Github
配置完成后,需要在repository的root directory的 .gitignore
文件中加入 .env
样例如下:
# misc .DS_Store .env
如果之前不小心已经commit或者push过 .env
file到自己的repository,那么需要清理一下Git cache. 让最新的 .gitignore
可以track到目前repository任何不应该被track的文件:
- 如果想untrack single file,只需要
git rm --cached filename
- 如果想要untrack所有
.gitignore
中的file,步骤如下: - First commit any outstanding code changes (否则git add之后其他进度的文件会消失)
- run
git rm -r --cached .
(This removes any changed files from the index - staging area)
- then run
git add .
- then commit:
git commit -m ".gitignore is now working"
链接中的注意事项里也提到了,再从git上pull下来的时候这些 .gitignore
中的文件就不会存在了,所以请做好本地处理。
另外,可以在repository中加上 .env.example
告诉其他developer该如何配置app中用到的key value pair.
3. Deploy on Heroku using Git
接下来需要聊聊deploy的问题。这次我尝试了Github Pages和Heroku.
最终Github Pages没有成功,我怀疑是我使用的第三方API专门track了Github来的request并且禁止了。每次我一部署在Github Pages上,我的API key就会被认为泄露,并自动更换,造成了很多痛苦。
如果碰到了可以接受Github Pages的第三方API,可以直接照着Github Pages的deployment来设置,也可以遵循Create React App官方的Github Pages deployment部分进行配置。推荐照着后者的教程,因为可以在deploy之后继续开发,不需要反复deploy,操作非常丝滑。
Github Pages配置Enviroment Variables的部分请参照Discord群的22和Chestnut的提供的教程,感谢帮助。
之后我转战了Heroku. 首先如果在别的平台deploy过并按照CRA官方文档修改过 package.json
,请记得要改回来!我在这部分卡了好久,恢复以后就好了。
接着根据CRA的官方文档来deploy with Heroku.
- 首先安装Heroku CLI. 我是PC,其他方法我怎么都配置不成功,所以最后用了官方不推荐的npm,最后也成功了。
- verify installation –
heroku --version
- 跟着步骤login –
heroku login
之后就是deploy到Heroku上。如果想在创建app之前就连好Heroku的deployment,需要follow这个教程。
我因为已经在安装Heroku之前创建了App,所以步骤略有不同,省略了前几步。
git init # 当时我copy到了一个新的repository里,还没有传到Github上,因此需要init. heroku create -b <https://github.com/mars/create-react-app-buildpack.git> git add . git commit -m "react-create-app on Heroku" git push heroku master heroku open
因为Heroku官网的教程和该developer自己的教程出现了一些不同:git push heroku master
和 git push heroku main
的区别,我没注意到,因此有了一个报错,最后使用了这个Stack Overflow的办法解决了。
git push heroku HEAD:master
或者 git push heroku HEAD:main
取决于想要用哪个branch deploy.
原理参见这个帖子。指明了用当前的repo来commit到我要deploy的branch.
4. Pass API Key to Heroku through Environment Variable
那么文件都deploy上Heroku了,但是如我之前所说, .gitignore
中的文件包括包含了我API key的 .env
并不会被commit到任何repository里。之后怎么将我的API key告诉Heroku呢?
答案是我通过Heroku的方式偷偷告诉它。有两种方式:一种是通过Heroku CLI,一种通过Heroku Dashboard. 参见这篇官方教程。
如果是用的React,也可以看这里的教程, 本质上都是一样的。
我用的是terminal command – heroku config:set REACT_APP_HELLO='I love sushi!'
注意读文档的时候不能掠过信息,比如这里: The app must be re-deployed for compiled changes to take effect, because during the build, these references will be replaced with their quoted string value.
因此不管用哪种方式配置了我的API Key,我都需要重新deploy一次。
git commit --allow-empty -m "Set REACT_APP_HELLO config var" git push heroku main
对于git repository来说,我们没有增删改减任何文件,所以直接 git add .
和 git commit -m "re-deploy"
的话并不会触发heroku的re-deploy.
所以记得commit的时候一定加上 --allow-empty
才会有效果!
5. Sync between Heroku and Github
为了保险起见,commit + push完heroku之后,commit到Github也请加上 --allow-empty
保证能顺利commit.
Reference
最后附上我这次的repository供参考 –
并欢迎大家来玩我的Web App – WeTalk.ai: https://fun-ai-response.herokuapp.com/
感谢猫咪的一路帮助和安抚。