如何开发前端开源项目

@GuoYongfeng 2016-07-14 12:58:36发表于 iuap-design/blog

如何开发前端开源项目

作为前端工程师的你,或是接触过前端项目的你,肯定用过或是听过很多前端相关的开源项目。那么,如何做一个开源项目呢?一个开源项目都有哪些注意点?如何参与到开源社区一起贡献代码?今天我们一起来聊聊这个话题。

1. 平台选择

Github是全球最大的社交编程及代码托管网站:https://github.com

  • 人气高,交流方便,聚集了志同道合的人
  • 完善的机制:issue,开源分享,代码托管,wiki,release功能,ci,文档机制等

2. 基础知识概览

Git

git 分布式版本控制系统

掌握基本的Git使用,建议多使用命令行的方式,会更清晰简单。

echo "# git-github" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin git@github.com:GuoYongfeng/git-github.git
git push -u origin master

markdown

markdown 基本语法

包管理工具

  • npm & nodejs 基础
  • bower

版本号

目前大多产品或开源项目采用类似1.2.3的三位数进行版本号管理。版本号修改规则如下:

  • **主版本号:**当功能模块有较大的变动,比如增加模块或是整体架构发生变化。此版本 号由项目决定是否修改。
  • **次版本号:**相对于主版本号而言,次版本号的升级对应的只是局部的变动,但该局部 的变动造成程序和以前版本不能兼容,或者对该程序以前的协作关系产生 了破坏,或者 是功能上有大的改进或增强。此版本号由项目决定是否修 改。
  • **修订版本号:**一般是Bug 的修复或是一些小的变动或是一些功能的扩充,要经常发布 修订版,修复一个严重 Bug 即可发布一个修订版。此版本号由项目经理 决定是否修改。

3. 快速开始

Git和Github快速入门指南

在Github注册帐户,建立仓库,上传代码。即使你是小白也没有关系,相信看完这篇Git和Github快速入门指南,你也能轻松开始。

项目结构

为大家准备了一个前端开源项目推荐目录结构

.babelrc        # babel 配置文件
.eslintrc       # eslint 代码规则检查配置文件
.gitignore      # git 忽略提交文件配置
.travis.yml     # ci 持续集成构建配置
CHANGELOG.md    # 项目更改日志记录
conf/           # 整体配置文件,构建相关
CONTRIBUTING.md # 如何参与贡献代码
dist/           # 构建产出资源
docs/           # 项目文档
LICENSE         # 版权说明
node_modules/   # node 安装包下载目录
package.json    # npm 包管理配置
README.md       # 项目整体说明
src/            # 开发源代码
test/           # 测试代码

4. 关于文档

文档是你的潜在用户了解项目的第一道窗口,文档书写的好坏直接决定了项目的易用性和用户粘性。

README

我们首先要提的是 README 文档,这是每个开源项目所必须的,README 文档会默认展示在项目首页,可以算作是整个项目的门面。一个靠谱的 README 应该包含以下几部分:

  • 言简意赅的项目介绍:你的项目解决了什么核心问题,有哪些令人心动的特性。
  • 简单的安装和使用指导:用户如何安装你的项目,又如何使用在自己的项目中,你应该想办法让这部分尽量简单,降低接受成本。
  • API 和配置说明:也许你的项目十分强大,支持很多特性,你需要告诉用户如何通过配置和 API 来完成这些事情,在这中间,也许你可以插入一些简单的 demo,帮助用户理解,这部分的好坏直接决定了项目的易用性。

随着你的项目日趋复杂,也许 README 的篇幅已经不能够承载你的 API 说明,这时在项目中单独建立一个 doc 文件夹用来存放文档,也是很多人的选择。

  • 如何贡献:开源的一个很重要的目的是为了让社区中的更多人来帮助你完善你的创意,你需要告诉他们你有哪些部分是他们可以帮的上忙的,你是如何对待 issues 和 pull requests( 后文称 pr) 的。
  • 如何与作者取得联系:有些合作和洽谈可能无法承载在 issue 上,告诉用户除了 issues,还有什么途径可以与作者取得联系。
  • 开源许可协议:既然是一个开源项目,那么开源许可协议必然是不可少的,你的开源许可是 MIT、BSD 还是 ISC、Apache?当然你也需要了解这些开源许可的意义,这里推荐一篇知乎问答。

CONTRIBUTING

上面我们也提到了如何贡献的问题,当贡献需要了解的东西越来越多的时候,我们也习惯于把它单独抽成一份 CONTRIBUTING.md。在贡献文档中应该详细地告诉贡献者,哪些功能点是需要贡献者参与的,如何提 issue 以及 pr。

CHANGELOG

无论什么项目,都是持续迭代开发的。每个版本之间,都会有很多或大或小的改动。通过CHANGELOG.md文档来记录项目每个大小版本之间的改动,方便开发者和用户进行沟通和使用。

LICENSE

除了在 README 中提到遵循的开源协议外,一个靠谱的开源项目还会将该开源协议的内容文档放在自己的项目中。

另外,选择一个合适的开源协议也是很重要的。开源协议比较多,下面聊几个常用的开源协议:

  • **BSD开源协议:**BSD开源协议是一个给于使用者很大自由的协议。基本上使用者可以”为所欲为”,可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。
  • **Apache Licence 2.0:**Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件)。
  • **MIT:**MIT是和BSD一样宽范的许可协议,作者只想保留版权,而无任何其他了限制。也就是说,你必须在你的发行版里包含原许可协议的声明,无论你是以二进制发布的还是以源代码发布的。

更多关于开源协议的内容可以直接查看五种开源协议比较

5. 代码风格

关于代码风格,每个人可能都会有自己的偏好,这些偏好中有好的,也有坏的,一些不好的代码风格会让其他开发者感到不快,减少了大家对于代码的关注,好在强大的开源社区中同样也有人开源了代码风格规范,这些代码规范都经过了激烈的讨论和充分的修改,为大多数人所认可,需要注意的是代码风格并不只是缩进、空格这一类的事情,它更多地是一种代码习惯,比如何时使用 const,何时使用 let,是否有声明但未使用的变量等等,这些习惯并不影响代码的功能,却可以很大程度上决定代码的可维护性、易读性和降低犯错的机会,同时也让其他开发者对你的项目刮目相看。

代码风格推荐

Airbnb

https://github.com/airbnb/javascript

Airbnb 的 js 规范应该是目前受认可度最高的代码规范之一,目前在 Github 上已经累加了 36700+ 颗星,包含的领域非常广泛,包括线下时髦的 ES6 和 React JSX 等等,笔者推荐。

idiomatic.js

https://github.com/rwaldron/idiomatic.js/

这是一份有着很长历史的,由一群经验丰富的 js 工程师维护的代码风格规范,同时也十分通俗易懂,另外他也有简体中文的版本。

jQuery

https://contribute.jquery.org/style-guide/js/

jQuery 所倡导和使用的代码规范,大量的 jQuery 组件根据这一规范书写,如果你读过 jQuery 的源码,你喜欢他的风格,或者你正在开发一款 jQuery 的插件,那这也是一个不错的选择。

Google

https://google.github.io/styleguide/javascriptguide.xml

谷歌倡导的代码风格,自 2012 年推出以后已经有很多谷歌的项目遵循这份规范进行编码,喜欢谷歌风格的朋友可以使用。

LINT

看到这里有人会有疑问,规范虽然好,可是条目太多了,我虽然可以学习,但是全都记住难度太高了。不用担心,你的痛点也是大家的痛点,早已经有工具帮助我们来解决这一问题,而且更棒的是他可以无缝地与你的 IDE 相结合。

在这里我们要推荐 ESLint 这款工具。在不久之前,你还有另一个选择 JSCS,但在最近,JSCS 团队选择与 ESLint 团队进行合并,专注于一款产品 ESLint 的开发,两大大牛团队的合体想必会带给 ESLint 更为强大的生命。

ESlint 提供了非常丰富的 IDE 集成工具,目前已经支持 Sublime Text 3, Vim, Emacs, Eclipse, TextMate 2, Atom, IDEA 和 Visual Studio Code。具体的插件工具请移步 ESlint 的集成文档。下面我们以 sublime 为例,简单讲一下如何使用这些插件:

  • 首先全局安装 ESLint:
npm install -g eslint
  • 接着通过 Package Control,安装 SublimeLinter 和 SublimeLinter-contrib-eslint。
  • 初始化 eslint 配置
eslint --init

这里会有一些人机交互,来选择 eslint 的风格,之后 eslint 就会在你的项目下添加对应的依赖,重启 sublime,就可以看到效果了。有时仅通过编辑器中给出的提示文案,无法帮你准确理解含义,这时我们还可以借助 eslint 的站点:http://eslint.org/docs/rules/ ,这里有更详细的讲解,你还可以直接搜索对应的规则。

6. 测试

靠人工来保证项目的维护总是不出差错是不靠谱的,人总有健忘和糊涂的时候,尤其是当项目越来越复杂时,一个人甚至可能无法全部了解项目的全部逻辑,这时我们就要依靠测试来保证项目的可靠性,这里的测试包括但不限于,单元功能测试,UI 测试,兼容性测试等等。

测试体系

一个测试体系大体应该包含以下三部分,这三者功能上互相独立,但合作完成一次测试:

  • 测试运行器(Test runner):主要负责测试的自动化,主要负责调用测试框架和测试代码,自动打开浏览器或者 js 环境,执行测试。
  • 测试框架(Testing Framework):测试框架规定了测试风格和测试的生命周期(lifeCircle hook)。
  • 断言库(Assertion library):每个测试单元是通过一句或者一组断言来组成的,每一句断言声明了对一种功能的描述。例如 expect(window.r).to.be(undefined);。

Test runner

一个优秀的 runner 可以做很多事情,我们以 Google Angular 团队推出的 karma 为例,你可以指定在什么浏览器中,使用什么测试框架,进一步地完成测试框架的配置,以及其他非常多的定制。他的安装和初始化也非常简单:

# Install Karma:
$ npm install karma --save-dev

# Install plugins that your project needs:
$ npm install karma-jasmine karma-chrome-launcher --save-dev

初始化配置文件

$ karma init my.conf.js

Which testing framework do you want to use?
Press tab to list possible options. Enter to move to the next question.
> jasmine

...

Do you want Karma to watch all the files and run the tests on change?
Press tab to list possible options.
> yes

Config file generated at "/Users/vojta/Code/karma/my.conf.js".

然后就可以运行了

# Run Karma:
$ ./node_modules/karma/bin/karma start

当然这只是最初始化的配置,我们还没有写真正的测试,所以这里只是一个空架子。

测试框架

测试框架有很多:

  • mocha
  • jasmine
  • qunit
  • Jest

对于一般的开发者来说,他们都能够满足日常的测试需求,所以主要看你的使用习惯,这里以 mocha 为例来给大家一个大概的印象。

首先安装 mocha

$ npm install -g mocha
$ mkdir test
$ $EDITOR test/test.js

接下来写你的 test

var assert = require('chai').assert;
describe('Array', function() {
  describe('#indexOf()', function () {
    it('should return -1 when the value is not present', function () {
      assert.equal(-1, [1,2,3].indexOf(5));
      assert.equal(-1, [1,2,3].indexOf(0));
    });
  });
});

运行 test,查看结果

mocha test/test.js

当然上面这个测试只能测试 node 下的 js 代码,如果你的代码是前端项目,那么就要借助 phantom/browser 等工具了,同时操作这么多东西很麻烦,这时 karma 的作用的就体现出来了,本文只是大体的介绍,因此不再铺开去讲,详细请查看 karma 的官方文档。

断言库

断言库也有很多的选择,其中比较有名气的有:

  • expect.js
  • should
  • chai

其中,chai 同时支持 BDD 和 TDD 两种测试模式,而 expect.js 具有 IE6+ 级别的浏览器兼容性。

测试模式

有人会问 BDD 和 TDD 都代表了什么?

  • TDD

TDD(Test-driven development),即 测试驱动开发。即先根据需求写测试,然后再写代码,使代码逐渐符合测试要求,不符合时重构代码满足。这种开发模式适合一些需求非常清晰明确,且不再变更的情况,在一般的开发中,我们还是 BDD 的模式使用的比较多。chai 提供的 assert 部分是经典的 TDD 风格,大致如下

var assert = require('chai').assert
  , foo = 'bar'
  , beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };

assert.typeOf(foo, 'string'); // without optional message
assert.typeOf(foo, 'string', 'foo is a string'); // with optional message
assert.equal(foo, 'bar', 'foo equal `bar`');
assert.lengthOf(foo, 3, 'foo`s value has a length of 3');
assert.lengthOf(beverages.tea, 3, 'beverages has 3 types of tea');
  • BDD

BDD(Behavior-Driven development),即 行为驱动开发。

通常 BD测试提供了几个方法:

  • describe()
  • it()
  • before()
  • after()
  • beforeEach()
  • afterEach()

通过这些方法描述一种行为,当测试的表现满足行为的预期时,即表示测试通过。

7. 持续集成

持续集成,continuous integration (简称 ci),指的是频繁地(一天多次)将代码集成到主干。

为了保证这种快速迭代的开发方式不出差错,采取的核心措施:代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。这种行为虽然不能消除 bug,但有效地帮助我们即时发现错误并改正。关于持续集成的详细流程,大家参考阮老师的 持续集成是什么?。本文则重点介绍已经介入 github,可以帮助到我们的继承工具。

接入到 github 的所有 CI 可以在 https://github.com/integrations 中查看。

CI: Travis CI/ CircleCI

两者都是接入 Github 的持续集成工具,其核心是通过一个脚本,在代码 commit 的时候自动运行继承脚本,完成测试、构建等任务。以 Travis CI 为例:

  • 首先在 github 的 Travis CI 页面将 Travis CI 的 hook 加入到你的项目中。
  • 接着在你的项目目录下建立一个 .travis.yml,大致长成这个样子:
language: node_js

sudo: false

notification:
  email:
    - xxx@hotmail.com

node_js:
- 4.0.0

env:
  matrix:
  - TEST_TYPE=test
  - TEST_TYPE=coverage
  - TEST_TYPE=saucelabs

在不指定 .travis.yml 的情况下,travis 会自动执行 npm install 和 npm test 来进行集成测试。更多的配置可以参考官方的文档。集成通过在两个地方可以有所体现:

  • 一个是 ci 提供的 badge:
  • 一个是在 pr 提交时的自动 comment

跨浏览器集成测试:SAUCELABS & Browser Stack

这两个工具都是提供了多种浏览器环境,包括 pc 端和移动端,然后在多种环境下都是去运行测试脚本,来测试项目的浏览器兼容性。其中 SAUCELABS 对于开源项目完全免费,只需要走他的 Open Source Plan 即可,而 Browser Stack 虽然也提供了 Open Source 的免费计划,但比较麻烦,需要邮件联系,并且在项目 README 中提到其对项目的支持。手动配置这些集成还是比较麻烦的,一般我们都借助 karma 来集成,使用 karma 的 karma-saucelabs-launcher 和 karma-browserstack-launcher。

saucelabs 也提供了很棒的 badge

代码覆盖率集成 Coveralls

代码覆盖率可以在本地测试里集成,同样也可以在 CI 中集成,通过引入 Coveralls,他可以将你持续集成测试中得到的代码覆盖率结果做一个记录和保存,同时及时的反馈给用户。

Coveralls 也有两个地方可以体现:

  • 一个是 Coveralls 提供的 badge:
  • 一个是在 pr 提交时的自动 comment

8. 总结

最后,希望通过上述内容,让大家了解到一个靠谱的前端开源项目应该具备的东西,这个靠谱不仅是为了让用户用的放心,更是为了开发者在开发时心中有谱。

但若要开发一个成功的开源项目,则还需要开发者更多的经营,最重要的,是一份为用户解决痛点的初衷和持之以恒的决心。