Elixir&React架構踩坑記錄.一

GitHub地址: zhengxiaoyao0716/honeycomb-adventure

踩坑記錄

Before All

請注意,這是 踩坑記錄 ,不是開發教程!我會嘗試解釋一些東西,但不會太多,因為我也在學習中。 你至少要具備與我相近的水平,才應該繼續看下去,我不會對一些我認為基礎的問題過多講解。

Install Environment

官網指引 ,或者,直接下載 OTPElixir v1.5.2 的安裝器進行安裝:8jji

OTPOpen Telecom Platform ,開放電信平台,是隨 Erlang 一起發布的庫。

安裝完畢後,可以在命令行輸入 erl 進入 Erlang 的REPL,輸入 iex 進入 Elixir 的REPL,請自行驗證版本號和一些基礎語法。

然後,我們需要安裝 PhoenixElixir 的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進位包管理器, 官方指引 說這是必要的。

phxPhoenix ,你也可以手動下載 ez 包,然後把GitHub地址換成本地路徑來從本地安裝。

Create Project

mix phx.new PROJECT_NAME

phx 默認使用 Brunch.io 來支持前端構建(代替 Webpack ),你可以添加 --no-brunch 選項來 禁用它

但我們當然不會用傳統Web技術去寫前端,我們要用那些酷炫的東西,並且早就受夠 Webpack 了,對吧? Brunch 看起來要好的多,不知道比起我之前挺喜歡的 roadhog 來怎麼樣,藉此機會我準備嘗試一下它。

phx 會自動幫我們安裝 Brunch 以及其它一些 NodeJS 的依賴,這意味著你需要先搭建好 NodeJS 環境。

phx 默認使用 PostgreSQL 持久化數據,我同樣不打算我禁用或更換,這意味著你需要事先裝好 PostgreSQL

你可以從 Postgres官方 或 9z3x 下載安裝,或參考 官方指引 換別的資料庫,又或者乾脆 --no-ecto 禁用了。

PROJECT_NAME 必須為小寫字母數字下劃線,不支持短橫杠這點讓我稍稍不爽了一下。

Config Secret

創建好的項目默認通過文件方式來配置,關鍵信息被放在了 prod.secret.exs 里,並添加進了 .gitignore 。我不喜歡這種方式,讓我們做點改造:

  1. 注釋掉 .gitignore 的 /config/*.secret.exs
  2. 把 prod.secret.exs 中的關鍵信息換成環境變數,比如 secret_key_base 的值換成 System.get_env("SECRET_KEY_BASE")
  3. 檢查其它文件,把需要自定義的地方也都換成環境變數,比如 prod.exs 里的url的host和port, endpoint.ex 里的 signing_salt
  4. 別忘了順手整理一下你添加環境變數,一般我的習慣就是直接寫ReadMe裡面了,部署的時候找起來方便。

確定資料庫安裝好了並正確運行了,資料庫連接配置也沒問題後,我們來創建資料庫:

mix ecto.create

Start server

運行開發伺服器:

mix.bat phx.server

由於我提交了 VSCode的任務配置 ,如果你也用 VSCode ,那麼只需要 Ctrl + Shift + B 就能運行。

然後瀏覽器打開 :4000 ,應該就能看到 Phoenix 的歡迎頁面了。

目前為止都是照著官方指引的基礎操作,下面我要開始添加自己的 私貨 了。

在這之前先提交了一次,因為後面的步驟與內容視具體情況可能差異很大,比如用不用 React 之類。

Write pages

首先要改動的當然就是前段結構。雖然我決定保留並嘗試 Brunch ,但我可一點都不打算遵循現在的模板開發架構。

當然,不是說這種架構不好,寫一些簡單的小頁面大概是很合適的吧。但這樣前端對後端的依賴太重了。

具體來說,我不希望寫前端時還要去考慮後端模板渲染適配,不希望還要去後端添加路由、控制器等。

再次強調,這只是我個人愛好。這麼做本身並沒錯,這種傳統方式填充數據可以節省很多Ajax請求。

第一步,我們需要引入 ReactReduxCSS-Modulebabeleslint 等:

F**k,安裝錯目錄了, package.json 都沒有還能安裝,那麼 --save-dev 參數怎麼解釋啊,直接忽略了?

東西有點多不寫出來了,你可以直接 npm i 來安裝所有,或者自己去 package.json 里看我具體都裝了哪些東西。

第一點五步,隨手複製了一份自己以前用的 .eslintrc ,點開幾個 js 文件,嗯報錯了,說明起作用了。

第一點七五步,把報錯的地方改了,用什麼雙引號啊,js沒分號能忍啊。呃,有點多,那麼乾脆刪了吧。

第一點八七五,於是看了看, socket.js 還有點價值,其它的都可以刪了,同時重新 配置 一下目錄結構。

第xxxx:F**k,果然踩坑裡了。 重大bug發現 , Brunchrequire 實現有問題,導致一使用 PostCSS 就玩完兒。

我提交了修復issue,但考慮到不止會不會、何時會採用,且由於實現比較偏門,不知道還有多少問題。

現在就又遇到個,不能直接 require 圖片等資源獲取連接。。。可見 brunch 還不太成熟。。。

是繼續這個折騰了半天的缺陷明顯的 brunch ,還是換回慣用的 roadhog ,我陷入了深深的憂鬱 -_-!!!

F**k,又踩坑了,這次好像是 phoenix 的坑,不是換不換 brunch 的問題了。

詳細原因還沒查出來,就是現在這次提交,直接運行,沒問題。保存個文件熱載入一下,頁面沒了, _build 里的 index.js 被刪空了。

看起來是熱載入問題 ,勉強還能繼續用下去。嘛,慢慢來吧,希望這些問題能早點修復。

問題雖然沒完全修復但也算有了臨時解決方案,就是先用管理員身份運行一次,詳情見那個 issue 。

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 吧,沒辦法,實在懶的折騰了。。。

因為突然發現 roadhog 並不支持 watch 模式,要換 roadhog 的話,就得採取以前的前後端分別開發的流程了。

不是說那樣不好,但不適合個人項目快速構建,有悖於我的初衷。我認可前後端分離架構,但不認可前後端分離開發。

前端用各種proxy去模擬後端,後端用各種單元用例去模擬前端,然後雙方各自開發,最後再集成到一起,我覺得沒必要。

只要做到寫前端不用考慮後端代碼,寫後端不用考慮前端代碼就夠了,本身開發中還是可以直接使用對方的服務的。

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 ,主要看看裡面的 queryobject 的寫法吧,沒什麼難的。

因為寫這段時我事實上已經順手把 下一節 弄完了,看起來複雜的話就參考 官方指引 吧。

關於數據表模型 HoneycombAdventure.User 的創建於用法等參見 這裡 ,應該也沒什麼難理解的吧。

然後安裝依賴,跑起項目,打開瀏覽器,訪問 GraphiQL實驗台 ,沒問題的話就可以試試拉點數據了。

Use socket

單純的 Http 請求-響應太落後了,我們當然要用 WebSocket !並且仍然要加上 GraphQL

其實 Phoenix 已經默認幫我們把 WebSocket 準備好了,我們主要來看看怎麼引入 GraphQL

與上一節類似,先安裝 absinthe_phoenix 依賴以提供 WebSocketGraphQL 支持,官方指引 在這 。

然後在 application.ex 里註冊 Absinthe.Subscription ,以在應用啟動時啟動 Absinthe 服務。

在 Web入口 里添加一行 use Absinthe.Phoenix.Endpoint 以引入 absinthe_phoenix

在 Socket 里引入 Absinthe.Phoenix.Socket 並指定 Schema ,復用上一節的就好了。

在 Web路由 上一節添加的路由後,再加一行,指定 socket 模塊,以便 GraphiQL 訪問 WebSocket

最後,編輯 Schema ,添加 mutationsubscription ,分別用於發布和訂閱消息,具體參考 這裡

這樣上一節讓大家跳過的地方應該就能看懂了吧?有沒有覺得這個地方思路和 Redux 真的挺像?

一切就緒,再次跑起應用,訪問 GraphiQL實驗台 ,這次開倆窗口,試試訂閱與發布消息吧。


推薦閱讀:

TAG:Elixir | React | Web開發 |