在一个小公司最大的好处是什么都要搞,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