fisp + yii1 的项目配置
最近我转组到一个之前没有前端的一个项目组,然后由偏后端的rd来开发全端。 弊病是:
-
样式乱七八糟
-
js效率低下
-
开发代码即为发布代码
1)为了压缩代码,他们是每次写完前端代码手动去掉换行和空格符。浪费劳动力加前端代码无法code review和版本管理。
2)css和js和view相关代码分别放至于不同的路径。相关的js、css和html没有放置在一起,开发时成本加高,组件化难度大。
既然作为这个组唯一的前端,我毅然决然决定必须重构,而因为我们组用的是php框架yii1。而fisp(百度基于PHP的前端工程化构建工具解决方案)只要为yii1增加smarty的扩展(接入方法见附录2),就可以简单切入了。而且fisp的好处如下:
1. 前后端分离,前端开发和发布分离
2. 组件化,增高代码复用性,并且结构清晰,也易于理解、学习和使用
fisp项目的文件结构:
-
fis-conf.js: 项目配置文件
- 开发和部署都相关: 合并压缩优化相关配置
- 开发相关:配置receiver.php路径和相应的项目文件在测试机上的存储位置
- 部署相关操作用: fisp本地发布和copy操作(可放入脚本)
- page:页面文件
- 标签
- html主要tag:html head body
- 自定义块: block
- 引入css和js文件的标签 require 发布后会吧css在head中引入,js在底部引入,而css与css之间,js和js之间的顺序保持不变
- 内嵌js代码标签 script
- 组件引入文件 widget
- 一般引入文件的定义为:
name="{namespace}:域名下的开发路径"
- 只用专注于开发路径,发布路径由fis-conf配置,会生map文件对应相应name的发布路径和它所依赖的模块
- layout.tpl 整体布局文件,定义好每个页面的相同处,比如引入公用样式,公用js
- 标签
- widget:组件文件
- static:静态资源
- server.conf: 用于本地测试时路径配置
-
test: 测试数据的php文件,根据page中的页面区分
3. 自动化,代码压缩、合并,图片压缩、雪碧图,发布预览自动化
通过fisp release指令可以轻松完成部署
部署主要分为本地部署和远程部署,由-d或者–dest配置:
1) 如果-d是一个目录,则会发布到相应的目录,例如:
fisp release -d ../output // 发布到你执行这条指令的位置的兄弟目录output中
2) 如果-d是你在fisp-conf.js里配置的deploy,则会发步到相应机器,至于如何配置见下文fis-conf.js代码和相关备注
注意远程发布的机器上要部署reciever.php,代码示例 为了安全,以上部署方式最好只用于安全域内的开发机使用,至于线上服务器的发布,我们建议用本地发布,然后cp指令将发布目录中的config,template和static目录复制到相应位置,举例:
#!/bin/sh
root_dir='XXX' #项目根目录
cd $root_dir/FEproject #前端项目目录
svn up
fisp release -omp -r ./common -d ./output
cp -rf ./output/config/* ../protected/config/
cp -rf ./output/template/* ../protected/views/
cp -rf ./output/XXX/* ..
rm -rf output
指令 | 说明 |
---|---|
-r | fisp项目(拥有fis-conf.js的目录) |
-d | --dest | 指定目录或者是你配置的远程发布 |
-c | 清理缓存 |
-o | 优化 |
-p | --pack | 打包 |
-m | --md5 | md5后缀 |
-w | --watch | 持续监视文件修改,除了fis-conf.js的修改其他前端修改会实时重新发布 |
附录1 fis-conf.js例子(我的修改:自定义static资源放置目录;远程发布deploy配置简化)
// 此处为了方便多个用户添加发布配置而做的修改
var webroot = {
fangsimin: {
"receiver": 'http://XXX/receiver.php', // 你的机器部署的reciever.php的url
"root": "", // 你的项目的根目录
"static_url": '/dev/assets/' // 修改静态资源发布路径的源目录
},
// 每个新机器只需添加一个类似前面fangsimin那样的配置
};
var RELEASE_MACHINE_CONFIG = (function() {
var ret = {};
for (i in webroot) {
ret[i] = {
// 你的机器部署的reciever.php的url
receiver: webroot[i]['receiver'],
// 相关配置发布路径
smarty_plugin: webroot[i]['root']+'protected/extensions/smarty/plugins',
smarty_config: webroot[i]['root']+'protected/config/',
template_dir: webroot[i]['root']+'protected/views/',
static_dir: webroot[i]['root']+'assets/',
}
};
return ret;
})();
// 此处为了配置fis.config中的static配置时使用,拿到的是 fisp release指令的-d的参数
var target = fis.cli.commander.args[0].dest;
//禁止模板xss优化
fis.config.set('modules.optimizer.tpl', '');
fis.config.set('modules.prepackager', fis.config.get('modules.prepackager') + ', widget-inline');
fis.config.merge({
namespace: 'common',
// 此处配置的是html,css和js中的相应静态资源的路径替换
statics: webroot[target]?webroot[target]['static_url']:'/dev/assets/',
settings: {
spriter: {
csssprites: {
margin: 10
}
},
prepackager: {
'widget-inline': {
include: /.*/i,
exclude: /(widget_a|widget_b|widget_c|widget_d)/
}
}
},
// 合成雪碧图
modules: {
spriter: 'csssprites',
},
// 打包配置
pack: {
// 所有页面公用模块
'/pkg/common.js': [
'/static/common/mod.js',
'/static/common/jquery.js',
'/static/common/jquery.cookie.js',
'/static/common/util.js',
'/static/common/template-native-debug.js',
'/static/common/bootstrap/js/bootstrap.js',
'/static/common/template-native-debug.js',
'/widget/popup/popup.js'
],
'/pkg/common.css': [
'/static/common/font-awesome/css/font-awesome.min.css',
'/static/common/bootstrap/css/bootstrap.css',
'/static/common/font-awesome/css/font-awesome.min.css',
'/static/common/common.css',
'/widget/popup/popup.less'
],
...
},
// 部署配置,此处外包函数执行循环方便我们通过前面设置的变量webroot来配置多个用户的发布配置
// 其实最后deploy就是一个object,其中key为你之后用fisp release的-d参数,value为相应的相应的发布对应地址。
// 具体可以参见fisp官网的deploy配置的例子
deploy: (function() {
var ret = {};
for (i in webroot) {
ret[i] = [
{
receiver: RELEASE_MACHINE_CONFIG[i].receiver,
from: '/plugin',
subOnly: true,
to: RELEASE_MACHINE_CONFIG[i].smarty_plugin,
},
{
receiver: RELEASE_MACHINE_CONFIG[i].receiver,
from: '/config',
subOnly: true,
to: RELEASE_MACHINE_CONFIG[i].smarty_config,
},
{
receiver: RELEASE_MACHINE_CONFIG[i].receiver,
from: '/template',
subOnly: true,
to: RELEASE_MACHINE_CONFIG[i].template_dir,
},
{
receiver: RELEASE_MACHINE_CONFIG[i].receiver,
// 此处不同于常规配置,是因为我们的项目定义的静态资源路径与fisp原来的'/static'目录
// 为了静态资源路径替换的正常而修改的配置
from: webroot[i]['static_url'],
subOnly: true,
to: RELEASE_MACHINE_CONFIG[i].static_dir,
}];
};
return ret;
})()
});
附录2 yii1加入smarty扩展
- 去smarty官网下载smarty
- 将下载包解压复制其中的lib到protected/extensions/smarty
- 在protected/extensions/smarty创建CSmarty.php
<?php
/**
* 扩展增加smarty模板
*
* @author Hema
* @link http://www.ttall.net/
* @copyright Copyright © 2012-2015 ttall.net
* @license http://www.ttall.net/license/
*/
Yii::import("application.extensions.*");
require_once (Yii::getPathOfAlias('application.extensions.smarty') . DIRECTORY_SEPARATOR . 'Smarty.class.php');
// 配置模板目录和配置目录
define('SMARTY_VIEW_DIR', Yii::getPathOfAlias('application.views'));
define('SMARTY_CONFIG_DIR', Yii::getPathOfAlias('application.config'));
class CSmarty extends Smarty {
const DIR_SEP = DIRECTORY_SEPARATOR;
function __construct() {
parent::__construct();
$this -> template_dir = SMARTY_VIEW_DIR;
$this -> compile_dir = SMARTY_VIEW_DIR . self::DIR_SEP . 'template_c';
$this -> caching = false;
$this -> cache_dir = SMARTY_VIEW_DIR . self::DIR_SEP . 'cache';
$this -> config_dir = SMARTY_CONFIG_DIR;
$this -> cache_lifetime = 0;
$this -> error_reporting = E_ALL & ~E_NOTICE; // smarty会报一些无关紧要的warning,故屏蔽掉
}
function init() {
}
}
然后在配置文件main.php中配置CSmarty