乐趣区

关于前端:2020成绩单前端脚手架的开发思路与实现

在一个小公司最大的益处是什么都要搞,PC/ 公众号 / 小程序,前台,后盾,中台,react,vue、UI 都接触,产品需要一直,我的项目越做越多,人还是那几个。对于前端的标准化,工程化的要求越来越高。

aotoo-hub作为一套通用型前端脚手架,无技术栈依赖,聚焦于多人合作及工程化。能够帮忙开发者疾速产出我的项目,喜爱折腾的能够钻研下。

aotoo-hub是一套前端 /NODE 端一体化设计的全栈脚手架,前端应用 webpack4 编译,node 端应用 koa2 提供服务。hub 可独立运行作为前端编译工具,也可配合 node 端部署线上服务

独立运行时,仅作为前端编译、输入动态资源工具,hub 采纳 webpack 对前端的资源进行编译,开发模式下由 webpack-dev-server 提供热更新反对,生产环境下仅产出压缩后的代码

交融运行时 ,node(koa2,koa-router) 将接管 webpack-dev-server 提供后端服务,此时可实现 SSR 服务,API 服务,可用于部署,提供线上服务

一些特点

  • 提供简略的命令行工具
  • 编译环境反对多我的项目,共享编译资源及 node_module
  • 反对为 React/Vue/Jq/ 原生 js/ 小程序等我的项目提供编译环境
  • 标准的前端、node 端目录构造
  • 反对动静款式(sass/stylus)
  • 反对多环境,命令行切换测试,生产等环境
  • 反对 node 端(koa2)

脚手架源码构造

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 
             ...
             ...

GITHUB
更多阐明

hub 脚手架开发的一些思路

前端我的项目架构比后端我的项目架构更具备挑战性,为啥呢?个别后端架构 (大部分中小我的项目) 稳固在一个环境,语言,我的项目下,可能几年更新一次,而前端要应答多端输入,我的项目繁冗,多种框架,简单组件等等状况,框架的更新还特地沉闷,常常有学不动想放弃的感觉。

脚手架作为一个重要前端工具,特地须要有对立的,标准化的思维。好的脚手架可能能让开发,测试、运维的工作变得很爽。咱们须要脚手架能束缚、标准工程项目构造;有对立的编译环境;与我的项目去耦合;不便进行多人合作;还应该要简略,开箱即用,开发者只需关注业务,在生成的我的项目构造的根底上进行开发即可

与我的项目解耦

为什么须要将架构与我的项目去耦合,试想下,当一个公司存在 n 个我的项目时,架构师更新、保护不同我的项目,不同框架的脚手架,造成我的项目不稳固的危险,同时减少了架构师、开发人员、测试人员、运维人员,经营人员的工夫老本,沟通老本。

技术栈无关

公司我的项目类型很多,轻量,且须要疾速迭代上线的我的项目,个别咱们用 vue;比较复杂,由多人合作共同完成的我的项目。个别咱们用 react;小程序也是前端的热门方向,还有老旧基于 jq 我的项目,因而脚手架须要可能反对编译多种前端框架

这个不是很难,在 webpack 中增加各种框架所需的配置就能够实现,hub 目前反对 React、Vue、Angular、Jquery、小程序等技术栈。

多我的项目反对

架构与我的项目去耦合,即可单个我的项目独立编译运行,又能够同时运行。所有我的项目共享 hub 工作空间的编译环境,共享工作空间的 node_module。我的项目自有 dist 目录,启动时有调配惟一服务端口。如下图所示

工作空间
  ├── build
  └── src
       └─ vueSample
             └─ dist
       └─ reactSample
                └─ dist
       └─ mdSample
             └─ dist
       └─ xcxSample
             └─ dist

命令行工具

命令行须要简洁高效,可能实现环境初始化、我的项目初始化、开发模式、生产模式,环境切换,能够传递参数,反对一键部署

配置化

命令行、配置文件相辅相成,一个都不能少,配置可能简化命令行操作,比方须要同时启动多我的项目,设置某我的项目的环境等。

下例是 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>
  • common.js 拆散的公共 JS 代码,由 webpack 编译时提取,注入
  • vendors.js 第三方框架库及通用库,对应 js/vendors 目录
  • common.css 公共 CSS,对应 css/common.[css|scss|styl]文件
  • [filename].js 业务 JS,对应业务目录 / 文件名称如 user.js
  • [filename].css 业务 CSS,对应业务目录 / 文件名称如 user.css
  • hub 应用 ejs 解析模板,由 node 或 webpack-dev-server 解析模板

如上例模板较为标准,能够很容易输入标准的我的项目目录构造,大抵有如下

 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

对于 webpack 的 entry

后面刚说了模板很重要,但却抉择了基于 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 中间层

引入 node 端能够解决

  • 跨域
  • 独立部署
  • 自定义 API
  • mock 服务
  • seo

路由

镜像路由
通过 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 端实现资源互通。不便疾速上手各套环境。

Vue 演示 DEMO

vueSample,基于 vue2.0 的空我的项目,蕴含 vue-router 简略我的项目演示

vue 的演示我的项目没有上 vue3.0,因为开发时 vue3.0 周边库还没有稳固,打算让它再飞一会,你也能够自行引入,更多阐明

REACT 演示 DEMO

reactSample,一个空我的项目,蕴含 REACT16 的简略演示。

小程序演示 DEMO

xcxSample,是原生微信小程序开发,反对云开发,该我的项目蕴含咱们开发的小程序库 queryUI 库及相干组件,清空相干援用就是一个残缺的小程序官网示例代码。更多阐明

  • 动静款式反对
  • webpack 的各种插件反对
  • 原生微信小程序
  • 动静模板构建
  • template less
  • 反对钩子办法
  • 内置反对 MARKDOWN 富文本
  • 内置反对 HTML 富文本
  • 由 aotoo 库构建

MD 文档零碎

这里重点讲一下文档零碎,文档零碎是一套 hub 环境的残缺演示,蕴含前端编译,路由,NODE 端镜像路由、插件,MPA/SPA 利用,命令行的应用等等,更多阐明

  • 全栈零碎
  • 栏目首页由 node.js 做服务端渲染 (SSR),浏览器端复用后渲染 (CSR & SPA)
  • 栏目项是多页利用 (MPA) 切换页面;菜单项是单页利用 (SPA) 切换路由
  • 自定义同构办法,Fether/requireMarkdown 等,Fetcher 前端 axios 构建,node 端 got 构建
  • 仿小程序的前端路由,构建时能够依据路由切割代码,按需加载 js 文件,反对 SSR
  • 仿小程序生命周期,让 page 代码、component 代码有更清晰的性能划分
  • template less,尽可能的少写模板,将模板逻辑交由 JS 实现(aotoo 库的外围性能)
  • 反对 markdown
  • 反对 SEO,外部主动解决在浏览器端复用服务端渲染的 html 和数据,无缝过渡
  • 多场景化,测试,生产一应俱全
  • aotoo 库构建(react 的封装库,react 组件 jquery 化)(阐明)

目录构造

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 
             ...
             ...

阐明

aotoo.config.js

我的项目配置文件,蕴含我的项目版本,我的项目类型,我的项目源码目录等各种配置

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',
      ...
    }
  ],
}

configs 目录

该目录寄存环境配置,编译器会依据命令行所给出的环境参数生成相干的配置,比方测试环境(test=>test.js)

aotoo dev --config test

dist 目录

该目录寄存前端编译文件,蕴含版本目录,开发目录,生产目录

├─ 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 源码

├─ 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.jscommon.js,须要留神的是,vendors 是一套独立的 webpack 打包过程,与业务 JS 打包不在一个过程,将生成 dist/.../vendors.js 文件,common.js来自业务 JS 的拆散代码 (webpack 的 split)。其中vendors.js 文件不反对热更新

业务打包
业务打包以 JS 文件作为 webpack 的 entry,通过 loader 模块同时生成其相干动态资源,如上例的 shop 目录

js/vendors 目录

该目录寄存通用代码或者框架库,比方在 vendors/index.js 中引入 react 或者 vue,须要留神,该目录的内容会被利用到node 端(如果启用了 server 服务),所以肯定要留神两端的兼容性写法

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 的命令行开发工具库,装置、编译都须要通过此工具来操作更多阐明

零碎环境

  • mac osx
  • linux
  • 不反对windows,但 win10 的 linux 子系统能够
  • node >= 12

INSTALL

npm install -g aotoo-cli
aotoo -V # 查看是否装置胜利

USAGE

装置一个新的 hub 空间

init <dir>

# 新建 xxx 我的项目
$ aotoo init xxx

新建 web 类我的项目

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

启动 VUE 我的项目

$ aotoo dev vueSample

启动 REACT 我的项目

$ aotoo dev reactSample

启动小程序我的项目

编译实现后须要应用小程序开发工具关上终端黄色字体批示的目录

$ aotoo dev xcxSample

工作模式

dev [name]

开发模式编译,并启动服务,前端反对热更新

# 启动 aotoo.config 中 apps 中的启动我的项目
$ aotoo dev

# 启动指定我的项目
$ aotoo dev project_name

dev-clean [name]

开发模式编译,革除 common/vendors 等 dll 文件,从新生成,并启动服务

$ aotoo dev-clean

# 启动指定我的项目,并革除该我的项目 common 的缓存
$ aotoo dev-clean project_name

dev-build [name]

开发模式编译,革除 common/vendors 等 dll 文件,从新生成,不启动服务

$ aotoo dev-build

# 编译指定我的项目
$ aotoo dev-build project_name

生产模式

build [name]

生产模式,纯编译输入,不启动服务

$ aotoo build

# 编译指定我的项目
$ aotoo build project_name

build-clean [name]

生产模式,革除 common/vendors 等 dll 文件,并从新生成,不启动服务

$ aotoo build-clean

# 编译指定我的项目
$ aotoo build-clean project_name

部署

部署之前,须要先以生产模式编译

aotoo build-clean project_name

start [name]

生产模式,启动 node 服务

$ aotoo start

# 编译指定我的项目
$ aotoo start project_name

node 启动

# 编译我的项目,生产模式
$ node index.js

# 启动测试环境
$ node index.js --config test

# 进入源码 server 目录启动  
$ cd src/project_name/server
$ node index.js

pm2 启动

# 编译我的项目,生产模式
$ aotoo build-clean project_name

# 启动测试环境
$ pm2 start index.js -- --config test

EXTEND PARAM 扩大参数

--config <name>

指定环境配置文件,配合 node 端一起应用

# 开发模式,启动测试环境
aotoo dev --config test

# 生产模式,启动测试环境  
aotoo build --config test

--name <name>

启动指定我的项目,该参数可多我的项目同时启动

# 同时启动 xxx 及 yyy 的我的项目
$ aotoo dev --name vueDemo --name reactDemo

GITHUB
更多阐明

退出移动版