写前端代码一段时间之后,你可能会萌生做一个开源项目的想法,一方面将自己的好点子分享出去让更多的人受益,另一方面也可以在社区贡献的环境下学到更多的东西从而快速成长。但是开源项目也有开源项目的玩法,一些可能没有注意的点,也许会让你的好点子和许多人失之交臂,在这里笔者以自身经验出发,聊一聊笔者心目中的靠谱的 Github 前端开源项目应该具有什么。当然我们讨论的只是一个项目至少需要什么才是靠谱的。真的想要做好一个项目,需要的比这里要讲的多得多。
限于篇幅,本文很多点都是点到为止,文章中有大量链接供同学进一步了解掌握相关知识。
文档是你的潜在用户了解项目的第一道窗口,文档书写的好坏直接决定了项目的易用性和用户粘性。
我们首先要提的是 README 文档,这是每个开源项目所必须的,README 文档会默认展示在项目首页,可以算作是整个项目的门面。一个靠谱的 README 应该包含以下几部分:
言简意赅的项目介绍:你的项目解决了什么核心问题,有哪些令人心动的特性。
简单的安装和使用指导:用户如何安装你的项目,又如何使用在自己的项目中,你应该想办法让这部分尽量简单,降低接受成本。
API 和配置说明:也许你的项目十分强大,支持很多特性,你需要告诉用户如何通过配置和 API 来完成这些事情,在这中间,也许你可以插入一些简单的 demo,帮助用户理解,这部分的好坏直接决定了项目的易用性。
随着你的项目日趋复杂,也许 README 的篇幅已经不能够承载你的 API 说明,这时在项目中单独建立一个 doc 文件夹用来存放文档,也是很多人的选择。
如何贡献:开源的一个很重要的目的是为了让社区中的更多人来帮助你完善你的创意,你需要告诉他们你有哪些部分是他们可以帮的上忙的,你是如何对待 issues 和 pull requests( 后文称 pr) 的。
如何与作者取得联系:有些合作和洽谈可能无法承载在 issue 上,告诉用户除了 issues,还有什么途径可以与作者取得联系。
开源许可协议:既然是一个开源项目,那么开源许可协议必然是不可少的,你的开源许可是 MIT、BSD 还是 ISC、Apache?当然你也需要了解这些开源许可的意义,这里推荐一篇 知乎问答 。
上面我们也提到了如何贡献的问题,当贡献需要了解的东西越来越多的时候,我们也习惯于把它单独抽成一份 CONTRIBUTING.md。在贡献文档中应该详细地告诉贡献者,哪些功能点是需要贡献者参与的,如何提 issue 以及 pr。
除了在 README 中提到遵循的开源协议外,一个靠谱的开源项目还会将该开源协议的内容文档放在自己的项目下方。
关于代码风格,每个人可能都会有自己的偏好,这些偏好中有好的,也有坏的,一些不好的代码风格会让其他开发者感到不快,减少了大家对于代码的关注,好在强大的开源社区中同样也有人开源了代码风格规范,这些代码规范都经过了激烈的讨论和充分的修改,为大多数人所认可,需要注意的是代码风格并不只是缩进、空格这一类的事情,它更多地是一种代码习惯,比如何时使用 const
,何时使用 let
,是否有声明但未使用的变量等等,这些习惯并不影响代码的功能,却可以很大程度上决定代码的可维护性、易读性和降低犯错的机会,同时也让其他开发者对你的项目刮目相看。
2.1.1 Airbnb: https://github.com/airbnb/javascript
Airbnb 的 js 规范应该是目前受认可度最高的代码规范之一,目前在 Github 上已经累加了 36700+ 颗星,包含的领域非常广泛,包括线下时髦的 ES6 和 React JSX 等等,笔者推荐。
2.1.2 idiomatic.js: https://github.com/rwaldron/idiomatic.js/
这是一份有着很长历史的,由一群经验丰富的 js 工程师维护的代码风格规范,同时也十分通俗易懂,另外他也有简体中文的版本。
2.1.3 jQuery: https://contribute.jquery.org/style-guide/js/
jQuery 所倡导和使用的代码规范,大量的 jQuery 组件根据这一规范书写,如果你读过 jQuery 的源码,你喜欢他的风格,或者你正在开发一款 jQuery 的插件,那这也是一个不错的选择。
2.1.4 Google: https://google.github.io/styleguide/javascriptguide.xml
谷歌倡导的代码风格,自 2012 年推出以后已经有很多谷歌的项目遵循这份规范进行编码,喜欢谷歌风格的朋友可以使用。
看到这里有人会有疑问,规范虽然好,可是条目太多了,我虽然可以学习,但是全都记住难度太高了。不用担心,你的痛点也是大家的痛点,早已经有工具帮助我们来解决这一问题,而且更棒的是他可以无缝地与你的 IDE 相结合。
在这里我们要推荐 ESLint 这款工具。在不久之前,你还有另一个选择 JSCS ,但在最近,JSCS 团队选择与 ESLint 团队进行合并,专注于一款产品 ESLint 的开发,两大大牛团队的合体想必会带给 ESLint 更为强大的生命。
图1:JSCS 与 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,就可以看到效果了。
图2:eslint sublime 插件演示
我们可以看到,linter 对于不符合规则的行和代码块会标红,将鼠标点击到对应标红的块,会显示报错的原因,比如上图中是因为 (global-require) 规则。有时仅通过提示的错误文案,无法帮你准确理解含义,这时我们还可以借助 eslint 的站点: http://eslint.org/docs/rules/ ,这里有更详细的讲解,你还可以直接搜索对应的规则。
靠人工来保证项目的维护总是不出差错是不靠谱的,人总有健忘和糊涂的时候,尤其是当项目越来越复杂时,一个人甚至可能无法全部了解项目的全部逻辑,这时我们就要依靠测试来保证项目的可靠性,这里的测试包括但不限于,单元功能测试,UI 测试,兼容性测试等等。
一个测试体系大体应该包含以下三部分,这三者功能上互相独立,但合作完成一次测试:
测试运行器(Test runner):主要负责测试的自动化,主要负责调用测试框架和测试代码,自动打开浏览器或者 js 环境,执行测试。
测试框架(Testing Framework):测试框架规定了测试风格和测试的生命周期(lifeCircle hook)。
断言库(Assertion library):每个测试单元是通过一句或者一组断言来组成的,每一句断言声明了对一种功能的描述。例如 expect(window.r).to.be(undefined);
。
一个优秀的 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()
通过这些方法描述一种行为,当测试的表现满足行为的预期时,即表示测试通过。
持续集成,continuous integration (简称 ci),指的是频繁地(一天多次)将代码集成到主干。
为了保证这种快速迭代的开发方式不出差错,采取的核心措施:代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。这种行为虽然不能消除 bug,但有效地帮助我们即时发现错误并改正。关于持续集成的详细流程,大家参考阮老师的 持续集成是什么? 。本文则重点介绍已经介入 github,可以帮助到我们的继承工具。
接入到 github 的所有 CI 可以在 https://github.com/integrations 中查看。
两者都是接入 Github 的持续集成工具,其核心是通过一个脚本,在代码 commit 的时候自动运行继承脚本,完成测试、构建等任务。以 Travis CI 为例,首先在 github 的 Travis CI 页面将 Travis CI 的 hook 加入到你的项目中。
图3:将 Travis CI/CircleCI 集成到你的项目中。
接着在你的项目目录下建立一个 .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
这两个工具都是提供了多种浏览器环境,包括 pc 端和移动端,然后在多种环境下都是去运行测试脚本,来测试项目的浏览器兼容性。其中 SAUCELABS 对于开源项目完全免费,只需要走他的 Open Source Plan 即可,而 Browser Stack 虽然也提供了 Open Source 的免费计划,但比较麻烦,需要邮件联系,并且在项目 README 中提到其对项目的支持。手动配置这些集成还是比较麻烦的,一般我们都借助 karma 来集成,使用 karma 的 karma-saucelabs-launcher 和 karma-browserstack-launcher 。
saucelabs 也提供了很棒的 badge
代码覆盖率可以在本地测试里集成,同样也可以在 CI 中集成,通过引入 Coveralls,他可以将你持续集成测试中得到的代码覆盖率结果做一个记录和保存,同时及时的反馈给用户。
Coveralls 也有两个地方可以体现:
一个是 Coveralls 提供的 badge:
一个是在 pr 提交时的自动 comment
图4:coveralls 的自动 comment
碍于篇幅有限和行文的目的,文中提供的很多点,只是举了一些例子,点到为止,同时提供了链接,供大家日后仔细研究。作者希望通过此文,让读者了解到一个靠谱的前端开源项目应该具备的东西,这个靠谱不仅是为了让用户用的放心,更是为了开发者在开发时心中有谱。那具备了这些就代表了一个成功的开源项目吗?很遗憾,这只是通往成功的必备条件,一个成功的开源项目还需要开发者更多的经营,最重要的,是一份为用户解决痛点的初衷和持之以恒的决心。
惯例地来宣传一下团队开源的 React PC 组件库 UXCore ,上面提到的点,在我们的 组件开发工具 中都有体现,欢迎大家一起讨论,也欢迎在我们的SegmentFault 专题下进行提问讨论。
本文作者 eternalsky ,始发于团队微信公众号 猿猿相抱 和 segmentFault 专栏 UXCore ,转载请保留作者信息。