生活之中,如行径林间

基于koajs的web项目构建(二)

2016-09-06

根据 基于koajs的web项目构建(一) 所描述的,建立了项目的基本目录结构,接下来的工作便是编码,编译,测试,发布。做为这些工作,每一项工作都有自己的学问,针对这三项工作的技巧分析文章在网上有很多,所以我并不认为有人能够以简单的描述就涵盖。对于自己,仅作文去尝试清楚的阐述自己构建node项目的一些实践。

闲谈

养成良好编码习惯。前端项目中,js和html的语法都是很松散的,变量使用大写或者小写,语句末尾是否有;,大多数情况都是可以适应的。这样的设计无疑提供了更好的容错能力,却助纣了很多开发者随意的编码习惯。随意的编码风格最终导致项目代码的可维护性低,新加入成员学习成本提高。为了克服这一问题,强制约束编码规范是第一层解决方案,我们可以参照airbnb的编码规范,读一读编写可维护的javascript.从自己做起,再到所再的团队,力求所有编码人员都是统一编码风格,让自己和阅读自己程序的人节省出更多的时间。

合理的使用开发工具。开发工具为前端开发提供了越来越多的便利,对于工具而言,无非是熟能生巧,所以对于一个开发人员慢慢积累自己掌握的开发工具是很重要的。能熟练的使用编辑器,提高自己的编码速度;定义好代码质量检测插件,能约束自己写出更规范的代码;合理使用一些自动化构建工具,能让自己避免很多重复性的工作。

在项目中积累。不断有项目从自己手中经过,项目过后,我们又该如何?善于总结的人总会去分析,汲取项目中精华之处,研究项目中所遇到困难,反思项目中不足之处。再想想自己所经历的项目,是否是在抱怨别人代码不能看,四处碰壁,在网上搜点解决方案,艰难的完成之后就草草收场?我想有很大一部分人是这样的,至少曾今的我是这样的。最终,善于总结的人慢慢就与我们拉开了差距,成为我们仰望的大牛~~

保持良好的心态。不要一直把自己沉浸在工作之中,学会放松自己。保持良好的心态,为高效率,高质量的编码提供基础。

分享

vscode编辑器

微软出品,开源免费,编码神器

推荐插件:

自动化构建 gulp + webpack

gulp负责任务集成,web pack完成commons浏览器化。

推荐插件:

基于koajs的web项目构建(一)

2016-08-29

对 koajs 的学习已经持续一段时间,对于"用"这一层面基本掌握。学习之后,总是希望能实际的应用到项目之中。贸然给现有项目大换血是不现实的,姑且先拟一个小项目付诸实践。

在尝试使用 koajs 时,我依旧采用严格的 MVC 模式。M 做为数据模型层,主要负责业务数据的管理和操作,来源于数据库操作或者api调用。V 做为视图层,主要负责站点前台的展示。C 做为业务控制层,主要负责对站点业务流程的处理。基于这样的思路,首先建立起项目的基本目录结构:

+表示一级目录,++表示二级目录,+++表示三级级目录,

+ configs(项目配置文件目录)
++ build(项目编译相关配置) *

+ controllers(项目业务控制代码目录)

+ kits(常用工具包)

+ middlewares(项目中间件)

+ models(业务数据对象,可以是操作数据库,可以是来源于调用api)

+ public(静态资源目录)
++ src(项目静态资源源文件)
+++ fonts(字体文件)
+++ iamges(图片)
+++ styles(未编译样式脚本,本项目使用sass)
+++ scripts(未编译js脚本,本项目部分使用es6)
++ publish(项目静态资源发布文件,发布自动生成)

+ routers(路由配置文件目录)

+ test(项目相关测试文件)

+ views(项目视图目录)
++ dev(开发视图文件)
++ pro(发布视图文件,发布自动生成)

+ app.js(项目入口)

注:项目目录是让写程序和看程序的人能一眼了解项目结构,我且主观的认为这样的结构是能让看到的人一目了然

对于以中间件为一级公民的koajs,在使用中我主要使用以下几个关键技术:

注:条条大路通罗马,所谓的技术选择全然是个人的爱好

剔除业务相关的功能,我将此项目的架子抽了出来,命名为koa-skeleton,意为骨架,希望供大家参考一二,项目地址:https://github.com/jaylinwang/koa-skeleton


  • 2016年9月5日补充项目目录描述

Swift http请求

2016-06-15

分享一段swift http请求的代码:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let url = NSURL(string: "http://www.douban.com/j/app/radio/channels");
        let session = NSURLSession.sharedSession()
        let task = session.dataTaskWithURL(url!) { (data, response, error) in
            if let err = error{
                print(err)
            }else{
//                let str = NSString(data: data!, encoding: NSUTF8StringEncoding)
//                print(str)
                let json = try? NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions()) as! NSDictionary
                print("json:\(json)")
            }
        }
        task.resume()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

可能遇到的问题: - 网络请求报 App Transport Security has blocked a cleartext - 解决方案:

打开Info.plist,设置

配置示意图

或者直接打开source code,添加

<key>NSAppTransportSecurity</key>  
<dict>  
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>  

gulp入门

2016-05-17

gulp作为新一代前端项目自动化构件工具,已经普遍应用于前端工程中。大部分前端开发者对gulp已经不再陌生,但是对于刚接触gulp的开发人员而言,也免不了些许迷茫。试着从自己学习和使用经验讲一讲。
首先,回顾当下自己所开发的前端项目,是否包含js、css、images静态资源,在项目上线前,我们需要这些静态资源合并压缩。在学习自动化构件工具之前的开发流程中,我们一般需要找到一些工具,我常用的有oschina在线工具koala(js/css编译压缩)TinyPNG(图片压缩),配置文件输入输出,upload、download、我们不断重复着这些工作。烦不烦,反正我是有些厌倦了。

我们本该将更多的精力放在更有意义的事情上

所以,grunt、gulp这一类构件工具出现了,将我们解救于重复的工作中。就自己的理解,自动化构件工具的核心是将我们的工作流抽离为一个个任务(task),根据我们自己的需求,css的合并压缩可以为一个任务、js的合并压缩可以为一个任务、图片的压缩也可以为一个任务,我们可以将上线前对静态资源的操作分成以上三个任务。最后,我们只需要运行一个命令,这些任务就会自动执行。再加上对每个文件变化的监听,每次文件的修改都会触发自动构建。妈妈再也不担心我们做重复的事情了,是不是倍儿爽?

对于我,学习一个新的工具,首先是用起来。

  • gulp需要依赖node环境运行,首先确保自己安装有node环境

  • 全局安装gulp,npm install -g gulp

  • 在文件夹创建gulpfile.js

  • 文件夹下创建src/css/main.css和src/js/main.js

  • 安装gulp和gulp plugin,执行npm install --save-dev gulp {gulp插件名},以cssmin和uglifyjs为例,npm install --save-dev gulp-cssmin gulp-uglify gulp-rename

  • 配置gulpfile,以cssmin和uglifyjs为例

const gulp = require('gulp');  
const cssmin = require('gulp-cssmin');  
const rename = require('gulp-rename');  
const uglify = require('gulp-uglify');

gulp.task('min:css', function () {  
    return gulp.src('src/css/main.css')
    .pipe(cssmin())
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest('dist/css'));
});

gulp.task('min:js', function () {  
    return gulp.src('src/js/main.js')
        .pipe(uglify())
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest('dist/js'));
});

gulp.task('default', ['min:js', 'min:css']);
  • 执行gulp,运行gulp default任务,执行gulp min:css,根据taskname执行单个任务

  • 执行结果,目录下有新增dist/css/main.min.css和dist/js/main.min.js压缩文件

根据以上步骤,gulp基本使用起来了。

本章源码托管于github/demo-gulp,希望能对gulp初学者有帮助。

晒一手handlebar helper

2016-05-15

最近项目中用到hbs模版,结合express,感觉还不错。其中,helper是handlebar的核心,为了让自己用得更爽,经过搜集和琢磨,留下一手helper,亲测有效。

1. block与extend

  • 源码
let blocks = {};  
hbs.registerHelper('extend', function (name, context) {  
    let block = blocks[name];
    if (!block) {
        block = blocks[name] = [];
    }

    block.push(context.fn(this));
});

hbs.registerHelper('block', function (name) {  
    let val = (blocks[name] || []).join('\n');
    blocks[name] = [];
    return val;
});
  • 使用

layout.hbs(page1页面母版):

<head>  
    <meta charset="UTF-8">
    <title>{{{block "title"}}}</title>
</head>  

page1.hbs(子页面):

{{#extend "title"}}
测试标题
{{/extend}}

输出:

<head>  
    <meta charset="UTF-8">
    <title>测试标题</title>
</head>  

2. 包含

  • 源码
hbs.registerHelper('include', function (args1, args2, context) {  
    let array = args2.split(',');
    if (!_.isArray(array)) {
        return context.inverse(this);
    }
    if (_.includes(array, args1) || _.includes(array, args1.toString())) {
        return context.fn(this);
    }
});
  • 使用
{{#include '1' '1,2,3'}}
'1' include in '1,2,3'  
{{else}}
'1' not include in '1,2,3'  
{{/include}}
---
{{#include 'b' 'c,d'}}
'b' include in 'c,d'  
{{else}}
'b' not include in 'c,d'  
{{/include}}

输出:

'1' include in '1,2,3'  
---
'b' not include in 'c,d'  

3. 等于

  • 源码
hbs.registerHelper('equal', function (args1, args2, context) {  
    if (args1 === args2) {
        //满足添加继续执行
        return context.fn(this);
    } else {
        if (typeof(args1) === 'number' && args1.toString() === args2.toString()) {
            return context.fn(this);
        }
        //不满足条件执行{{else}}部分
        return context.inverse(this);
    }
});
  • 使用
{{#equal 1 2}}
1 === 2  
{{else}}
1 !== 2  
{{/equal}}

输出:

1 !== 2  

4. 大于等于

  • 源码
hbs.registerHelper('egt', function (args1, args2, context) {  
    if (args1 >= args2) {
        return context.fn(this);
    } else {
        return context.inverse(this);
    }

});
  • 使用同equal

5. 大于

  • 源码
hbs.registerHelper('gt', function (args1, args2, context) {  
    if (args1 > args2) {
        return context.fn(this);
    } else {
        return context.inverse(this);
    }

});
  • 使用同equal

6. 小于等于

  • 源码
hbs.registerHelper('elt', function (args1, args2, context) {  
    if (args1 <= args2) {
        return context.fn(this);
    } else {
        return context.inverse(this);
    }

});
  • 使用同equal

7. 小于

  • 源码
hbs.registerHelper('lt', function (args1, args2, context) {  
    if (args1 < args2) {
        return context.fn(this);
    } else {
        return context.inverse(this);
    }

});
  • 使用同equal

8. 结合each实现遍历N次

  • 源码
hbs.registerHelper('count', function (args1, context) {  
    let array = [];
    for (let i = 1; i <= args1; i++) {
        array.push(i);
    }
    return context.fn(array);
});
  • 使用
{{#count 5}}
  {{#each this |index|}}
    {{index}}、
  {{/each}}
{{/count}}

输出:

1、2、3、4、5  

9. 加法

  • 源码
hbs.registerHelper('add', function (args1, args2) {  
    return args1 + args2;
});
  • 使用
{{add 1 2}}

输出:

3  

10. 减法

  • 源码
hbs.registerHelper('sub', function (args1, args2) {  
    return args1 - args2;
});
  • 使用
{{sub 3 1}}

输出:

2  

Atom配置emmet快速编码

2016-05-15

Emmet 的前身是大名鼎鼎的 Zen coding,从事 Web 前端开发的同学对该插件一定不会陌生。在编写 html 时它使用仿 CSS 选择器的语法来生成代码,大大提高了 HTML/CSS 代码编写的速度。atom 默认是没有支持 emmet 的,需要我们自己安装。

安装

执行 apm install emmet 或者进入 atom 插件安装界面,搜索 emmet 完成安装

配置

大多数人应该习惯 tab 触发 emmet 快速生成代码,在 atom 中,我们可以配置自定义快捷键达到我们想要的效果。

  • 找到 keybinding > your keymap file ,打开 keymap.cson 配置文件

  • 添加如下配置:

'atom-text-editor[data-grammar="YOUR GRAMMAR HERE"]:not([mini])':  
    'tab': 'emmet:expand-abbreviation-with-tab'

YOUR GRAMMAR HERE 是你想要支持的语法,可在编辑代码时打开 atom 审查元素窗口,找到<atom-text-editor> 标签,例如,html 的 grammar 是 text html basic. 以下是我的配置。

'atom-text-editor[data-grammar="source js jsx"]:not([mini]),atom-text-editor[data-grammar="text html basic"]:not([mini])':  
    'tab': 'emmet:expand-abbreviation-with-tab'