Elixir&React架構踩坑記錄.一
GitHub地址: zhengxiaoyao0716/honeycomb-adventure
踩坑記錄
Before All
請注意,這是 踩坑記錄
,不是開發教程!我會嘗試解釋一些東西,但不會太多,因為我也在學習中。 你至少要具備與我相近的水平,才應該繼續看下去,我不會對一些我認為基礎的問題過多講解。
Install Environment
官網指引 ,或者,直接下載 OTP
與 Elixir v1.5.2
的安裝器進行安裝:8jji
OTP
即Open Telecom Platform
,開放電信平台,是隨Erlang
一起發布的庫。
安裝完畢後,可以在命令行輸入 erl
進入 Erlang
的REPL,輸入 iex
進入 Elixir
的REPL,請自行驗證版本號和一些基礎語法。
然後,我們需要安裝 Phoenix
, Elixir
的Web框架。我們使用 mix
來安裝它
mix local.hexmix archive.install https://github.com/phoenixframework/archives/raw/master/phx_new.ez
Elixir 自帶
mix
作為構建工具,大概是Managing elixir
之類的意思?反正我是這麼理解的。local.hex
全名Hex package manager
,16進位包管理器, 官方指引 說這是必要的。phx
即Phoenix
,你也可以手動下載ez
包,然後把GitHub地址換成本地路徑來從本地安裝。
Create Project
mix phx.new PROJECT_NAME
但我們當然不會用傳統Web技術去寫前端,我們要用那些酷炫的東西,並且早就受夠
phx
默認使用Brunch.io
來支持前端構建(代替Webpack
),你可以添加--no-brunch
選項來 禁用它Webpack
了,對吧? Brunch 看起來要好的多,不知道比起我之前挺喜歡的 roadhog 來怎麼樣,藉此機會我準備嘗試一下它。phx
會自動幫我們安裝Brunch
以及其它一些NodeJS
的依賴,這意味著你需要先搭建好NodeJS
環境。phx
默認使用PostgreSQL
持久化數據,我同樣不打算我禁用或更換,這意味著你需要事先裝好PostgreSQL
。你可以從 Postgres官方 或 9z3x 下載安裝,或參考 官方指引 換別的資料庫,又或者乾脆--no-ecto
禁用了。PROJECT_NAME
必須為小寫字母數字下劃線,不支持短橫杠這點讓我稍稍不爽了一下。
Config Secret
創建好的項目默認通過文件方式來配置,關鍵信息被放在了 prod.secret.exs 里,並添加進了 .gitignore 。我不喜歡這種方式,讓我們做點改造:
- 注釋掉 .gitignore 的
/config/*.secret.exs
。 - 把 prod.secret.exs 中的關鍵信息換成環境變數,比如
secret_key_base
的值換成System.get_env("SECRET_KEY_BASE")
。 - 檢查其它文件,把需要自定義的地方也都換成環境變數,比如 prod.exs 里的url的host和port, endpoint.ex 里的
signing_salt
。 - 別忘了順手整理一下你添加環境變數,一般我的習慣就是直接寫ReadMe裡面了,部署的時候找起來方便。
確定資料庫安裝好了並正確運行了,資料庫連接配置也沒問題後,我們來創建資料庫:
mix ecto.create
Start server
運行開發伺服器:
mix.bat phx.server
由於我提交了 VSCode的任務配置 ,如果你也用 VSCode ,那麼只需要 Ctrl + Shift + B
就能運行。
然後瀏覽器打開 :4000 ,應該就能看到 Phoenix
的歡迎頁面了。
目前為止都是照著官方指引的基礎操作,下面我要開始添加自己的 私貨
了。
在這之前先提交了一次,因為後面的步驟與內容視具體情況可能差異很大,比如用不用 React
之類。
Write pages
首先要改動的當然就是前段結構。雖然我決定保留並嘗試 Brunch
,但我可一點都不打算遵循現在的模板開發架構。
當然,不是說這種架構不好,寫一些簡單的小頁面大概是很合適的吧。但這樣前端對後端的依賴太重了。
具體來說,我不希望寫前端時還要去考慮後端模板渲染適配,不希望還要去後端添加路由、控制器等。再次強調,這只是我個人愛好。這麼做本身並沒錯,這種傳統方式填充數據可以節省很多Ajax請求。
第一步,我們需要引入 React
和 Redux
, CSS-Module
、 babel
和 eslint
等:
F**k,安裝錯目錄了,
東西有點多不寫出來了,你可以直接package.json
都沒有還能安裝,那麼--save-dev
參數怎麼解釋啊,直接忽略了?npm i
來安裝所有,或者自己去 package.json 里看我具體都裝了哪些東西。
第一點五步,隨手複製了一份自己以前用的 .eslintrc ,點開幾個 js
文件,嗯報錯了,說明起作用了。
第一點七五步,把報錯的地方改了,用什麼雙引號啊,js沒分號能忍啊。呃,有點多,那麼乾脆刪了吧。
第一點八七五,於是看了看, socket.js
還有點價值,其它的都可以刪了,同時重新 配置 一下目錄結構。
第xxxx:F**k,果然踩坑裡了。 重大bug發現 , Brunch
的 require
實現有問題,導致一使用 PostCSS
就玩完兒。
我提交了修復issue,但考慮到不止會不會、何時會採用,且由於實現比較偏門,不知道還有多少問題。
現在就又遇到個,不能直接require
圖片等資源獲取連接。。。可見brunch
還不太成熟。。。是繼續這個折騰了半天的缺陷明顯的brunch
,還是換回慣用的roadhog
,我陷入了深深的憂鬱 -_-!!!
F**k,又踩坑了,這次好像是 phoenix
的坑,不是換不換 brunch
的問題了。
詳細原因還沒查出來,就是現在這次提交,直接運行,沒問題。保存個文件熱載入一下,頁面沒了,
看起來是熱載入問題 ,勉強還能繼續用下去。嘛,慢慢來吧,希望這些問題能早點修復。問題雖然沒完全修復但也算有了臨時解決方案,就是先用管理員身份運行一次,詳情見那個 issue 。_build
里的index.js
被刪空了。
F**k,到底多少坑啊!垃圾 brunch
,玩票的東西吧?時不時會報跟source_file有關的錯誤,然後就tm的不重編譯了。
具體來說,某個watch的文件的本來被import了,然後我不想用了,刪掉那行import,就會導致
brunch
報錯崩潰。之前報的bug,pull-request都提了,官方毫無響應。GitHub上open著的issue居然有一百多個了,不能想像。
軟連接導致熱載入失敗問題好歹解決了,Phoenix
本身是可以繼續用下去了,但Brunch
這垃圾還是早點換掉吧。差點忘了,brunch的sourceMap完全沒用,瀏覽器報錯根本找不到源碼。不知道是不是哪裡配錯了,但實在太難用了。擦,還原到初始狀態沒有復現這個問題,看來是之後添加的插件之類造成的。懶得麻煩了,換掉不成熟的brunch
吧。
好吧但我真的不想用回 Webpack
,作為代替,我們這次來試試 parcel
:
npm i --save-dev parcel-bundler
簡直nice,名不虛傳,
收回,parcel
就是我想要的,跟roadhog
類似的簡單配置,但完全擺脫了Webpack
。parcel
也不怎麼成熟,沒有sourceMap就算了, CSS-Module經常編譯報錯 ,還是考慮Roadhog
吧。
然而切換 roadhog
失敗了。。。暫時先用著 parcel
吧,沒辦法,實在懶的折騰了。。。
因為突然發現
不是說那樣不好,但不適合個人項目快速構建,有悖於我的初衷。我認可前後端分離架構,但不認可前後端分離開發。前端用各種proxy去模擬後端,後端用各種單元用例去模擬前端,然後雙方各自開發,最後再集成到一起,我覺得沒必要。只要做到寫前端不用考慮後端代碼,寫後端不用考慮前端代碼就夠了,本身開發中還是可以直接使用對方的服務的。roadhog
並不支持watch
模式,要換roadhog
的話,就得採取以前的前後端分別開發的流程了。
Write service
前端踩坑先告一段落,讓我們開始後端吧,這才是主要目的。首先呢,我們需要部署 GraphQL
來提供服務:
我們將選擇 absinthe-graphql ,相比於 graphql-elixir ,這個庫封裝更加高級,文檔也更加齊全。
遵循 官方指南 ,我們直接在 mix.exs 的 deps
里添加 absinthe_plug
依賴 {:absinthe_plug, "~> 1.4"}
absinthe_plug 是
官方指引里說還要添加Absinthe
的插件,用來提供HTTP
以及 GraphiQL (一個基於瀏覽器的交互實驗台)支持。poison
以提供JSON
支持,但我覺得沒必要,因為這個庫事實上早已引入了。
然後編輯項目的 Web路由 ,為 Absinthe.Plug
添加一條路由,別忘了指定你的 Schema
模塊。
這裡我在開發環境下做了個特殊處理,將路由控制器換成了
如果後端只打算提供Absinthe.Plug.GraphiQL
,以支持GraphiQL
。GraphQL
服務,你可以簡單的把插件注入到 Web入口 來全局應用插件。
最後,編個簡單的 Schema ,主要看看裡面的 query
和 object
的寫法吧,沒什麼難的。
因為寫這段時我事實上已經順手把 下一節 弄完了,看起來複雜的話就參考 官方指引 吧。
關於數據表模型 HoneycombAdventure.User 的創建於用法等參見 這裡 ,應該也沒什麼難理解的吧。
然後安裝依賴,跑起項目,打開瀏覽器,訪問 GraphiQL實驗台 ,沒問題的話就可以試試拉點數據了。
Use socket
單純的 Http
請求-響應太落後了,我們當然要用 WebSocket
!並且仍然要加上 GraphQL
!
其實
Phoenix
已經默認幫我們把WebSocket
準備好了,我們主要來看看怎麼引入GraphQL
。
與上一節類似,先安裝 absinthe_phoenix 依賴以提供 WebSocket
的 GraphQL
支持,官方指引 在這 。
然後在 application.ex 里註冊 Absinthe.Subscription
,以在應用啟動時啟動 Absinthe
服務。
在 Web入口 里添加一行 use Absinthe.Phoenix.Endpoint
以引入 absinthe_phoenix
。
在 Socket 里引入 Absinthe.Phoenix.Socket
並指定 Schema
,復用上一節的就好了。
在 Web路由 上一節添加的路由後,再加一行,指定 socket
模塊,以便 GraphiQL
訪問 WebSocket
。
最後,編輯 Schema ,添加 mutation
和 subscription
,分別用於發布和訂閱消息,具體參考 這裡
這樣上一節讓大家跳過的地方應該就能看懂了吧?有沒有覺得這個地方思路和
Redux
真的挺像?
一切就緒,再次跑起應用,訪問 GraphiQL實驗台 ,這次開倆窗口,試試訂閱與發布消息吧。
推薦閱讀: