转载

网站架构-从无到有

注意:该文件比较长,写的是从没有项目起到项目上线的一些事,从大的方面约束规范到环境的配置、代码的模式、静态文件管理都有些概括,希望对你有帮助~

环境和域名

项目的开发基本是 开发->测试->线上 的流程,那么项目开发前,约定好环境和域名,首先我们已知如下条件:

  • 使用 git 版本控制,前、后端分2个仓库(repository),会有 master线上develop开发release发布 3大分支
  • 后端使用 php 语言, Yii2
  • 项目域名 fe.com
  • 项目静态域名 cdn-fe.com ,线上启用 CDN 服务
  • 分本地开发、联调测试、线上3个环境,每天环境都能独立的运行,当然前端fe可以不装数据库,但后端环境得有一套
  • 后端代码目录: /home/wwwroot/fe.com/
  • 前端代码目录: /home/wwwroot/cdn-fe.com/
  • 全是本地开发,fe本地有静态服务开发,rd本地有后端服务+数据库服务

代码目录只是个例子

本地环境

域名为: fe.mecdn-fe.me

前端fe维护 前端仓库 ,当前如果前端也要"套模板"的话,本地也得有一套后端服务,当前数据库可以连接测试环境的

本地环境主要是前端fe开发静态页面使用,为的是方便快速开发,在 develop 分支开发并每天下班前推送到联调环境,以供后端和团队其他小伙伴及时应用最新版本

联调、测试、发布环境

域名为: fe.devcdn-fe.dev

该环境大多数在内网,测试服务器具有前、后端独立环境,并且具有数据库,联调环境 fe.dev 迁出 develop 分支,并在每天开发者 push 的时候自动更新最新代码,后端开发静态资源连接该环境的代码 cdn-fe.dev

在每次上线前,把要上线的版本合并到 release 分支,并在测试服务器迁出 release 分支为 fe.releasecdn-fe.release 域名,让 qa 测试,测试通过后直接更新到线上

也就是说在这个测试服务器上具有4个站点:

  • fe.dev - 项目最新代码,用来开发功能
  • cdn-fe.dev - 静态项目最新代码,用来开发功能,主要是后端rd本地连接该资源
  • fe.release - 每次版本要上线的代码(其实也可以说是沙盒)
  • cdn-fe.release - 静态项目上线版本代码

这样的环境不冲突,不至于rd1和qa1在测试上线代码,而导致rd2的开发不正常,理论来说rd跟fe也一样,都是本地开发,只是rd连接的是测试环境(cdn-fe.dev)的静态文件,因为这个静态文件可以保证实时更新

线上

域名 fe.comcdn-fe.com ,当 release 版本测试通过,直接发布到线上

环境配置的问题

看着上面感觉乱乱的,其实都是配置文件,开发个 Yii2 模块,让配置为 用户配置 > 环境配置 > 默认配置 这样的规则去覆盖, 用户配置 可以用电脑主机名为 key 去设置,比如:

js// 后端环境/config/默认配置.php {     // 配置     "config": {         // 线上默认配置         "production": {             "数据库": "阿里云",             "域名": "fe.com",             "静态域名": "cdn-fe.com"         },          // 开发环境配置         "develop": {             "数据库": "内网测试机:dev",             "域名": "fe.dev",             "静态域名": "cdn-fe.dev"         },          // 发布/测试配置         "test/release": {             "数据库": "内网测试机:release",             "域名": "fe.release",             "静态域名": "cdn-fe.release"         }     },      // 当前环境     "env": "production" }

然后我fe本地的是:

js// 后端环境/config/fe1.php {     // 配置     "config": {         "develop": {             "数据库": "测试机:dev",             "域名": "fe.me",             "静态域名": "cdn-fe.me"         }     },     // 当前环境     "env": "develop" }

可见我本地有环境,但数据库我连接的是测试机的dev,而rd的本地可以是这样:

js// 后端环境/config/rd1.php {     // 配置     "config": {         "develop": {             "数据库": "本地",             "域名": "fe.rd",             "静态域名": "cdn-fe.dev"         }     },     // 当前环境     "env": "develop" }

整个配置的思路感谢 @阿旭、@消寒 大神的指导,非常好用

可见rd本地域名是自己、数据库是自己,因为这样很方便修改,而由于rd不改静态文件,那么又想保证链接最新的静态文件,那就连接测试机的dev吧,因为不管前端后端,只要往 develop 分支 push ,测试的 dev 版本就会自动更新。

当然配置式覆盖只是个思路,具体如何编写我想肯定难不倒你~

ps: 有次rd发现我个小问题,正好我也看到了,我顺手就改好了,然而rd刷新他的本地页面想稳定复现后找我来报bug,但发现我 push 后他那么好了,哈哈

多域名的好处

  1. 域名后缀使用语义化,比如 .me 就是本地、 .dev 就是测试机开发分支、 .release 就是要发布啊、 .com 就是线上
  2. 多个域名可以达到 cookie 不共享,避免线上出问题,本地想查却发现 cookie 共享了

规范

目录规范

前端仓库目录:

# 静态文件源码 ./src/     # 一些公用模块,包括js、css、和图片     ./common/         ./jquery.js         ./zepto.js         ./dialog/             ./dialog.js             ./alert.js             ./close.png         ./popup/             ./select.js             ./select.css             ./base.js             ./base.css          # 单独的公用样式         ./css/             ./reset.css             ./markdown.css          # 单独的公用图片         ./img/             ./loading-16.gif             ./loading-32.gif      # 其他的以业务/方向名命名,比如:user、home、login     ./{module}/         ./img/             ./login.png             ./user.png         ./page.js         ./page.css  # 编译后的目录,里面目录结构同src一致,方便2个版本之间的切换 dist/  # 模板文件 ./tpl/     # 公用的基础样式演示     ./commom/         # 弹出层演示         ./dialog/index.html      # 其他的以业务/方向名命名,比如:user、home、login     ./{module}/         ./index.html         ./login.html         ./xxoo.html  # 单元测试 ./test/

为什么模板文件单独存放,而不是跟 src/ 静态文件在一起呢?是因为模板文件最终会给后端rd并套到 php Yii2 框架里运行,前端只是本地开发方便而已

样式、交互规范

同ue、pm约定好基础样式、交互的规范,比如:

  • psd确认稿单位、比例、标注
  • 定义基础样式:栅格、颜色、间距、字号等
  • 定义组件:幻灯、Tab、筛选、手风琴、输入框、下拉框等
  • 数据加载:加载中、加载超时、加载出错、数据为空
  • 样式规范抽离成公用组件文档

前、后端联调规范

  1. 接口规范、数据规范 - 因为约定好这些前端就可以使用 mock 数据而不依赖后端开发,达到并行开发
    • 接口参数类型和值
    • 返回值结构和类型(强制类型)
    • 统一返回状态码
    • 接口路径(版本、语义化)
  2. 模板代码注释,比如告诉套模板的人如何使用页面上的元素状态(登录前用xx,使用后用xx)、如何循环列表
  3. 约定整个项目的公用模块,比如公用的 layout 、商家中心的 layout
  4. 文档

静态文件引用规范

本地开发时在 /tpl/*.html 里引用静态文件是:

<script src="/src/xxoo.js"></script> <link rel="stylesheet" type="text/css" href="/src/xxoo.css">

这样是可以快速开发,但由于前、后端不是一个项目目录,又不想每次修改个静态文件还需要上线 静态文件+后端文件 ,但不编译后端如何处理静态文件版本号呢?

点击这里查看静态文件版本号的处理

如果在后端项目里使用前端的一些编译语法,这样导致修改个静态文件后端就得编译,不然版本号对不上,当然你会说把后端的 View 层也放在前端项目里,做到前、后端模板分离,其实也可以,但模板里就会有些数据相关的问题,我们这里使用这样的方法处理静态文件:

  1. 后端扩展一个 php 的方法,启名为 STATIC_FILE ,后端模板(View层)里所有引用静态文件都使用该方法
  2. 前端在 release 的时候把代码编译并生成一个 md5 映射文件存放在 前端项目/static_map.php
  3. 模板里使用 <script src="<?php echo STATIC_FILE('common/login.js')?>"></script> ,文件路径基于 src/ 开始,因为这样可以很好的在 src dist 两个版本切换

再配置里添加个是否使用 md5 版本和使用 src 还是 dist 的参数,如:

js{     // 配置     "config": {         // 线上默认配置         "production": {             "static_model": "dist",             "static_md5": true         },          // 开发环境配置         "develop": {             "static_model": "src",             "static_md5": false         },          // 发布/测试配置         "test/release": {             "static_model": "dist",             "static_md5": true         }     } }

这样就是线上使用压缩版本 dist 并且开启 md5 功能,而开发环境既使用开发代码 src 也不开启 md5 功能,由于测试/发布环境就是沙盒所以必须跟线上一致。

前端生成的 static_map.php 大概长这样:

php<?php $STATIC_FILE_MD5 = array(     'common/login.js' => '123456',     'user/index.css' => '123456', );

STATIC_FILE 方法大概长这样:

php<?php # 假如 $CONFIG 就是配置变量,是由 【用户配置 > 项目配置 > 默认配置】 合并过来  /**  * 获取静态文件路径  *  * @param {string} $uri 文件uri,以静态项目里的src为起始目录  * @return {string}     文件的绝对路径  */ function STATIC_FILE ($uri) {     # 静态域名 + 静态模式(src,dist) + 路径     $url = $CONFIG['静态域名'] . '/' . $CONFIG['static_model'] . '/' . $uri;      # 如果没有开启md5则直接返回路径     if (isset($CONFIG['static_md5']) && $CONFIG['static_md5'] === false) {         return $url;     }      # 处理md5版本号     # 加载前端项目编译后的md5文件     include_once(前端项目 . '/static_map.php');     $version = '';      # 如果md5版本里有该文件     if (!empty($STATIC_FILE_MD5[$uri])) {         $version = '?' . $STATIC_FILE_MD5[$uri];     }      # 把版本号追加上返回,当前如果不存在md5也就忽略     return $url . $version; }

这里有个问题就是说, 前端项目/static_map.php 这个配置文件,他只能跟在前端项目仓库里,如果把她放在后端仓库也那也就成了 前端改静态文件也需要上后端项目 的问题。

这样比如前端要改个样式,只需要改好测好后编译下,把前端代码一上线即可,线上 影射 文件一更新就会生成新的 md5 文件路径,比如:

前端项目里开发静态页面 <script src="/src/xx.js"></script>  后端项目里 <script src="<?php echo STATIC_FILE('xxoo.js')?>"></script>

STATIC_FILE('xxoo.js') 会根据环境的配置生成不同的,比如:

测试环境关闭了md5并且引用开发代码src http://cdn-fe.dev/src/xxoo.js  上线开启了md5并引用压缩代码dist http://cdn-fe.com/dist/xxoo.js?qwerty  发布/测试环境同线上一致 http://cdn-fe.release/dist/xxoo.js?qwerty

你可能会说为啥不是 xxoo_qwerty.js 呢?我想说你随便啊,改这个不过就是改下编译脚本和 STATIC_FILE 方法而已~

前端项目

开发模式

前端使用 requirejs 开发,页面中始终加载一个入口文件,这个入口文件在 src 里只是个加载器和项目配置,而在 dist 环境就是一些公用某块打包合并之后的,这样可以减少请求,通常这个引用是在公用的 layout 里,比如:

html    <body>         这里是其他的block          <script src="<?php echo STATIC_FILE('common/main.js')?>"></script>          ...          <script>             require(['home/index', 'common/xxoo']);         </script>     </body> </html>

src/common/main.js 文件内容是:

js// requirejs代码 // ...  //requirejs配置 requirejs.config({     // 默认主路径是src/     baseUrl: '../',      // 其他的路径映射     paths: {},      //... });

dist/common/main.js 文件是这样:

js// requirejs代码 // requirejs配置代码  // jquery.js // util.js // ...

当然你可以有很多公用文件,比如频道的公用文件、某模块集合的配置文件,我们在开发时全使用异步加载,在发布、测试时前端使用脚本编译处理下,当然编译前/后的模块路径不换,也方便文件定位

项目配置

前端项目配置在 /package.json 里,大概如:

json{     "name": "前端项目",     "version": "1.0.0",     "description": "xx网前端项目",     "srcipts": {         "server": "http-server -p 8080",         "start": "npm run server",         "test": "mocha --reporter spec --timeout 5000 --recursive test/",         "test-cov": "istanbul cover _mocha -- -t 5000 --recursive  -R spec test/",         "fecs": "fecs check src/ test/",         "release": "",         "watch": "",         "debug": ""     },     "devDependencies": {         "http-server": "*",         "mocha": "*",         "istanbul": "*",         "fecs": "*"     } }

说下几个命名:

  • npm run server, npm run start, npm start - 本地开启 web server 功能,用来开发静态页
  • npm run test - 使用 mocha 运行单元测试
  • npm run test-cov - 使用 istanbul 运行测试覆盖率
  • npm run fecs - 使用 fecs 检查代码规范
  • npm run release - 编译发布代码,把 src/ 文件编译、混淆、压缩、合并到 dist/ 目录里,把 dist/ 目录里的所有文件生成 md5 并生成 static_map.php
  • npm run watch - 本地监听静态文件修改并实时刷新浏览器
  • npm run debug - 本地开启 web server ,配置 host 修改把线上域名 cdn-fe.com 域名到本地环境,并可配置 dist->src 或者 src->dist 的映射,方便调试线上代码

至于 watchdebugrelease 这些脚本,我想你可以根据你的项目写出来,但不使用全局的包,目前 webpackgulp 都支持非全局使用

开发流程

这里的开发流程只是说前端的一些流程工作,不包括诸如跟pm对需求这些

制作静态页面

develop分支:根据psd确认稿开发成本地的 .html 文件,可以使用 npm run * 的一些命令更好的本地开发,必须在文件内写好相关注释,开发完成(自测通过)后可在测试静态环境(cdn-fe.dev)让ue、pm确认效果,当然这里也只能确认下效果,逻辑还得出整个测试环境才可以测,在这里确认效果方便fe修改,不然套完模板告诉你有问题你就哭吧

套模板

develop分支:把静态项目里的 .html 文件代码片段根据注释编写出后端 View 层代码,并写相关的逻辑处理,某些功能告一段落后可以让联调

发布版本

在准备上线时把前端代码编译处理,再把开发分支代码合并入 release 分支,推送到测试机,让qa测试该版本的 release 代码,通过后给该版本打上标签,并合并入 masterdevelop

上线

线上永远是 master ,只要合并入 master 分支表示代码没有问题,上线可使用 线上机器 拉分支,或者 .tar 包上线,当然这些看你如何处理了,线上只要一更新到 master 代码,就表示项目上线

修复线上问题

前端项目上如果发现线上问题,可在本地把 master 迁出一个 fix-* 分支,可以使用 npm run debug 命令把线上压缩代码重写到本地开发代码以方便调试,代码没问题后,合并 release ,并测试,通过后合并到 master 上线并打上标签,并合并到 develop

整个架构的特点

优点

  1. 本地开发,开发代码不依赖于编译才能查看
  2. 合理的使用 npm run 功能,杜绝使用全局包(开发只需要克隆仓库和 npm install 安装依赖即可
  3. url规则重写方便调试线上问题
  4. 静态文件自动 md5 ,而不用担心上线需要编译后端模板
  5. 多环境配置不冲突,如果你们是 session 单点服务器,可以相应的调整下配置的方案

缺点

  1. 线上后端机器也需要迁出一份前端代码,因为需要前端的文件 md5 映射

总结

你会不会说为啥感觉这么多额,其实当你整个走下来也没什么,至于说不用 requirejs 而用 commonjs 或者 es6 啥的,亦或者说用 fis3 ,使用 react 不使用 smarty 之类我认为大的流程上都是大同小异,开发模式很多,好的不一定适合自己项目~

当然可能考虑的还不够多,欢迎吐槽~

原文  https://xuexb.com/html/wang-zhan-jia-gou-cong-wu-dao-you.html
正文到此结束
Loading...