Athena
O2前端流程工具
Install / Use
/learn @o2team/AthenaREADME
athena-html
<img src="athena.jpg" width="240">O2Team构建项目流程工具,可以生成相应目录和代码,同时对项目进行编译
一次安装,到处运行
功能一览
创建项目
- [x] 生成项目、模块、页面、组件文件结构
编译预览
- [x] 轻量组件化功能
- [x] 根据组件加载情况生成资源依赖表
- [x] 页面、组件html编译
- [x] Sass/less 编译
- [x] CSS合并压缩
- [x] CSS prefix,px转rem
- [x] JS合并压缩
- [x] 自动生成雪碧图,自动多倍图
- [x] 文件内联,自定义图片转base64
- [x] 图片压缩
- [x] 字体压缩
- [x] 文件MD5戳
- [x] 本地预览
项目部署
- [x] 资源定位(图片等资源路径替换)
- [x] 生成CSS页面片
- [x] 部署到预览机和开发机
ChangeLog
加入开发
请见开发指引
安装
基于node,请确保已具备较新的node环境(>=4.0.0),推荐使用node版本管理工具nvm,这样不仅可以很方便地切换node版本,而且全局安装时候也不用加sudo了。
安装本项目 athena-html
$ [sudo] npm install -g athena-html
由于国外源实在太慢,建议使用国内源来安装
$ [sudo] npm i -g athena-html --registry=http://registry.npm.taobao.org --disturl=http://npm.taobao.org/mirrors/node
目前已支持sass/less文件的编译,使用sass需要使用ruby安装compass
$ [sudo] gem install compass
由于墙的缘故(你懂的),原始的gem源https://rubygems.org/ 几乎无法使用,建议将gem源替换成 ruby-china 的源
$ gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
$ gem sources -l
*** CURRENT SOURCES ***
https://gems.ruby-china.org
# 请确保只有 gems.ruby-china.org
$ gem install compass
项目结构
一个项目对应一个目录,项目中可以包含多个 模块 ,项目将由以下结构组成
├── module1 - 模块1
├── module2 - 模块2
├── module3 - 模块3
└── app-conf.js - 项目的配置信息
项目中模块将由以下结构组成
├── dist - 通过编译生成的目录
│ ├── output - 真正用来上线的目录
│ ├── combofile - publish时用来存放生成页面和页面片文件的目录
│ ├── css - 通过编译生成的css文件
│ ├── js - 通过编译生成的js文件
│ ├── images - 通过编译压缩后的images文件
│ ├── page1.html - 通过编译生成的页面html
│ ├── map.json - 通过编译后生成页面/widget依赖关系已经页面引用资源、资源md5对应表
|
├── page - 所有页面目录
│ ├── page - 某一页面目录
│ ├── images - 页面的图片目录
| ├── page.json - 页面的说明文件
│ ├── page.css - 页面级css
│ ├── page.js - 页面级js
│ ├── page.html - 页面html
│
├── static - static目录一般用来存放需要引用的第三方的资源文件,需要配合``static-conf.js``来使用
│ ├── css - 额外的css文件
│ ├── js - 额外的js文件
│ ├── images - 额外的image文件
│
├── widget - 所有widget目录
│ ├── widget - 某一widget目录
│ ├── images - widget的图片目录
| ├── widget.json - widget的说明文件
│ ├── widget.css - widget的css
│ ├── widget.js - widget的js
│ ├── widget.html - widget的html
│
├── static-conf.js - 需要额外引用的静态资源的配置
│
└── module-conf.js - 模块的配置信息
在这种项目组织方式中,将页面拆分成各个widget组件,在页面中通过加载各个widget的方式来拼装页面,再经过编译,生成正常页面。
公共模块gb
在创建项目时,每个项目都会默认拥有一个公共模块 gb 。
普通模块只允许调用公共模块 gb 的公共的组件、css或js,而不允许调用其他普通模块的资源。
快速开始
基于命令 athena,同时提供了简写ath
初始化
首先需要初始化Athena,在这一步会有初始化工作目录、输入用户名等操作
$ ath init [工作目录]
生成新项目
生成一个新的项目目录
$ ath app [项目名称]
或者使用简写 ath a [项目名称],ath app -h可以看到该命令的使用方式
同时提供了通过携带参数快速创建项目的命令
$ ath a --name lo --description 测试 --sass --template 默认模板
参数 --name 指定项目名称
参数 --description 指定项目描述
参数 --sass 指定项目使用 sass
参数 --less 指定项目使用 less
参数 --template 指定项目使用的模板,输入模板名称,默认模板是 默认模板
每个参数都是可缺省的。
然后根据提示一步一步来,将会自动生成项目的结构和所需文件代码
新增模块
在某一项目中新增一个模块,比如在项目 wd 中新增一个 open 模块,需要在项目根目录下执行
$ ath module [模块名]
或者使用简写 ath m [模块名],ath module -h可以看到该命令的使用方式
[模块名]参数指定模块,可以包含多个模块,多模块间使用 , 进行分隔
举个栗子
// 以下命令将创建my和hello两个模块
ath m my,hello
同时提供了通过携带参数快速创建模块的命令
$ ath m --name hhh --description 测试 --sass
参数 --name 指定模块名称
参数 --description 指定模块描述
参数 --sass 指定模块使用 sass
参数 --less 指定模块使用 less
每个参数都是可缺省的。
然后根据提示一步一步来,将会自动生成项目的结构和所需文件代码
新增页面
在某一模块下新增一个页面,进入到该模块 下,执行
$ ath page [页面名]
或者使用简写 ath pa [页面名],ath page -h可以看到该命令的使用方式
同时提供了通过携带参数快速创建页面的命令
$ ath pa --name hello --description 测试 --sass --remote jd
参数 --name 指定页面名称
参数 --description 指定页面描述
参数 --sass 指定页面使用 sass
参数 --less 指定页面使用 less
参数 --remote 指定页面属于域,目前分别有 tencent 和 jd
每个参数都是可缺省的。
然后根据提示一步一步来,将会自动生成athena的页面目录和模板
新增widget
在某一模块下新增一个widget组件,进入到该模块 下,执行
$ ath widget [组件名]
或者使用简写 ath w [组件名],ath widget -h可以看到该命令的使用方式
同时提供了通过携带参数快速创建组件的命令
$ ath w --name topbar --sass --description 测试
参数 --name 指定组件名称
参数 --description 指定组件描述
参数 --sass 指定组件使用 sass
参数 --less 指定组件使用 less
参数 --cms 指定这是供CMS使用的楼层组件
每个参数都是可缺省的。
然后根据提示一步一步来,将会自动生成athena的widget目录和模板
删除命令
通过命令 athena delete 可以进行 项目、模块、页面、组件 的删除,请遵循以下场景使用
命令简写 ath del
场景一
在项目目录外,可以使用如下命令来进行删除
// 删除当前目录下项目
$ ath del -a [项目名]
// 删除当前目录下项目的某一模块
$ ath del -a [项目名] -m [模块名]
// 删除当前目录下项目的某一模块中的某一页面
$ ath del -a [项目名] -m [模块名] -p [页面名称]
// 删除当前目录下项目的某一模块中的某一组件
$ ath del -a [项目名] -m [模块名] -w [组件名称]
场景二
在项目目录下,可以使用如下命令来进行删除
// 删除当前项目的某一模块
$ ath del -m [模块名]
// 删除当前项目的某一模块中的某一页面
$ ath del -m [模块名] -p [页面名称]
// 删除当前项目的某一模块中的某一组件
$ ath del -m [模块名] -w [组件名称]
场景三
在模块目录下,可以使用如下命令来进行删除
// 删除当前模块的某一页面
$ ath del -p [页面名称]
// 删除当前模块的某一组件
$ ath del -m [模块名] -w [组件名称]
使用及编译
编译模式
过一段时间的探索演进,目前Athena有2种编译模式,分别是
- 在客户端进行代码合并的客户端完全处理client模式
- 在静态服务器进行代码合并的server模式
而这两种模式下又要区分是编译出上线前代码的build,还是进行开发时的实时预览serve,build和serve需要执行的编译任务是不一样的,所以其实认为有4种模式也并无不可。
两种模式下大家开发时的代码写法完全一样,唯一的区分是在项目的app-conf.js中进行配置,配置项为comboConf如下
module.exports = {
app: 'nima',
appId: '7024e980-8cd8-11e5-89fe-370bd1e969e9',
description: '尼玛',
common: 'gb',
moduleList: ['gb', 'hh', 'lp'],
platform: 'mobile',
versionControl: 'git',
comboConf: {
mode: 'server', // server/client
server: {
flag: '??', // server端合并时的分割标识,如某Url //static.360buyimg.com/nima??/gb/common_d6e4c134.css,/hh/jj_5e52390b.css,/hh/topbar_17c154d1.css,/hh/banner_2dc311a1.css,/hh/hello_1ed059f2.css
onlineDomain: '//static.360buyimg.com/', // 服务端合并的线上域名
shortPath: 'nima' // 次级目录
}
}
...
}
comboConf.mode为server则是server模式,client即是client模式。
模块化
通过阅读设计稿,我们可以将页面拆分成不同widget,而一些可以通用的widget我们可以放到一个公共模块中去统一管理,通过这样的页面组件化方式,我们可以很好地避开复制代码的问题,同时让我们的代码更好管理。
在执行athena page [pageName]命令生成页面后,可以发现在模块的page目录下多了一个以刚刚输入的页面名称pageName作为名字的目录,这个目录下面包含 html/js/css 三个文件。在html文件中一般通过加载各个widget的方式来进行开发,具体代码如下:
<%= widget.load('user') %>
<%=
widget.load('user', {
param: 'test'
})
%>
<%= widget.load('user', null, 'gb') %>
widget.load可以方法接收三个参数,第一个参数是widget的名称,后面两个参数是可选参数,第二个是向widget传递的一些参数,第三个是widget所属的模块,如果是本模块,可以不传。
在 widget 的目录下包含了一个该组件的json格式的说明文件,文件中的 data 字段可以用来定义组件所需接收的默认参数,在执行 widget.load 方法时 data 字段会作为参数的一部分,方法调用时传入的参数若和 data 有重叠,则会对 data 进行覆盖。
页面中API
widget.load
如前一小节所显示,用来加载组件
widget.loadFloor
widget.load 的变种,用来加载CMS解决方案中的楼层,参数与widget.load方法一致,默认加载 widget 目录中的 data.json 文件,但需要注意的是,目前这个方法只有在开启server模式才有效。
widget.loadFloorSmarty
widget.load 的变种,用来加载使用Smarty语法编写的楼层或元件,参数与widget.load方法一致,默认加载 widget 目录中的 custom_data.json 文件,但需要注意的是,目前这个方法只有在开启server模式才有效。
getCSS
使用方式 <%= getCSS() %>
用来输出页面所需引用的CSS Link,可传入3个参数,第一个参数是CSS 样式表的名称,第二个参数是模块名,第三个参数是是否加入页面片中(client模式)。如果什么都不传则默认输出与当前页面同名的样式表。例如:
当前模块hello中有一页面为mine.html,在页面<head>标签中调用<%= getCSS() %>将输出
<link rel="stylesheet" type="text/css" href="css/mine.css" combo-use="/hello/css/mine.min.css">
若第三个参数为 inline ,则该样式文件会以内联的形式写入页面片中(client模式)。
getJS
与上述getCSS相似,将输出页面所需引用的脚本文件,参数与getCSS保持一致。
当前模块hello中有一页面为mine.html,在页面<body>标签最后调用<%= getJS() %>将输出
<script src="js/mine.js" combo-use="/hello/css/mine.min.js"></script>
若第三个参数为 inline ,则该样式文件会以内联的形式写入页面片中(client模式)。
注意
- 这些API调用语句末尾不要加分号
app-conf.js
在项目的根目录下生成的文件中,app-conf.js 文件是一个通过传入配置项生成的关于本项目的配置文件,我们可以看到它包含如下配置:
'use strict';
module.exports = {
app: 'qwd', // 项目名称
appId: 'd562b930-be56-11e5-8027-b52041f428b5', // 项目ID
description: 'demo',
platform: 'pc', // 平台 pc or mobile
common: 'gb', // 公共模块
moduleList: ['gb', 'frs', 'test'], // 项目下模块列表,通过athena module命令生成模块时会自动往此处添加新模块名
tmpId: 'default', // 选用模板
versionControl: 'git', // 标记当前项目使用的版本控制工具,目前只有git,若设置了,则在发布时将经过代码是否已提交远程仓库的检测
shtml: { //页面片配置
use: true, //是否使用,总控制,若要开启使用页面片,这里必须为true
needCombo: true, // 页面片中链接是否合并
needTimestamp: true //增加时间戳
},
useInclude: { // 启用生成html页面片功能
folder: 'include', // 生成页面片目录名字
pathPrefix: 'include', //页面片路径前缀 include/header.html
files: { // 需要生成的页面片文件
'header.html': { // 文件名,文件对应的widget组件信息
module: 'gb',
widget: 'mod_hd'
}
}
},
comboConf: { // 文件合并模式,server模式为文件在服务器端合并,client即文件通过工具本地合并
mode: 'server', // server/client
server: {
flag: '??', // server端合并时的分割标识,如某Url //static.360buyimg.com/nima??/gb/common_d6e4c134.css,/hh/jj_5e52390b.css,/hh/topbar_17c154d1.css,/hh/banner_2dc311a1.css,/hh/hello_1ed059f2.css
onlineDomain: '//static.360buyimg.com/', // 服务端合并的线上域名
shortPath: 'nima' // 次级目录
