- Related Document
- Requirement
- Folder Structure
- Release Flow
- Version
- Mock Data Server
- LocalStorage
- Local Development
- Embedded In Platform
- Theme
- Locales
- Device
- Chatroom
- Postcss Root Selector
- Unit Testing
- Issues
- 平台與 IM 廣場串接文件
- 平台與 IM 聊天室串接文件
- 51 API Doc
- Backend 專家主播 API Doc
- Backend 聊天室 Ws Doc
- IM Release Note
- 51 直播後台
- 51 直播前台
- FE commit Rule
Build Tool : Turbo ≥ 1 Package Manager : Pnpm ≥ v8 Environment : Node ≥ v16.x
Pnpm v.s Node Version Compatibility
turbo 需要安裝在電腦全域的 npm module (或許能只安裝在專案內,需測試)
For more detail see README .
For more detail see README .
For more detail see README .
im 上版後要在線上環境確認版號,可以透過下面方式:
- 進到平台的線上環境
https://en-vd004-tiger-portal.innodev.site/
- 進到平台廣場
- 打開 devtool 輸入
_version_
,便可查到現在線上版本以及git commit sha
細節:apps/library/src/utils/versionInfo.ts
For more detail see README .
目前有一些供測試或是與 universe-portal-wap/
相關的 localStorage 變數在使用:
imVIPNotify
: 記錄專家頁面隱藏金色鎖頭的過期時間dev
: 設為true
打開 ws 的debug mode
,可以參考 聊天室文件locale
: im 內的語系,會與平台的locale.current
同步mock
: 設為true
改打 mock data serverdev_login
: 設為true
可以在 im 專案執行平台登入動作imAllowTranslate
: 是否打開翻譯的參數allow
= 是,not-allow
= 否,default
= 看預設值
目前散落在專案各處,未來可以統整在一起。
因為 im-monorepo
是打包後被平台透過 npm 安裝下來的,
在本地若需測試兩個專案一起的話,
是透過 vite watch mode 的方式將專案打包至本地 universe-portal-wap
底下的 node_modules/im-library
,是透過 .env
設定來控制打包路徑。
操作方式:
- 將專案底下
apps/library/.env.development
複製一份並取名.env
cp ./apps/library/.env.development ./apps/library/.env
- 將
.env
檔案內的PLATFORM_OUT_DIR
參數修改成自己電腦裡universe-portal-wap
的node_modules/im-library
路徑
PLATFORM_OUT_DIR="{UNIVERSE_PORTAL_WAP_PROJECT_PATH}/node_modules/im-library"
- 在
apps/library/
底下執行指令以watch mode
形式打包到universe-portal-wap
下
cd apps/library
pnpm run build:library-watch
-
啟動 universe-portal-wap 專案
-
只要
im-monorepo
中有檔案異動,都會重新打包一次放到平台底下
For more detail see README .
在專案啟動的時候根據 env-config
中的業主代號
去抓該業主的主題色 mapping。
目前只有分谷歌
及瑞銀
兩主題色,其他業主都會是這兩個其中之一。
// packages/utils/vdThemeGenerator/map.ts
const themeMap = {
vd001: theme.ruiYin,
vd002: theme.guGe,
vd003: theme.guGe,
vd004: theme.ruiYin,
// vd005: theme.guGe,
vd006: theme.guGe,
vd007: theme.ruiYin,
vd008: theme.guGe,
vd009: theme.ruiYin
}
ruiYin: {
primary: '76 158 234', // #4C9EEA
secondary: '80 189 255' // #50BDFF
},
guGe: {
primary: '12 24 108', // #0C186C
secondary: '80 84 255' // #5054FF
}
取到對應的主題色 mapping 表後,用 js 將 mapping 表
轉換成 css 變數表
並以 <style></style>
包裹後插入至 <head></head>
中
<style>:root {--im-monorepo-primary:76 158 234;
--im-monorepo-secondary:80 189 255;
}</style>
因為專案也有使用 tailwindcss,所以也會定義 extend color。 細節: packages/tailwind-config/tailwind.present.cjs.
colors: {
imprimary: {
DEFAULT: 'rgb(var(--im-monorepo-primary))'
},
imsecondary: {
DEFAULT: 'rgba(var(--im-monorepo-secondary))'
}
}
這個 utils function 主要是用來取圖片用的,有些分業主的圖片檔會放在 vd002
/ vd004
的資料夾內,這個 utils 會去決定要去哪個資料夾底下拿。
// packages/utils/getVendorTheme/index.ts
switch (VENDORID) {
case 'vd001':
case 'vd004':
case 'vd007':
case 'vd009':
return 'vd004'
case 'vd002':
case 'vd003':
case 'vd006':
case 'vd008':
return 'vd002'
default:
return
}
For more detail see README .
For more detail see README .
主播有一個語系機制比較特別:
- 因為廣場資料來源是串接 51 第三方,而第三方語系跟我們的語系有差異,需要做對應
- 後台可以控制哪些語系的主播可以呈現在前台,又分為指定語系與預設語系
im 專案也有做 rwd
的設計,而實作方式基本上與 universe-portal-wap
的機制相同。
md: 375px
(手機)lg: 600px
(平板)xl: 1024px
(電腦)
- 在專案啟動時透過
vite.config
將裝置尺寸設定從tailwind.config
讀取進來 - 將設定透過
vite.config
的define
功能定義至process.env.SCREENS
變數 - 註冊一個全域的
resize
事件監聽當前畫面尺寸,再跟上述設定值做比對分辨現在屬於哪一種裝置。
兩種根據尺寸做調整樣式/功能
的方法:
- tailwind responsive design
- 全局 svelte/store,
isMd
,isLg
,isXl
及deviceSize
// tailwind
<div class='color-red lg:color-blue xl:color-green'></div>
// svelte(js)
{#if $isXl}
<div>我是電腦版看到的</div>
{:else if $isLg}
<div>我是平板看到的</div>
{:else}
<div>我是手機版看到的</div>
{/if}
For more detail see README .
im
專案與 universe-portal-wap
專案都有在使用 tailwindCSS
寫樣式,之前遇到一個問題:
平台的樣式因為 RWD
的需求會有 media-query
的樣式覆寫:
<div class='color-red-500 lg:color-blue-500 xl:color-white'></div>
可是 media-query
與一般樣式是屬於同層級
的選擇器,只因載入順序與尺寸影響。
所以如果有一個一模一樣的樣式在載入順序上比平台的更後面時,會導致就算平台有使用 media-query
,還是會被同名的樣式覆蓋。
EX:
// 載入 bundled CSS 的順序:
// 1. 平台 color-red-500
// 2. 平台 lg:color-blue-500
// 3. 平台 xl:color-white
// 4. im color-red-500
<div class='color-red-500 lg:color-blue-500 xl:color-white'></div>
這時候前面的 media-query 的樣式就會因為載入順序的關係被 im 的樣式覆蓋。
workaround:
引入 postcss-add-root-selector
套件,將 im 打包的 css 全部都加上 .im-library
的前綴,以此來跟平台的樣式區隔開,平台就不會在同名的 class 去引入 im 的樣式。
drawbacks:
所有會在平台底下使用的 im 組件都必須包裹一個有 .im-library
的外層 html 元素,包含會 portal 到 body 的也是。
如果有些 im 暴露出去的元素是套件 (ex: mobile-select.js),且能確保套件的樣式不會影響到平台,可以在 postcss.config.cjs
加上 exclude
option 去濾掉某些樣式檔不用加前綴這件事。
// postcss.config.cjs
module.exports = {
plugins: {
// ...
'postcss-add-root-selector': {
rootSelector: '.im-library',
exclude: ['mobile-select.css']
}
}
}
專案有用 testing-library, vitest 做單元測試。
跑測試會涵蓋 library,ui,utils 及 api 底下的 *.{test,spec}.{ts,js...}
的檔案。
# testing
pnpm run test
# testing in watch mode
pnpm run test:watch
unit-testing 目前大多用來測試 function, class 的正確性,比較少用來測試組件。
因為 unit-testing 不好用來測試有異步行為邏輯的組件 (ex: 在生命週期下執行業務邏輯的行為),組件多半是測試傳入 props
後的行為、event 觸發
行為等等。
測試範例可以參考: packages/utils/amount/amount.test.ts
-
type declaration
現在打包到平台使用的 svelte 組件沒有做 .d.ts 檔的宣告,所以只能暴力的使用
//@ts-ignore
去忽略報錯。svelte 官方提供的套件包 svelte-package/svelte2tsx 是針對某個根路徑去產生底下所有的 .d.ts,但是 im 專案只有導出特定模組,就算針對根目錄
platform/
去跑指令,底下的模組又會引用其他非platform/
底下的模組,產生出來的.d.ts 路徑
也會有問題。詳情可參考檔案: apps/library/env_scripts/generateDts.mjs
# apps/library/ pnpm run dts-generate
workaround:
- 跑完官方提供套件後透過
shell
腳本去解決路徑問題並放到release/
底下。 - 手動定義
.d.ts
宣告
- 跑完官方提供套件後透過
-
Version Control
現在專案沒有走正常的 gitlab CI/CD 流程,而是完全透過 shell script 來做上版。 會有一個很嚴重的問題,程式碼可以不經過版控系統直接推至遠端 repo。 因為只透過 shell script 檢查版號是否一致,只要更動版號後就算在本地的程式碼也能夠直接推至
im-library
repo,而且im-library
repo 也沒有做嚴格的分支保護,此情況下是可能完全找不到問題點的。workaround:
- 專案改走正規 gitlab CI/CD 流程
-
聊天室偶發斷線問題
發生異常:
- 送訊息都沒有回應,重整以後
沒有看到之前送出的訊息
。 - 推測有連線成功但送訊息沒有回應,重整後
有看到之前送出的訊息
。
推測問題原因:
- 可能平台用戶
token
已經過期,沒有做重新登入(flutter 有做) - 後端的 push message 有異常。
之後若再發生可能需與移動端討論當時如何實作這個登入機制,以及去看 sports-chatroom 專案是否有做什麼特殊處理。
- 送訊息都沒有回應,重整以後
-
svelte context module
串接平台 的部分有提到,目前與平台溝通都是透過 svelte 提供的
context module
來在平台註冊對應的 callback/setter隱憂:
如果未來需求需要掛載複數個同樣的組件到平台內,因為
context module static state
的特性,所有組件都會共享這個狀態,會造成組件互相影響、狀態管理受到污染。workaround:
-
svelte 有提供類似 react
ref
的功能,能夠呼叫組件實例內部暴露的方法,再搭配 reactref
或許能做到從SvelteAdapter
呼叫綁定的 svelte component 內部的 method/state,就能將狀態切割開來。 -
一樣使用
context module
的方式,但是多一層維度去管理各個創建的組件。可以用像是 map 去對每個創建的組件存放屬於它自己的狀態與方法。
-
-
svelte in react
在串接平台專案時有遇到的一些問題:
- react 在觸發 re-create component 時 (
key bind
、new component
) 會先產生新的 component 才會清掉舊的
,這會導致 svelte 的組件在其生命週期執行順序上會有問題(ex: 聊天室訂閱,先訂閱新的又被清掉訂閱)。
workaround:
暫時的解法都是先共用同一個組件,勁量不做
re-create
的動作。react-redux
在執行 dispatch event 時會影響到 svelte store reactive syntax 的機制,如果同時執行會導致 reactive syntax 失效。
workaround:
改成使用 store subscribe 的方式去做狀態響應式處理。
- react 在觸發 re-create component 時 (
dev true mock true