在一個小公司最大的好處是什麼都要搞,PC/公衆號/小程序,前臺,後臺,中臺,react,vue、UI都接觸,產品需求不斷,項目越作越多,人仍是那幾個。對於前端的標準化,工程化的要求愈來愈高。css
aotoo-hub
做爲一套通用型前端腳手架,無技術棧依賴,聚焦於多人協做及工程化。能夠幫助開發者快速產出項目,喜歡折騰的能夠研究下。html
aotoo-hub
是一套前端/NODE 端一體化設計的全棧腳手架,前端使用webpack4編譯,node端使用koa2提供服務。hub可獨立運行做爲前端編譯工具,也可配合node端部署線上服務前端
獨立運行時,僅做爲前端編譯、輸出靜態資源工具,hub採用webpack對前端的資源進行編譯,開發模式下由webpack-dev-server提供熱更新支持,生產環境下僅產出壓縮後的代碼vue
融合運行時,node(koa2,koa-router)將接管webpack-dev-server提供後端服務,此時可實現SSR服務,API服務,可用於部署,提供線上服務java
一些特色node
腳手架源碼結構react
hub工做空間 ├── build ├── aotoo.config.js ├── index.js ├── package.json ├── postcss.config.js └── src # vue 項目演示 └─ vueSample ├── configs # node環境配置文件,默認包含default.js ├── dist # 靜態資源輸出目錄 ├── js # 前端業務js目錄(前端) │── venders # 第三方庫文件目錄+自定義公共庫(前端) ... └── server # node端的源碼目錄 │── pages # node端的業務目錄 └── plugins # 自定義插件目錄 # react 項目演示 └─ reactSample ├── configs # node環境配置文件,默認包含default.js ├── dist # 靜態資源輸出目錄 ├── js # 前端業務js目錄(前端) │── venders # 第三方庫文件目錄+自定義公共庫(前端) ... └── server # node端的源碼目錄 │── pages # node端的業務目錄 └── plugins # 自定義插件目錄 # 小程序項目演示 └─ xcxSample ... ... # 文檔項目演示 └─ mdSample ... ...
前端項目架構比後端項目架構更具備挑戰性,爲啥呢?通常後端架構(大部分中小項目)穩定在一個環境,語言,項目下,可能幾年更新一次,而前端要應對多端輸出,項目繁雜,多種框架,複雜組件等等狀況,框架的更新還特別活躍,常常有學不動想放棄的感受。linux
腳手架做爲一個重要前端工具,特別須要有統一的,標準化的思想。好的腳手架可以能讓開發,測試、運維的工做變得很爽。咱們須要腳手架能約束、規範工程項目結構;有統一的編譯環境;與項目去耦合;方便進行多人協做;還應該要簡單,開箱即用,開發者只需關注業務,在生成的項目結構的基礎上進行開發便可webpack
爲何須要將架構與項目去耦合,試想下,當一個公司存在n個項目時,架構師更新、維護不一樣項目,不一樣框架的腳手架,形成項目不穩定的風險,同時增長了架構師、開發人員、測試人員、運維人員,運營人員的時間成本,溝通成本。
公司項目類型不少,輕量,且須要快速迭代上線的項目,通常咱們用vue;比較複雜,由多人協做共同完成的項目。通常咱們用react;小程序也是前端的熱門方向,還有老舊基於jq項目,所以腳手架須要可以支持編譯多種前端框架
這個不是很難,在webpack中添加各類框架所需的配置就能夠實現,hub目前支持React、Vue、Angular、Jquery、小程序等技術棧。
架構與項目去耦合,便可單個項目獨立編譯運行,又能夠同時運行。全部項目共享hub工做空間的編譯環境,共享工做空間的node_module。項目自有dist目錄,啓動時有分配惟一服務端口。以下圖所示
工做空間 ├── build └── src └─ vueSample └─ dist └─ reactSample └─ dist └─ mdSample └─ dist └─ xcxSample └─ dist
命令行須要簡潔高效,可以實現環境初始化、項目初始化、開發模式、生產模式,環境切換,能夠傳遞參數,支持node、pm2部署
aotoo dev # 編譯開發環境文件,並打開webpack-dev-server服務 aotoo dev --config test # 編譯測試環境文件,並打開webpack-dev-server服務 aotoo build # 編譯生產環境文件 node index.js # 啓動項目,可用於docker pm2 start index.js # 使用pm2部署項目
命令行、配置文件相輔相成,一個都不能少,配置可以簡化命令行操做,好比須要同時啓動多項目,設置某項目的環境等。
下例是hub項目的具體配置項
{ // 項目名稱 name: 'mdSample', // 指定項目版本 version: 1.0.8, // 是否啓動項目,默認false // 啓動時,可簡化命令行輸入項目名稱 startup: true, // 是否啓動node server,默認false,由webpack-dev-server提供服務 // 如在組件開發過程當中,關閉node服務,提高性能和效率 server: false, // 省略前端編譯,默認false,須要設置server=true // 只啓動node端,開發模式提高效率,生產模式可直接部署 onlynode: false, // 項目源碼目錄 src: path.join(ROOT, 'src/mdSample'), // 指定項目端口,不指定則分配隨機端口 port: 8400, options: { // 項目灰度環境,如測試,預發佈,生產等 // 建議使用命令行 --config test,選擇環境配置 // scenes: 'default' } },
環境與項目隔離
隔離是爲了更專一,各司其職,架構師更新環境,開發人員更新業務,互不干擾,編譯環境與項目去耦合。使用git可以很方便的實現這一設想,以下圖
工做空間 # ==> 設置環境git,忽略src/* ├── build └── src └─ vueSample # ==> 設置項目git
在使得命令行工具能夠支持在項目源碼目錄中執行,開發人員使用vscode僅僅打開vueSample目錄就能夠心無旁騖的開始開發工做。
# 在hub工做空間目錄下 aotoo dev vueSample # 運行開發環境 # 在項目vueSample目錄下 cd src/vueSample aotoo dev vueSample # 在項目源碼目錄中也能夠啓動開發環境
項目版本
項目版本基於配置文件的version,項目的靜態資源會被所有編譯至dist/${version}
目錄,多個版本就會存在多個目錄,方便回滾,備份等等保險操做,以下圖
├─ dist # 輸出目錄(前端) │─ 1.0.1 # 版本目錄,依據配置中的version字段 └─ 1.0.8 └─ dev # 開發目錄 │── js/index.js │── html/index.html ...
test1環境,test2環境,test3環境...,腳手架經過命令行參數指定項目當前運行時環境配置,也能夠設置配置文件來切換。
如今不少公司都用到了apollo這樣的雲配置中心,這對於開發者來講很是不方便,有兩種方案能夠考慮,一是使用命令行傳遞不一樣參數,使項目調用雲配置或者本地配置;二是在項目初始化時,在配置文件中建立方法去自動抓取雲配置。
aotoo dev --config test1
設計合理、規範、靈活的模板對於項目結構的合理性很是有好處,由於咱們都圍繞模板來創建目錄,產出資源,而任何資源最終都被用在模板上。
模板的靜態資源
<html> <head> <link href="common.css" /> <link href="[filename].css" /> </head> <body> <div id="root"><%- root %></id> <script src="vendors.js" /> <script src="common.js" /> <script src="[filename].js" /> </body </html>
如上例模板較爲規範,能夠很容易輸出規範的項目目錄結構,大體有以下
project ├── html └── index.html ├── css └── index.css └── js └── index.js
在hub項目中,大部分狀況下咱們能夠省略html目錄和css目錄(無額外需求),目錄結構能夠精簡以下
project └── js └── index.js
做爲hub項目,它能夠正常運行,hub在編譯時會自動爲該項目生成模板、樣式、node等等。
仿小程序目錄結構
hub項目的目錄結構也能夠項小程序或者Vue這樣設置,以下例
project └── js └── user ├── index.js # 輸出業務JS => user.js ├── index.css # 輸出業務CSS => user.css └── index.html # 輸出業務模板 => user.html
前面剛說了模板很重要,但卻選擇了基於JS索引生成webpack的entry,這裏有一個假設前提,即每個模板頁面必然包含一個業務JS。
基於JS索引構建的entry對於webpack來講有自然的親和性,可使用webpack-html-plugins自動生成其對應的模板。
做爲編譯入口,咱們能夠爲webpack的entry賦予了更多的職能,爲entry的每個trunk編譯其靜態資源、生成node端路由、生成node端api等等。
reactSample
hub的演示項目reactSample目錄結構很是簡單,構成以下
reactSample ├── configs/default.js # 環境配置,實際上也是編譯時生成的 └── js/index/index.js
該項目所需的資源文件在編譯時自動生成,樣式在運行時由JS注入,生產環境提供node服務,開發環境提供dev-server服務。服務端提供模板渲染、鏡像路由,鏡像API等服務。而這些只是一個命令node index.js
就ok了
終極目標固然是實現MPA-SPA混合模式,即多-單頁模式,H5須要SPA,PC須要MPA+SPA。MPA很簡單,node端輸出的頁面都是獨立的頁面,有模板就行,是自然的MPA模式。
hub工做空間 ├── mdSample ├─ dir1 # => page1.html ├─ dir2 # => page2.html └─ dir3 # => page3.html
hub也可以很容易的爲react,vue提供MPA-SPA模式,這是hub腳手架自帶的buf
引入node端能夠解決
鏡像路由
經過webpack的entry構建的node路由,稱之爲鏡像路由,鏡像路由能夠提供頁面渲染服務和API數據接口服務
鏡像路由示意結構
reactSample └── js └── user/index.js # 前端 └── server └── pages/user/index.js # node端 # 訪問鏡像路由 http://www.abc.com/user # 請求API數據路由 ajax.post('/user', {...}).then(res) # node端controler文件 server/pages/user/index.js
咱們知道koa2是典型的MVC後端模型,view對應模板,model對應數據層(由業務驅動,大部分是ajax數據)。將entry的trunk與koa-router綁定,就構成與前端的鏡像路由關係(一一對應),同時輸出其controler文件用來處理GET/POST/PUT/DELETE等事務
自定義路由
有些路由與頁面沒有關係,好比上傳,API接口就屬於這一類特殊的路由,因此咱們還須要經過plugins來手動建立自定義的路由
插件用來建立自定義路由與建立功能模塊,自定義路由如上所述。
功能模塊的典型應用是數據庫請求。controler層通常都須要發起數據庫請求,插件將功能模塊綁定到koa的context上。注意這個過程是一個預處理過程,而controler層的運行則屬於運行時過程,所以只要controler層有須要就能夠從koa的上下文中得到數據處理模塊用來發起數據庫請求
對於小程序項目,咱們要控制webpack輸出,不要讓它作多餘的事情,最終輸出代碼由微信小程序開發工具來處理
按照1:1對等輸出小程序源碼,僅利用webpack處理一下小程序的一些小毛病,好比markdown,動態樣式,html等等。(輸出不會產生webpack的冗餘代碼),支持熱更新
使用webpack參與小程序編譯,咱們可使用loader/plugins實現一些想法,好比寫個loader,將微信小程序轉譯成其餘小程序,只是對照表有點麻煩,思路應該是可行的
我也是個前端老人了,前端切圖仔的歲月依稀在眼前,前端後端的融合開發模式(java渲染模板)痛點在於你要搭一個java環境,你須要知道模板中的每個ID,你對模板龐雜的結構瞭若指掌。
在腳手架編譯的同時,將全部資源收集起來並整理一份資源文件(mapfile.json),包含JS/HTML/CSS/IMAGE等信息。將mapfile.json交給java大佬,將靜態資源文件目錄(dist)交給運維大哥,請求java大佬寫一份腳本自動匹配靜態資源。
項目包含(REACT/VUE/小程序/MD 文檔系統)等 4 套 DEMO 演示項目,每一個項目便是獨立項目,又可以經過node端實現資源互通。方便快速上手各套環境。
vueSample,基於vue2.0 的空項目,包含vue-router簡單項目演示
vue的演示項目沒有上vue3.0,由於開發時vue3.0周邊庫尚未穩定,打算讓它再飛一會,你也能夠自行引入,更多說明
reactSample,一個空項目,包含REACT16 的簡單演示。
xcxSample,是原生微信小程序開發,支持雲開發,該項目包含咱們開發的小程序庫queryUI庫及相關組件,清空相關引用就是一個完整的小程序官方示例代碼。更多說明
這裏重點講一下文檔系統,文檔系統是一套hub環境的完整演示,包含前端編譯,路由,NODE 端鏡像路由、插件,MPA/SPA應用,命令行的使用等等,更多說明
aotoo-hub
安裝完成後的目錄結構
hub工做空間 ├── build ├── aotoo.config.js ├── index.js ├── package.json ├── postcss.config.js └── src # vue 項目演示 └─ vueSample ├── configs # node環境配置文件,默認包含default.js ├── dist # 靜態資源輸出目錄 ├── js # 前端業務js目錄(前端) │── venders # 第三方庫文件目錄+自定義公共庫(前端) ... └── server # node端的源碼目錄 │── pages # node端的業務目錄 └── plugins # 自定義插件目錄 # react 項目演示 └─ reactSample ├── configs # node環境配置文件,默認包含default.js ├── dist # 靜態資源輸出目錄 ├── js # 前端業務js目錄(前端) │── venders # 第三方庫文件目錄+自定義公共庫(前端) ... └── server # node端的源碼目錄 │── pages # node端的業務目錄 └── plugins # 自定義插件目錄 # 小程序項目演示 └─ xcxSample ... ... # 文檔項目演示 └─ mdSample ... ...
項目配置文件,包含項目版本,項目類型,項目源碼目錄等各類配置
apps: [ { name: 'reactSample', // 項目名稱 version: '1.0.1', // 項目版本,每一個項目有本身的版本 startup: true, // 是否默認啓動 server: false, // 是否提供node端服務,默認爲`dev-server`提供服務 type: 'web', // 項目類型, 'mp'爲小程序 src: path.join(ROOT, 'src/reactSample'), // 源碼目錄 micro: false, // 是否微服務模式(開發中,未完善) options: { // 項目擴展參數 scenes: 'default',// 默認項目環境,將生成環境配置文件 cloud: false, // 小程序項目是否啓動雲端 }, port: 8500 // 項目端口 }, { name: 'vueSample', ... }, { name: 'xcxSample', ... } ], }
該目錄存放環境配置,編譯器會根據命令行所給出的環境參數生成相關的配置,好比測試環境(test=>test.js)
aotoo dev --config test
該目錄存放前端編譯文件,包含版本目錄,開發目錄,生產目錄
├─ dist # 輸出目錄(前端) │─ 1.0.1 # 版本目錄,依據配置中的version字段 └─ 1.0.8 └─ dev # 開發目錄 │── js/index.js │── html/index.html ... └── mapfile.json # 靜態資源鏡像文件 └─ pro # 生產目錄 │── js/index_[hash].js # 生產文件會帶上hash ... └── mapfile.json # 靜態資源鏡像文件
該目錄存放前端JS源碼,公共JS源碼,業務JS源碼
├─ js │─ vendors # 公共JS └─ index # 前端業務目錄 │─ index.js # 業務 => dist/.../index.js │─ index.scss # 樣式 => dist/.../index.css └─ index.html # 模板 => dist/.../index.html └─ shop # 前端業務目錄 │─ index.js # 業務 => dist/.../shop.js │─ index.scss # 樣式 => dist/.../shop.css └─ index.html # 模板 => dist/.../shop.html
編譯思路
編譯器遍歷業務JS文件並生成其配套資源(html/css/node)
dll打包(vendors目錄)
這裏dll打包指代打包vendors.js
和common.js
,須要注意的是,vendors是一套獨立的webpack打包進程,與業務JS打包不在一個進程,將生成dist/.../vendors.js
文件,common.js
來自業務JS的分離代碼(webpack的split)。其中vendors.js
文件不支持熱更新
業務打包
業務打包以JS文件做爲webpack的entry,經過loader模塊同時生成其相關靜態資源,如上例的shop目錄
該目錄存放通用代碼或者框架庫,好比在vendors/index.js
中引入react或者vue,須要注意,該目錄的內容會被應用到node端
(若是啓用了server服務),因此必定要注意兩端的兼容性寫法
當你在配置中設置server參數爲true時,編譯器將會自動生成server目錄,並將後端服務由webpack-dev-server
轉向由node端提供的服務
鏡像路由server/pages
當你在配置中設置server參數爲true時,編譯器會遍歷entry(業務JS),並鏡像生成其node端的controler文件,如上例shop
server └─ pages └─ shop └─ index.js
controler文件默認提供渲染服務、GET、POST接口服務
node端插件server/plugins
該目錄須要手動生成,插件支持自定義路由,支持自定義功能模塊
aotoo-cli
是aotoo-hub的命令行開發工具庫,安裝、編譯都須要經過此工具來操做更多說明
npm install -g aotoo-cli aotoo -V # 檢查是否安裝成功
init <dir>
# 新建xxx項目 $ aotoo init xxx
create <dir>
自動建立pc/h5/公衆號等web項目並啓動項目
# 新建項目 $ cd xxx $ aotoo create projectName
將會在xxx/src目錄下,建立項目目錄projectName
,按照提示輸Y
,回車繼續
完成安裝後,修改aotoo.config.js
,補充項目描述
create <dir>
適用於建立小程序項目
# 新建項目 $ cd xxx $ aotoo create minip_name
將會在xxx/src目錄下,建立項目目錄minip_name
,提示請輸入n
完成安裝後,打開aotoo.config.js
,補充項目描述,從新啓動項目
安裝完成後,hub的src目錄下包含4個演示項目,經過如下命令能夠分別啓動
# 文檔項目屬於默認項目,能夠直接啓動 $ aotoo dev
$ aotoo dev vueSample
$ aotoo dev reactSample
編譯完成後須要使用小程序開發工具打開終端黃色字體指示的目錄
$ aotoo dev xcxSample
開發模式編譯,並啓動服務,前端支持熱更新
# 啓動aotoo.config中apps中的啓動項目 $ aotoo dev # 啓動指定項目 $ aotoo dev project_name
開發模式編譯,清除common/vendors等dll文件,從新生成,並啓動服務
$ aotoo dev-clean # 啓動指定項目,並清除該項目common的緩存 $ aotoo dev-clean project_name
開發模式編譯,清除common/vendors等dll文件,從新生成,不啓動服務
$ aotoo dev-build # 編譯指定項目 $ aotoo dev-build project_name
生產模式,純編譯輸出,不啓動服務
$ aotoo build # 編譯指定項目 $ aotoo build project_name
生產模式,清除common/vendors等dll文件,並從新生成,不啓動服務
$ aotoo build-clean # 編譯指定項目 $ aotoo build-clean project_name
部署以前,須要先以生產模式編譯
aotoo build-clean project_name
生產模式,啓動node服務
$ aotoo start # 編譯指定項目 $ aotoo start project_name
# 編譯項目,生產模式 $ node index.js # 啓動測試環境 $ node index.js --config test # 進入源碼server目錄啓動 $ cd src/project_name/server $ node index.js
# 編譯項目,生產模式 $ aotoo build-clean project_name # 啓動測試環境 $ pm2 start index.js -- --config test
--config <name>
指定環境配置文件,配合node端一塊兒使用
# 開發模式,啓動測試環境 aotoo dev --config test # 生產模式,啓動測試環境 aotoo build --config test
--name <name>
啓動指定項目,該參數可多項目同時啓動
# 同時啓動 xxx 及 yyy的項目 $ aotoo dev --name vueDemo --name reactDemo