iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 3
0
Modern Web

從頭建立一套 web-based 服務架構系列 第 3

從頭建立一套 web-based 服務架構 (3) 模版架構

從頭建立一套 web-based 服務架構 (3) 模版架構

在開發 React.js 專案時,使用 JSX 語法撰寫 React component 較為方便,因此專案初始階段就需要將 JSX 相容性納入考量。除了跟隨官網的 getting started 範例,尋找合適的模版架構(boilerplate)也是很好的作法(註1),能夠以他人架好的基礎上快速開始,也可以學習 boilerplate project 內的專案優點。

React.js boilerplate 選擇眾多,一般會依照自己想要的功能需求(Server-side rendering、Redux、Flux、React-Router)和可讀性或自己的喜好來選擇。以作者個人喜好而言,會以下列功能需求做考量:

  • 語法:使用 ES6 / ES-next / JSX 進行撰寫,並搭配 Babel/Traceur 做 ES5 transpiling
  • 包含 task runner,例如 GruntGulp 或 npm scripts
  • 以 Webpack 做 JS/CSS bundling
  • 搭配 React.js 使用的 dataflow library,如 ReduxMobX
  • Testing 相關的設定(雖然作者其實本次專案不打算撰寫 testing...)
  • Linting,一般而言會使用 ESLint 並整合進 task runner

回到本次的專案架構,比起直接選擇現有的 boilerplate,我們以上述的考量點來進行專案初始化,並以最低限度的需求來做組合,之後開發過程碰到需要的功能再加進去。以下是初始化後的專案結構

gulp
src
  |- client
  |- server
webpack
.babelrc
.eslintrc
gulpfile.babel.js
package.json

Gulp 的使用

為何選擇 Gulp 作為 task runner?以作者本身曾經使用 Grunt 和 Gulp 的經驗而言,Grunt 的運作邏輯偏向以「功能完整的 plugin」搭配「gruntfile 提供的 config」運作,使用上比 Gulp 容易上手一些;然而這樣同時意味著專案的套件相依性容易受不同的 plugin 影響。

例如,若使用 grunt-webpack 進行 Webpack 整合,專案所使用的
Webpack 版本就會受限於 grunt-webpack plugin 所使用的版本(定義於 plugin 自己的 package.json);因此,當專案本身需要升級 Webpack 的話,便容易產生 dependency 衝突的狀況。
Gulp 相較之下更為輕量,雖然需要自己額外做較多設定,但也帶來比較高的彈性。

gulp 資料夾內宣告了幾個功能不同的 Gulp task:

  • build: clean + webpack,先清空上次的 build 結果後再行 build
  • clean: 清空上次的 build 結果
  • env: 強制讓 NODE_ENV 環境變數指定為 local(開發階段)或 production
  • lint: 執行 Linting 程序
  • server-hot: 運行 Webpack dev server 於開發階段使用 hot module replacement (HMR) 功能
  • server-node: 運行 server 程式
  • server-nodedev: 用 node-dev 運行 server 程式
  • server: 同時充當 default task,依 NODE_ENV 差異而有兩種版本:
    • 開發階段:lint + watch + server-hotserver-node,也就是會有兩個 server 同時運行
    • production 階段:build + server-node
  • watch: 當 src/client 的 JS 程式碼變動時重新進行 Linting。(重新 compile 這個工作由 HMR 機制負責)
  • webpack: Build 前端的 JS/CSS 程式碼,並 bundle 成兩隻檔案

關於 Webpack 和 ESLint 等設定的細節將於後續文章說明。

執行方式就是直接呼叫 gulpgulp buildgulp lint 等即可;或是再更進一步,於 package.json 的 npm scripts 宣告如何執行這些 Gulp task:

"scripts": {
    "local": "gulp",
    "production": "NODE_ENV=production gulp"
},

然後使用 npm run localnpm run production 執行。

附帶一提,包含 gulpfile.babel.js 在內,此專案所撰寫的 Gulp tasks 使用了 ES6 語法,若是沒有在 node_modules 安裝 babel-register 等 Babel 套件的話會造成執行失敗。這是因為 gulpfile 的名稱帶有 .babel 後綴,Gulp 會在 runtime 會找尋專案內的 .babelrc 檔案並試著以 babel-register 進行 transpiling 再執行的緣故。


註1:Find your Perfect React starter projectAwesome React 都值得一看


上一篇
從頭建立一套 web-based 服務架構 (2) 概覽與需求簡介
下一篇
從頭建立一套 web-based 服務架構 (4) 環境變數、ESLint 與 Babel
系列文
從頭建立一套 web-based 服務架構9

尚未有邦友留言

立即登入留言