写在前面

最开始只是在做活动页面时苦于效率太低制定了这样一个自动化的工作环境, 所以Github上项目名是Rapid-Dev-Activity-Page(快速开发活动页...).

活动页这类比较简单的页面有几个特点:

  • 一刀切图, 图片自然需要压缩
  • 资源(js, css)较少, 可以直接内联到模板或者直接合并压缩成一个文件.
  • 大多都是服务端直接吐数据, 前端编写模板, 服务端渲染输出.
  • 前端强依赖后端的数据和环境.
  • 开发测试时间短, 快速开发.

其实时间短对于活动页来说并不是问题, 对于这样的页面, 一刀切, 静态页面分分钟写好, 可以写好后如何调试呢. 比如我们需要根据用户手机号的运营商来输出不同的内容, 这时候难道要不停的改变HTML结构来判断输出么. 直接写成Freemarker模板, 可是我们又没有后端提供的数据和环境, 只能干等..这时候如果有这样的一套环境:

  • 根据mock数据和我们编写的模板输出html文件.
  • 开启静态服务器调试
  • 大图的压缩
  • 当测试设备过多时, 在文件改动时能够自动刷新以方便查看页面.

这样, 我们就可以不必依赖后端的环境和数据, 在约定接口后各自开发, 直到联调. 除非有接口变动, 基本不会出错. bug率大大降低. 可以腾出更多的时间和大家交(shui)流(qun)技(dou)术(meizi).

总有些工具可以帮我们完成这些工具, 由于我厂广泛使用Freemarker模板, 我们在前端使用FMPP来进行模板的处理, 其他的开启服务器, 资源优化等都交给Gulp.

简单介绍FMPP

FMPP - FreeMarker-based file PreProcessor, 基于Freemarker的文件预处理器, 就像我们用的CSS预处理器一样. 通过他拜托后端环境的束缚. 总的来说: HTML = FTL + DATA. FMPP就是通过数据和模板生成html文件, 和后端渲染输出是一个道理.

使用也很简单(如果不考虑那一堆的配置项)

  • 准备的你的模板文件
  • 准备配置文件config.fmpp, 虽然可以命令行带参数, 但谁也不想那么费劲.
sourceRoot: src                 // ftl目录
sources: index.ftl              // 需要编译为html的文件, 如果没有此项配置, 那么sourceRoot下的所有ftl都将被编译
outputRoot: dist                // 输出目录
logFile: log.fmpp               // 日志打印目录, 可查看出错信息
modes: [execute(*.ftl)]         // 对sourceRoot下的ftl文件进行操作
replaceExtensions:[ftl,html]    // 编译后后缀改为html
data:tdd(../mock/index.tdd)     // 数据文件, 路径相对于sourceRoot
  • 准备数据文件 也就是配置文件中最后一项data, 我们看到上文中数据以tdd包裹, 这应该是FMPP自己的一种格式, 当然也可以使用json, 就是类似这样:  data: { user: json(../mock/index.json') } . 两者类似但又有点不同. 比如两者同样是下面的数据:
{
  "id": 1
}

如果是tdd的, id可以直接在模板中用${id}中获得, 但是如果json格式, fmpp会报错, 提示hash没有key, 所以就需要像 data: { user: json(../mock/index.json') } 使用, 在页面中${user.id}使用, 在activity和normal两个demo里可以看到不同的数据格式.

更多配置参考官网: http://fmpp.sourceforge.net/manual.html

这样, 命令行下运行fmpp命令即可, 为了能够在文件每次改变时自动执行fmpp, 我们可以使用Gulp结合Nodejs的child_process模块.

// 自动进行fmpp

var exec = require('child_process').exec;
gulp.task('fmpp', function() {
    exec('fmpp', function(err, stdout, stderr) {
        if(stdout) console.log(stdout);
        if(stderr) console.log(stderr);
        if(err) console.log('exec error: ', err);
    })
})
gulp.task('watchFmpp', function() {
    gulp.watch(PathConfig.fmppSrc, ['fmpp']);
})

其余的统统交给Gulp

基于编程的Gulp风头已经远远超过了基于配置的Grunt, 我已经根据一些场景写好了一些配置. Github地址: Rapid-Dev-Activity-Page. 你可以直接使用.

项目目录说明

  • activity, 为极简的活动页定制, 编译FTL, 资源内联, 开启静态服务器, 自动刷新等等. 示例在acticity_demo下.
  • normal, 对于资源稍微多一些的页面可能资源缓存更合理, 不再内联, 而是合并压缩更改引用. 示例在normal_demo下. 如果你的页面使用了模块化, 这个方案就不再适用, 推荐第三种.
  • server, 抽取了其中的FTL编译, 静态服务器, MCSS编译为CSS, 自动刷新的部分, 对于资源的打包工作交给你所使用的模块工具.(nej-build, r.js, webpack或者查看他们对Gulp的支持等等...

How I Use

  • 根据自己的项目页面, 选择activity, normal或者server, 将文件夹下的 package.json ,  gulpfile.js 以及 config.fmpp , 根据自己的项目做修改.

比如gulpfile.js下, 你需要修改的是各个task对应的目录.

var PathConfig = {
  ftlSrc: './src/index.ftl',  // Freemarker模板
  inlineDist: './template/',  // 内联js, css后生成的模板的所在目录
  imageSrc: './img/',         // 图片目录
  livereloadSrc: ['./js/index.js', './css/index.css', './dist/index.html'], // 自动刷新监听文件/目录
  liveInlineSrc: ['./src/index.ftl', './js/*.js', './css/*css'],    // 自动内联监听文件/目录
  fmppSrc: ['./src/index.ftl', './mock/index.json'],                 // 自动执行fmpp监听文件/目录
  lintSrc: './js/*.js'        // jshint检查文件目录
}

这里有一些建议, 以为gulp是资瓷通配符的, 所以强烈建议统一功能或页面的模板或者资源有自己的文件夹, 然后配置里都用通配符识别即可, 比如 ftlSrc: './src/*.ftl' , 同时, 对于activity和normal中, 因为最后template中的模板是经过资源内联或者引用替换的, 强烈建议建立一个类似src的目录开发. 而server下则不用关心.

  • 根据约定的接口准备mock数据即可
  • 命令行下gulp或者gulp+task运行即可.

注: 因为MCSS在我厂广泛使用, 如果你厂使用Less或者Sass, 切记修改Gulp的配置.

写在后面

本项目主要对活动页这类比较简单的页面进行了轻量级的前后分离和构建, 由于gulp的方便性, 你也可以扩展自己需要的功能, 比如执行JSHint进行代码检查, 开启服务器代理, (事实上我的demo里已经给出了), 总之任意配置达到自己的要求, 从繁杂的业务中抽离出来. 如果对于其中的代码和插件感兴趣, 可直接查看直接源文件或者看这一篇.

2015-11-27更新 增加对异步接口的支持

之前结合FMPP只是解决了同步接口的问题, 那对于异步接口, 我们如何mock数据进行调试呢. 这里引入了优秀的express, 借助express强大的路由来实现前端模拟异步接口的功能.

既然express已经提供服务器的功能, 我们就不再需要gulp-connect了, 自动刷新功能借助connect-livereload和tiny-lr. 具体代码见server以及server_demo下的gulpfile.

你需要做的只是准备一份async.api.js, 里面根据你和后端约定的接口配置一份路由:

module.exports = {
    'get /rest/hh/:id': function(req, res) {
        res.json({"id":req.params.id, "hello":"ws"})
    },
    'get /rest/other': function(req, res) {
        res.json({"id":req.query.id, "hello":"23333"})
    },
    'post /rest/user': function(req, res) {
        if(req.body.username.length > 0 && req.body.password.length > 0) {
            res.json({"code":200, "message":"success"});
        } else {
            res.json({"code":400, "message":"参数错误"});
        }
    },
    'get /rest/com': function(req, res) {
        res.json({"com": "sd"});
    }
}

格式和puer一样.

然后执行gulp, 爽快的开发吧.

更多express路由的内容: http://expressjs.com/4x/api.html

构建前端Mock Server的更多相关文章

  1. 使用RAP搭建前端Mock Server

    转载自:<前后端分离--构建前端Mock Server--windows部署rap>http://www.cnblogs.com/dothin/p/5361883.html mock:模拟 ...

  2. 前后端分离--构建前端Mock Server--windows部署rap

    mock:模拟的,虚假的 mock server:模拟服务,模拟请求,模拟虚假数据 为了前后端更好的分工,接口文档是必须的,前后端都根据接口文档写代码,然后对接接口就行了. 但是,后端跟不上前端节奏, ...

  3. [03]使用阿里RAP搭建前端Mock Server

    MockServer可以减少前端开发对后端的依赖,提高前端开发的效率,同时也利于团队的协作. 什么是RAP? RAP是阿里团队出的一款WEB接口管理工具,帮助开发人员更高效的管理接口文档,同时通过分析 ...

  4. 【前端开发】 5分钟创建 Mock Server

    http://blog.csdn.net/wxqee/article/details/50165581 NOTIFY 官网文档现在已经很简约.很强大了,建议直接点击这里: Getting Starte ...

  5. 搭建Mock Server

    1.为什么要搭建mock-server? 为了更好的分工合作,让前端能在不依赖后端环境的情况下进行开发,其中一种手段就是为前端开发者提供一个 web 容器,这个本地环境就是 mock-server. ...

  6. 关于mock server

    这篇技术博客是在知乎上看到的 知乎js大神张云龙写的 这里贴过来记录下,如果侵权 请告知将及时删除. --------------------------- 为了更好的分工合作,让前端能在不依赖后端环 ...

  7. 用gulp替代fekit构建前端项目

    https://segmentfault.com/a/1190000003060016 离开qunar有一个多月了,在离开的时候就决定不再用fekit.做出这个决定并不是因为fekit不好,恰恰相反, ...

  8. mock server相关解决方案

    前后端分离之后 前后端分离后, 大家从此进入了所谓的并行开发时代. 一旦完成前后端的(边界)分工, 大家就可以各司其职了. 前端在与后端交互时, 要想有效地提高工作效率, 后端的接口文档就是重中之重了 ...

  9. mock server 前后端分离小结(转)

    1.前台开发受限于后台开发的速度 2.后台提供给前台的接口缺字段,时常需要联调 基于Mock Server开发的好处: 对于前端来讲,可以独立于后端进行开发. 对于后端来讲,根据前端定义的接口进行开发 ...

随机推荐

  1. TP复习11

    ## ThinkPHP 3.1.2 模板中的基本语法#讲师:赵桐正微博:http://weibo.com/zhaotongzheng 本节课大纲:一.导入CSS和JS文件 1.css link js ...

  2. [Angular2 Router] Understand the Angular 2 Base href Requirement

    The <base href=”/”/> you define will determine how all other assets you plan on loading treat ...

  3. [MEAN Stack] First API -- 3. Select by ID with Mongoose and Express

    Mongoose allows you to easily select resources by ID from your MongoDB. This is an important aspect ...

  4. iOS开发——开发必备OC篇&UITableView设置界面完整封装(一)

    UITableView设置界面完整封装(一) 简单MVC实现UITableView设置界面分组数据显示 一:模型 1:cell模型 /** 描述cell图片 */ @property (nonatom ...

  5. 对javascript this的理解

    对于this的理解,大部分时间都比较模糊,最近几天做了一些研究,记录一下 首先应该明白,this是执行上下文的一个属性,它的值取决于执行上下文,执行上下文和函数调用方式相关,定义一个function的 ...

  6. 关于修改Android手机的音量

    首先,必须要获取系统的声音服务权限 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS&qu ...

  7. 源码-hadoop1.1.0-core-org.apache.hadoop

    按包的顺序类的顺序来吧,因为我不懂hadoop类的具体体系和类之间的联系,如果有一定知识积累的可以看下别人写的hadoop源码解读类的书,类似的有 http://pan.baidu.com/s/1i3 ...

  8. Sql 之 sql中的强制类型转换

    1. convert(数据类型, 字段名) convert(datetime, startDate) 2. cast(字段名 as 数据类型) ,))

  9. SQL Server 的事务和锁(二)-Range S-S锁

    在这篇随笔中,我们的主要关注点在 Key-Range Lock.Key-Range Lock有 S-S.S-U.I-N.X-X几种情况.我们一个一个来说,力求明白.遗憾的是,这里可能会比较冗长,那么死 ...

  10. Oracle 约束类型

    在Oracle中的约束类型:NOT NULLUNIQUE KeyPRIMARY KEYFOREIGN KEYCHECK create table emp--创建表格 ,注意约束( empno numb ...