normae
normae是基于fis3的拉勾网前端解决方案
- 后端为Java+Velocity
- 采用less作为css处理器
- 采用amd模块化开发方案
- 采用bower管理第三方依赖
阅读本文档前,建议先阅读fis3的文档,很多涉及到fis3的内容都没有提及,请查看相应的文档。
目录规范
site //能独立提供服务,具有单独二级域名的产品线
├ common //通用子系统
| ├ components //组件,业务逻辑无关
| | ├ popoup
| | | | ├ popoup.js
| | | | └ popoup.less
| ├ static //非组件模块资源目录,包括模板页面引用的静态资源(favicon.ico)
| ├ widgets //模块,业务逻辑相关
| | ├ header
| | | | ├ header.html
| | | | ├ header.js
| | | | └ header.less
├ dep //第三方依赖
| ├ jquery
| | └ jquery.js
| ├ esl
| | └ esl.js
├ test //测试数据
| ├ common //所有模版共用的模拟数据,主要放置velocity tool相关的方法
| | └ common.js
| ├ ajax //模拟ajax请求返回的数据
| | └ test.json
├ sub //子系统,具有较清晰业务逻辑关系的功能业务集合
| ├ page //具有独立URL的输出内容
| | ├ index
| | | | ├ index.html //velocity模版
| | | | ├ index.html.js //页面对应的mock数据
| | | | ├ index.less
| | | | └ index.js
| ├ static
| ├ modules
| | ├ content
| | | | ├ img
| | | | ├ tpl //放置模块的前端模版
| | | | | └ content.tpl
| | | | ├ content.html
| | | | ├ content.js
| | | | └ content.less
| ├ fis-conf.js //子系统的fis配置文件
| ├ server-conf.js //子系统的url模拟转发配置文件
├ .bowerrc //bower配置文件
├ bower.json //bower package文件
├ fis-conf.js //fis配置文件
├ server.conf //本地url模拟转发配置文件
使用
本地安装normae
$ npm install normae
全局安装bower
$ npm install bower -g
normae内置了3种release模式
-
默认的dev模式,用于本地调试,会编译velocity,模拟转发url。
$ normae release -
qa模式,用于测试环境测试,会添加md5戳,打包,合成精灵图。
$ normae release qa -
prod模式,用于生产环境上线,会添加md5戳,打包,合成精灵图,压缩。
$ normae release prod
具体配置请参考这里。
normae的三种release方式只提供了一些基本的匹配处理规则,如果想添加适合本项目的特殊规则,如具体的打包规则等,请在项目根目录下的fis-conf.js文件中添加规则来扩展或覆盖基本的规则。
按子系统release
随着子系统的增加,给我们的日常开发带来了以下两个问题
- 整个系统releae,时间越来越长,自动刷新功能总是延迟很多
fis-conf.js
,server.conf
配置文件内容越来越多,变得难以维护
因此,normae在v0.1.0将release的粒度改到子系统的层级,相应地需要在子系统目录下添加fis-conf.js以及server.conf来配置release规则和url转发规则,而根目录下的fis-conf.js以及server.conf则放置一些common的配置。通过修改根目录下的fis-conf.js文件中的releaseMods变量,来release所有子系统或者指定的子系统:
var releaseMods = 'dashboard' ;// var releaseMods = 'all';var root = fisproject;var confs = fisutil;var path = ;var mods = ;confs;mods;
需要注意以下几点:
- 如果修改了子系统间共同依赖的资源,请release所有的子系统
- 通过
-wL
参数开启监听改动自动刷新功能后,即使修改了子系统下的fis-conf.js文件,也不会被监听到,请重新输入normae release -wL
release
本地调试
$ normae server start
其他命令以及参数请参考fis相关文档。
-
#### 模拟转发url
normae使用fis内置server默认的node server,同时开启模拟转发url功能,需要在项目根目录添加server.conf文件。
文件内容参考如下:rewrite ^\/$ /template/sub/page/index/index.htmlrewrite /test.json /test/ajax/test.json配置文件说明:
- 配置文件每一行为一条规则。
- 规则格式为:匹配类型 (空格) 匹配url正则或url (空格) 命中后的目的文件url。
- 匹配类型包括rewrite和redirect。
- rewrite:匹配规则后转发到一个文件,同时url修改为访问文件的url。
- redirect:匹配规则后重定向到另一个url。
-
#### 编译velocity模版
借助fis-postprocessor-velocity插件,实现在开发阶段编译velocity模版。如果page文件夹下存在独立页面的velocity模版index.html,则需要在同级目录添加mock数据文件index.html.js。
index.html
$!{foo}$math.floor(2.5)index.html.js
moduleexports =foo: "bar"math:{return Math;}另外可以添加/test/common/common.js文件,用来放置一些如模拟velocity tool的方法, 作为所有velocity模版的公共mock数据文件,在编译velocity模版时,会将该文件中的mock数据合并到模版对应的mock数据中。
开发
引入html
我们并没有使用velocity模板自带的#parse语法,因为这种引入模板片段的方法只有在用户访问页面时,服务器才会将模板片段合并成一个完整的文件并编译输出,但是我们采用的是纯前端的解决方案,并没有扩展velocity模板的语法,是无法处理这种运行时的问题的,比如模板片段中引用资源的路径问题,以及无法将模板对css,js文件的引用链接最后统一放置在完整页面的合适位置,因此我们转而将合并模板片段的时间提前到发布期,借助fis的内容嵌入能力,实现了模板片段的开发分离,发布合并,事实上最后放到服务器上的是包括所有模板片段的完整的velocity模版页面。
js加载方式
normae采用的是amd的模块化开发方案,amd中require([])为异步加载的用法,而且作为加载入口文件时也只能使用这种用法,但是目前出于打包等方面的考虑,最后发布时的js加载方案使用的是把js放在body底部的同步加载方案,主要是通过设置fis-hook-amd插件的globalAsyncAsSync属性为true实现的,这样异步加载的js模块都会默认改为同步加载,那如果确实需要异步加载一个js模块怎么办,很简单:
// fis async
加了这段注释的异步用法就是真正的异步用法了。
引入模块
normae采用的是纯前端的解决方案,所以并没有对velocity模版进行扩展,因此不能直接引入独立的组件模块。以下面的目录为例:
.
├── modules
│ └── sidebar
│ ├── main.html
│ ├── main.js
│ └── main.less
└── page
└── index
├── main.html
├── main.js
└── main.less
过去的引入方式
index/main.html
index/main.js
;
index/main.less
/*** @require "../../modules/sidebar/main.less"**/
这种模块组件引入方式延续了拉勾过去的前端集成开发方案idt的模式,为页面分别提供一个入口js文件和入口css文件,再在其中分别引入模块组件的js和css文件,但是这种模式将模块组件割裂开来,引入和删除都很不方便。
推荐的引入方式
因此我们决定改为将js文件/css文件的依赖关系定义到html文件中,引入模块直接引入html文件即可(如果只有js文件/css文件,那么将css的依赖关系定义到js文件里,只需要引入js文件)。
index/main.html
sidebar/main.html
<!--@require "main.less"-->Sidebar
前端模版使用
拉勾之前的前端解决方案idt中,前端模版会通过html2js这样的node组件编译成js文件,再通过amd loader加载进来,在fis中提供了一种更简单的方式,将前端模版内容直接插入到js文件中,具体是通过fis内容嵌入能力实现的:
var template = ;var tpl = ;var html = templatefeatures: resultfeatures;;
__inline为编译期函数,在编译期间会把前端模版内容直接替换掉它。
ignore html代码
可以通过在html中添加注释来使部分html代码在指定的release模式下才能release,其他模式将被忽略。
source code
all release<!-- fis-dev-start -->dev release<!-- fis-dev-end --><!-- fis-qa|prod-start -->qa release or prod release<!-- fis-qa|prod-end -->
release code
-
normae release
all release<!-- fis-dev-start -->dev release<!-- fis-dev-end --> -
normae release qa
ornormae release prod
all release<!-- fis-qa|prod-start -->qa release or prod release<!-- fis-qa|prod-end -->
不支持嵌套,开始和结束注释标签中的release模式必须一致,支持多个release模式,用' | '连接。
打包方式
在qa和prod的release模式中,自带了allInOne的打包方式,就是页面的所有css文件打包成一个文件,所有js文件打包成一个文件,就像之前说的并不建议这种粗暴的打包方式,其实我们可以自己配置打包的方式,其他的零散资源再使用allInOne的方式打包成一个文件。
打包可以参考如下的方式,数组中资源路径的顺序决定了最后在打包文件中资源的顺序。
fismedia'qa';
不再使用如下的packTo的配置打包方式
fismedia'qa';
原因是无法控制各文件在打包后文件中的顺序,而且两者不能混用。