前言現在的 Node 對於前端而言可以涵蓋各個方面,包括命令行介面、插件、依賴庫、腳手架以及 Web 服務等。本文是一篇對於 Node 使用的淺談文章,會簡單講解一些個人使用 Node 的經驗,分享的內容主要可分為三個方面: 工具篇 插件篇 服務篇 工具篇會講解使用 NPM 發佈命令行介面的簡單教程 ...
前言
現在的 Node 對於前端而言可以涵蓋各個方面,包括命令行介面、插件、依賴庫、腳手架以及 Web 服務等。本文是一篇對於 Node 使用的淺談文章,會簡單講解一些個人使用 Node 的經驗,分享的內容主要可分為三個方面:
- 工具篇
- 插件篇
- 服務篇
工具篇會講解使用 NPM 發佈命令行介面的簡單教程。插件篇主要講述如何開發一個有趣的 Webpack 插件(Vue CLI / Babel 插件同理)。服務篇會講解一些基於 Express 應用框架的技術選型方案,這類技術往往對於做一些前端工具平臺非常有用(例如 Mock 平臺、多語言平臺等,往往可配合命令行介面進行設計)。由於篇幅較長,本文只講解服務篇內容。
溫馨提示:
1.這裡的服務篇主要講解了一些自己搭建 Express 應用的經驗,是自己學習 Node 的一個過程。大家如果喜歡折騰或者想做一些前端的工具平臺可以按照這種思路去嘗試,但是如果要做業務項目,大家還是要選擇一些成熟穩定的技術方案,考慮的方面需要更多。
2.不要在博客私信我、大家有問題或者交流經驗可以來我的扣扣裙 519293536 找 我 都會儘力幫大家哦
Web 應用框架
基於 Node.js 的 Web 應用框架很多,包括但不限於
- Express : 已經成為開發 Node.js WEB 應用的標準框架,大多數工程師都很熟悉他的設計思想(極簡的內核,但能讓你用各種中間件來擴展他的功能)
- Koa :設計思想非常類似 Express,區別在於它是使用 ES6 中的 generator 編寫,這種寫法解決了大家所熟知的回調地獄問題
- Feathers:用來實現面向服務架構的一種靈活的解決方案,非常適合創建 Node.js 微服務
- Sails :是一個全能的 MVC 框架,主要是受到 Ruby on Rails 啟發,已經存在很長時間,支持各種資料庫,不管是 SQL 還是 No-SQL
- Egg :為企業級框架和應用而生
- Modal:創建基於 PostgreSQL 的無狀態的、分散式的服務
- Keystone:快速搭建基於 MongoDB 的管理後臺的最佳解決方案,基於數據模型的定義即可自動生成後臺界面,支持常見的增刪改查操作和靈活的數據過濾
- Loopback:內置了很多特性的成熟框架,支持基於 token 的認證,支持各種資料庫。 loopback 的“殺手鐧”功能是 API 瀏覽器,該功能能讓開發者用非常直觀的方式查看所有的 API 介面,如果你需要創建 API 服務的話,它無疑是個很好的選擇
這裡盜一張 2019 Node.js Frameworks star 情況(供大家參考):
本文主要講解 Express 應用框架,雖然它提供的能力非常簡單,但對於一些工具平臺的開發完全可以勝任,並且可以寫出各種千奇百怪的 MVC 模式(如果對服務端 MVC 不是很清晰可以閱讀 服務端 MVC 之 Model2 的衍生)。這裡簡單介紹以前設計的幾種基於 Express 擴展的技術選型方案,恰好涵蓋了 React、Angular 以及 Vue 這三個 Web 前端框架。
溫馨提示:接下來使用的示例項目都相對簡單,希望對剛入門 Express 的小白們有所啟示。
React 技術方案選型
2016年7月到10月,從零開始學習 React 並使用 React 設計了服務端渲染的 Express 應用(同年10月25日誕生了 Next.js ),大致的技術選型如下:
- Bootstrap
- React
- Mongoose
- Webpack
- Karma/Chai
由於對 React 不是很熟悉,首先實現了單頁應用,然後實現了服務端渲染應用。
實現 React 單頁應用(SPA)
React 學習和設計過程
在使用 React 之前只會簡單的使用 Bootstrap,當時對 React 的學習歷程大致如下:
- 學習 React 語法
- 學習 ES6 / ES7 語法
- 學習 Babel / Webpack,打包代碼支持 ES6 / ES7 / JSX 語法
- 學習 webpack-dev-server / Hot Module Replacement,啟動開發環境的 Express 服務,實現熱載入功能
- 學習 flux / react-redux
- 學習 react-router
- 學習 mocha / karma
學習總結文檔如下:
以上學習過程記錄在 react-demo 和 react-start-kit (小而全的概念性參考價值)中,此時只是簡單的 React 單頁應用設計過程。大致結構如下:
溫馨提示:在前後端分離的開發模式中,如果 Web 前端實現的是 SPA(單頁應用),服務端可以選用不同的設計語言,例如 Node.js、Java 或者 Golang 等。Web 前端可以通過 Express渲染伺服器 進行後端的請求代理轉發。如果想要前端先行,可以使用 Easy Mock 或者自己設定的 JSON 數據模擬後端提供的介面規範。
Express 服務端設計過程
服務端的設計選用 Node.js 的 Express 框架,大致實現步驟如下:
- 搭建服務端 Express,設計服務端 MVC 目錄結構
- 設置 Express 的靜態資源目錄,將 Web 前端的 Webpack 構建目錄設置成 Express 的靜態資源目錄
- 設置單頁應用的路由和路由服務
- 啟動服務查看頁面是否可以渲染成功
以上實現過程記錄在一個簡單的示例 rewatch 里,入口文件是 app.js
。此時前後端分離,可以同時啟動服務端 Express 服務和啟動開發態 React 調試頁面服務(webpack-dev-server),並使用開發態頁面向 Express 服務發送請求獲取介面數據(當時使用 JQuery 的$.ajax
發送請求)。設計完成後將開發態頁面使用 Webpack 打包構建,構建目錄為服務端 Express 的靜態資源目錄。首屏渲染的工作交給 Ejs 模板引擎(事實上也可以直接使用 HTML 字元串渲染)進行處理。大致結構如下:
實現 React 服務端渲染(SSR)
單頁應用在路由跳轉時不需要額外的請求靜態資源,可以提升用戶的體驗。但是如果應用較大,首次請求靜態資源和進行頁面動態渲染的過程中會產生以下問題:
- 首屏載入慢,產生白屏效果
- 不利於 SEO
為瞭解決上述客戶端的渲染問題,需要實現 React 服務端渲染。由於當時還沒出現成熟的服務端渲染應用框架,因此只能自己摸索構建 React 服務端渲染方案:
- 為了實現前後端代碼同構,需要對服務端代碼進行 Webpack 打包配置
- 使用 script 標簽以及全局變數的形式實現前後端
react-redux
數據store
的統一(這個印象深刻,當時思索了很久)
使用了服務端渲染方案後,可以去除之前的 Ejs 模板引擎,當時設計的大致結構如下:
當頁面發送路由請求時,Express 服務端使用
react-router
匹配相應路由對應的 React 組件實例並調用 renderToString
方法進行服務端頁面渲染(實現頁面的局部刷新)。當頁面渲染完成後,由 React 打包後的靜態資源對頁面進行 hydrate 處理。此時的 React 代碼是同構的,因此需要註意哪些會運行在服務端,哪些會運行在客戶端。同時服務端需要對同構代碼進行Webpack 打包處理。
以上實現記錄在示例 rewatch 中,入口文件是 server.js
,由於文件比較混亂(把客戶端渲染和服務端渲染的示例放在了同一個文件項目中),這裡給出另外一個非常簡單的示例 rewatch-server-render,項目目錄結構如下:
.
├── public # 靜態資源目錄
│ └── js
│ ├── bundle.js # react 目錄打包文件
│ ├── common.js # react 目錄打包公共文件
│ ├── react-dom.min.js # react 庫文件
│ └── react.min.js # react 庫文件
├── react # react 同構代碼目錄(沒有 react-router,可以查看 rewatch 示例)
│ ├── actions
│ ├── components
│ ├── containers
│ ├── reducers
│ ├── store
│ └── index.js
├── server # 服務端
│ └── routes # 服務端路由(沒有使用 react-router 同構,可以查看 rewatch 示例)
├── server.js # 開發態服務入口文件
├── server.bundle.js # 生產態服務入口文件
├── webpack.browser.config.js # 靜態資源打包的 webpack 配置(目標文件 bundle.js、common.js)
└── webpack.node.config.js # 服務端打包的 webpack 配置(目標文件 server.bundle.js)
複製代碼
Angular 技術方案選型
2016年10月到2017年3月,使用 Angular 設計了一個 Express 應用,大致的技術選型如下:
- Ejs
- Bootstrap
- Angular-Chart
- Mongoose
- Redis
- Sokect.io
這是一個簡單的服務端多頁應用示例,使用 Ejs 模板引擎進行頁面渲染,渲染完成後交由 Anguar 進行頁面的響應操作(發送請求使用 Angular 內置的 $http
服務)。該示例不需要額外的 Webpack 配置,只需要啟動 Express 服務本身渲染設計即可。目錄結構如下:
.
├── client # 靜態資源目錄
│ ├── css/ # 樣式
│ ├── imgs/ # 圖片
│ ├── js/ # 腳本
│ │ ├── angular/ # angular應用
│ │ │ ├── controllers/ # angular控制器
│ │ │ ├── services/ # angular服務
│ │ │ └── webapp.js/ # angular自動引導應用程式
│ │ └── sockets/ # sockets應用
│ └── lib # 插件(包括angualr、bootstrap/bootstrap-table、chart等)
├── config # 配置(包括Redis、Mongoose配置)
│ ├── config.js # 參數配置
│ └── index.config.js # 導出配置
├── server # 服務端
│ ├── constants/ # 常量
│ ├── controllers/ # 控制器
│ ├── events/ # 事件
│ ├── models/ # 模型
│ ├── routes/ # 路由
│ ├── sockets/ # socket.io
│ ├── pubs/ # Redis發佈
│ └── subs/ # Redis訂閱
├── views # 視圖(使用Ejs模板引擎)
└── app.js # 服務入口文件
複製代碼
溫馨提示:這種多頁應用框架是天然的 SSR 模型,一般都需要配合模板引擎進行設計。
Vue 技術方案選型
2018年6月,使用 Vue 設計了服務端渲染的 Express 應用,大致技術選型如下:
- Mongoose
- Nuxt
- Vue
- lokka
- Muse-UI
- 客戶端和服務端同構代碼的 Webpack 配置由 Nuxt 封裝
- 服務端 Backpack 配置
該技術選型最主要的特點如下:
- 支持服務端渲染
- 支持 Graphql 查詢語言
- 前後端統一 TypeScript 語法
選型詳細說明
- 為了支持 Graphql 查詢語言,服務端選擇使用支持 Express 中間件擴展的 graphql-yoga。
- 客戶端的 HTTP 請求需要符合 Graphql 請求格式,一種方式是使用 axios 等模擬 Graphql 的請求格式,另外一種方式是選用支持Graphql 請求格式的請求庫,這裡選用 lokka 作為 Graphql 客戶端的請求庫。
- 為了快速設計頁面,選用了基於 Vue 2.0 的 Material Design UI 組件庫 Muse-UI。
- 選用了 Nuxt 作為服務端渲染的中間件(基於 Vue.js 的通用應用框架,預設了服務端渲染應用所需要的各種配置)。
- 為了支持客戶端 TypeScript 語法,需要擴展 Nuxt 的預設 Webpack 配置,利用 Nuxt 的模塊/註冊自定義loaders配置 ts-loader,配合 nuxt-property-decorator 實現客戶端 TypeScript 語法。
項目目錄結構
在 Nuxt 的目錄結構中,服務端引入的同構代碼放在.nuxt
目錄中,是 Webpack 打包後的代碼文件,因此如果服務端不使用特殊的語法,完全不需要 Backpack 配置。此項目為了支持服務端 TypeScript 語法,使用 Backpack 對服務端代碼進行構建(不影響同構部分代碼的構建,同構代碼在 Nuxt 里是通過讀取文件的方式獲取)。
.
├── .nuxt # Nuxt構建目錄(Nuxt預設目錄)
├── assets # 資源目錄(Nuxt預設目錄)
│ ├── img # 圖片
│ ├── icon # 圖標
│ └── style # 樣式
├── build # 配置(包括Redis、Mongoose配置)
│ └── main.js # 服務端Backpack構建的目標啟動入口文件
├── common # 前後端通用
│ ├── constants/ # 常量
│ └── types/ # TypeScript介面
├── components # 組件目錄(Nuxt預設目錄)
├── constants # 前端常量目錄
├── docs # 文檔目錄(渲染.md文件)
├── graphql # 前端Graphql請求介面
├── layouts # 佈局目錄(Nuxt預設目錄)
├── middleware # 中間件目錄(Nuxt預設目錄)
├── mixins # 全局mixins
├── modules # Nuxt模塊(TypeScrpt的Webpack配置擴展)
├── pages # 頁面目錄(Nuxt預設目錄)
├── plugins # 插件目錄(Nuxt預設目錄)
├── server # 服務端目錄
│ ├── constants/ # 常量
│ ├── database/ # 資料庫模型
│ ├── express/ # 服務對外的公共API介面
│ │ ├── controllers/ # 控制器
│ │ ├── routes/ # 路由
│ │ └── services/ # 服務
│ ├── graphql/ # 服務內部的Graphql查詢介面
│ │ ├── middlewares/ # Graphql中間件
│ │ ├── resolvers/ # Graphql Resolver
│ │ ├── schemas/ # Graphql Schema
│ │ └── index.ts # graphql介面入口文件
│ ├── types/ # TypeScript介面
│ ├── utils/ # 工具方法
│ └── index.ts # 服務端入口文件(Backpack構建入口地址)
├── static # 靜態文件目錄(Nuxt預設目錄)
├── store # Vuex目錄(Nuxt預設目錄)
├── utils # 客戶端工具方法
├── .cz-config.js # cz提交配置文件
├── .env # 環境變數
├── .gitignore # Git忽視文件
├── .huskyrc # Git鉤子配置文件
├── .vcmrc # cz校驗配置
├── app.html # html文件
├── backpack.config.js # Backpack配置文件
├── CHANGELOG.md # 升級日誌
├── ecosystem.config.js # PM2啟動配置文件
├── index.d.ts # TypeScript聲明文件
├── nuxt.config.js # Nuxt配置文件
├── package.json # 項目描述文件
├── README.md # 說明
├── tag.bat # 項目打Tag腳本
└── tsconfig_node.json # TypeScript配置文件
複製代碼
運行腳本設計
在package.json
中的配置腳本如下:
"build": "cross-env NODE_ENV=production nuxt build && backpack build",
"pm2": "pm2 start ecosystem.config.js",
"pm2:stop": "pm2 stop ecosystem.config.js",
"dev:client": "cross-env NODE_ENV=development DEV_TYPE=nuxt ts-node --compiler ntypescript --project tsconfig_node.json ./server",
"dev:server": "cross-env NODE_ENV=development DEV_TYPE=server ts-node-dev --compiler ntypescript --project tsconfig_node.json ./server"
複製代碼
build
:使用 Webpack 構建 Nuxt 資源包以及使用 Backpack 構建服務端入口文件(轉義 TypeScript)pm2
:以生產模式啟動一個進程守護的 Web 伺服器pm2:stop
:停止運行 Web 伺服器dev:client
:啟動開發態熱部署前端渲染服務dev:server
:啟動開發態熱啟動服務端服務
雖然是服務端渲染框架(理論上可以一個人開發項目,啟動一個熱載入的服務端命令即可),但是在開發的過程中考慮到多人協作以及開發的便利性仍然將客戶端和服務端進行分離。
在服務端配置 Nuxt 的 Builder
會導致服務端熱載入過慢,因此將服務端 Nuxt 的 Builder
過濾掉,使用 ts-node-dev 做服務端熱啟動。在客戶端使用 ts-node 啟動服務,通過識別 DEV_TYPE
環境變數載入Nuxt的 Builder
,實現 Web 前端的熱載入功能。需要註意客戶端向服務端發送請求是跨域的,因此在服務端的開發態環境需要配置允許跨域。
溫馨提示:一個服務端渲染框架楞是讓我拆成了前後端開發分離的框架模式。
最後
設計了以上三個方案後,發現從零開始構建一個 Express 應用時至少需要考慮以下幾個方面:
- 資料庫( MongoDB / MySql 等)選型
- 是否需要模板引擎以及模板引擎( Ejs / Jade 等)選型
- 前端框架( JQuery / Angular / React/ Vue 等)選型
- HTTP 請求庫(axios / request / superagent 等)選型
- 是否需要 UI 組件庫以及 UI 組件庫選型
- 客戶端是否需要 Webpack 構建
- 服務端是否需要 Webpack / Backpack 構建
- 其他(session、redis、socket.io 等)
- 性能、監控等
簡單的起手式
- MongoDB
- Ejs 模板引擎
- JQuery
- JQuery 內置的
$.ajax
- Bootstrap(可選)
- 客戶端和服務端都不需要 Webpack 配置
對於 Express 新手而言,可以先嘗試多頁應用 + MongoDB + 模板引擎 + JQuery 的選型方案:
- 使用 Ejs 模板引擎需要額外瞭解 Ejs 語法,但是語法相對簡單,學習成本低。
- 使用 JQuery 不需要考慮 HTTP 請求庫選型,JQuery 內置了 HTTP 請求的 API。
- 如果對於頁面佈局以及樣式設計不熟悉,可以考慮選用 Bootstrap 前端框架。
- 不需要深入瞭解 ES6 / ES7 / JSX 等語法,因此不需要學習和使用 Webpack 配置。
- 使用 Ejs 模板引擎進行渲染的 Express 應用,是天然的服務端渲染應用。
主流框架的應用設計
- MongoDB
- 無需模板引擎
- React / Vue 等
- axios / request / superagent 等
- Ant Design / Ant Design Vue / Element / Muse-UI 等
- 客戶端 Webpack 配置
- 服務端是否需要 Webpack / Backpack 配置依據情況而定
如果前端框架選型是 React 或 Vue(通常是單頁應用設計),並且需要使用 ES6 / ES7 / JSX 以及 Vue 的 SFC 格式等語法,那麼Web前端勢必要設計 Webpack 的構建配置,此時可以使用類似於 webpack-dev-server
的 Express 開發態渲染伺服器設計和調試開發態前端頁面。當然目前的 Web 前端開髮針對不同的前端框架都有自己設計的腳手架,因此可以直接使用腳手架進行開發設計和靜態資源構建。同時如果框架中沒有內置 HTTP 請求庫,可以自己封裝或者使用一些成熟的 HTTP 庫,例如axios、request以及superagent等。如果需要使用 UI 組件庫進行頁面設計,可以根據使用的框架進行 UI 組件庫選型,例如 React 的 Ant Design、Vue 的 Element 等。Express 服務端的設計由於使用了主流框架的動態渲染能力,因此可以去除模板引擎渲染功能。如果想支持 Node.js 不支持的 ES6 / ES7 / TypeScript 語法等,那麼需要 Backpack 進行服務端構建。
溫馨提示:不要在博客私信我,大家有問題或者交流經驗可以來我的扣扣裙 519293536 找 我 都會儘力幫大家哦
本文的文字及圖片來源於網路加上自己的想法,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理