评论删除后,数据将无法恢复
Two weeks ago, I open-sourced TravisLight, a build monitoring tool, also known asbuildwall, for Travis-CI. That was a weekend project I did for fun, but also to act as a real frontend developer.
When I was at Nelmio, I was more a backend guy than a frontend developer, even if I worked on some of the JavaScript applications. I spent most of my time writing APIs for the frontend developers, but sometimes I was just wrong. Actually, I think every backend guy should work on frontend stuff for a while, and vice versa. That’s one of the best ways to understand what you need to do.
I noticed that the only things a frontend developer needed was a smart API, and a good documentation. As a backend developer, you have to provide both. The frontend developer depends on you. Also, don’t force your frontend guy to use your tools. Yeah, Assetic is a wonderful toy for PHP developers, but it’s not a tool for frontend guys. There are better tools to compile the JS/CSS files, written in JavaScript, like Grunt. Let your frontend developer manage his own stuff. For example, in a Symfony2 project, I would recommend to put all JS/CSS files into theweb/folder rather than into the*Bundle/Resources/publicfolders, so that the frontend guy doesn’t have to browse the whole project to find a specific file.
But this is not the purpose of this post. Let me explain why and how I wrote TravisLight, and the tools I discovered.
I started reading Backbone Fundamentals as I wanted to learn Backbone.js. If you don’t know Backbone yet, it’s a JavaScript framework that gives you a structure to write a web application.
As working on a project is the best way to learn, I decided to write a Backbone.js application using the Travis-CI API. TravisLight was something I always wanted in order to manage my own open source projects. I needed a tool that was simple and clear. That was the perfect project to start, especially for a weekend.
Instead of using Underscore.js, I used Lo-Dash which is an alternative to Underscore.js delivering consistency, customization, performance, and extra features as they say. I also used RequireJS, and Moment.js. In order to manage all these dependencies, I needed a tool, so I took a look at Bower, from the Twitter guys.
Bower is a package manager for the web, in other words, a package manager for JS/CSS libraries. Even if it’s more a package downloader for now, it’s worth using it to avoid versioning jQuery, Twitter Bootstrap, etc. All you need is acomponent.jsonfile that looks like:
{ "name": "travis-light", "dependencies": { "jquery": "~1.8.3" } }
Runningbower installinstalls the dependencies into acomponents/folder.
So, I started to work hard on my application. Each time I needed a new library, I ranbower install <lib> --saveto install it and update thecomponent.jsonfile.
At some point, I needed a tool to perform some tasks on my application like running jshint or compiling my files. I tried Grunt, a build tool written in JavaScript, and it was a good choice.
Grunt is a task-based command line build tool for JavaScript projects. At first glance, this tool seems hard to use, but once you get it, it’s just awesome! You canlintyour files,minifyyour JS/CSS files,runthe test suite, and so on.
In TravisLight, I mainly use Grunt to package the application. Packaging the application means:
requirejs: { compile: { options: { name: "main", baseUrl: "js/", mainConfigFile: "js/main.js", out: "dist/compiled.js" } } }
Compiling the CSS files in TravisLight is a two-step action. First, all images in the CSS are embedded using the grunt-image-embed plugin:
imageEmbed: { application: { src: 'css/application.css', dest: 'dist/application-embed.css', deleteAfterEncoding : false } }
Then, the CSS files are minified using the grunt-contrib-mincss plugin:
mincss: { compress: { files: { 'dist/compiled.css': [ 'css/bootstrap.min.css', 'dist/application-embed.css' ] } } }
Now, I just have to compile the HTML to use these compiled JS and CSS files. It’s achieved by using the grunt-targethtml plugin:
targethtml: { dist: { src: 'index.html', dest: 'dist/index.html' } }
Theindex.htmlfile looks like:
<!doctype html> <html lang="en"> ... <body data-api-url="https://api.travis-ci.org"> <!--(if target dist)> <script data-main="compiled" src="js/require.js"></script> <!(endif)--> <!--(if target dummy)><!--> <script data-main="js/main" src="components/requirejs/require.js"></script> <!--<!(endif)--> </body> </html>
Last but not the least, the grunt-contrib-copy plugin is the one I used to copy some files to thedist/folder:
copy: { dist: { files: { 'dist/js/require.js': 'components/requirejs/require.js' } } }
Runninggrunt packageperforms all these tasks. See the TravisLight’s grunt.js file for more details, especially the aliases.
At this moment, I had a JavaScript application that worked for me™. So, I looked at some JavaScript testing libraries. I already knew QUnit but I wanted to use something different so I gave a try to Mocha and Chai.
In the JavaScript world, there are plenty testing libraries such as QUnit, Mocha, Jasmine, Chai, Sinon.js, Expect.js, Should.js, and a lot more.
I tried Mocha and Chai. These libraries can be installed using NPM, the Node.js package manager. NPM needs apackage.jsonfile with the list of the project’s dependencies, and thedevdependencies:
{ "name": "TravisLight", "version": "0.0.1", "dependencies": { }, "devDependencies": { "mocha": "~1.7.4", "chai": "~1.4.0" } }
Runningnpm installinstalls both Mocha and Chai in thenode_modules/directory.
Now, you need atest/index.htmlfile to run the test suite in a browser:
<html> <head> <meta charset="utf-8"> <title>TravisLight Test Suite</title> <link rel="stylesheet" href="../node_modules/mocha/mocha.css" /> </head> <body> <div id="mocha"></div> <script src="../node_modules/chai/chai.js"></script> <script src="../node_modules/mocha/mocha.js"></script> <script src="../components/jquery/jquery.min.js"></script> <script src="../components/requirejs/require.js"></script> <script src="setup.js"></script> <script> require( [ '../test/router.test', ], function () { mocha.run(); } ); </script> </body> </html>
First, Mocha and Chai are loaded, followed by jQuery and RequireJS. Then, asetup.jsfile is loaded. It contains the Mocha and RequireJS configurations, and two global variablesassertandexpectthat will be used in the test files:
var assert = chai.assert, expect = chai.expect; mocha.setup({ ui: 'bdd' }); require.config({ baseUrl: '../js/', ... });
I decided to follow the BDD style, but it’s just a matter of taste. Here is an example of test file for the TravisLight’srouter:
define( [ 'router' ], function (router) { "use script"; describe('router', function () { it('should be an instance of Backbone.Router', function () { expect(router).to.be.an.instanceOf(Backbone.Router); }); it('should have a routes property', function () { expect(router.routes).to.be.an('object'); }); }); } );
You can look at the test/directory for more information.
Achievement unlocked! I wrote a JavaScript application that is tested.
I am a big fan of Travis-CI, and I wanted to put TravisLight on it. Thanks to Grunt, it couldn’t be easier!
The grunt-mocha plugin allows to use Mocha and PhantomJS to run a test suite. Here is the TravisLight’s configuration for this plugin:
mocha: { all: [ 'test/index.html' ] }
A simplegrunt mocharuns the test suite using PhantomJS:
$ grunt mocha Running "mocha:all" (mocha) task Testing index.html...................OK >> 19 assertions passed (0.14s) Done, without errors.
Not bad. However, Travis-CI needs to be configured using a.travis.ymlfile. JavaScript projects have to use thenode_jsenvironment on Travis-CI, and the application requires a set of libraries installed through Bower:
language: node_js node_js: - 0.8 before_script: - export PATH=$PATH:`npm bin` - bower install
Travis-CI will runnpm installfirst, and thennpm test. This second command has to be configured in the TravisLight’spackage.json:
{ ... "scripts": { "test": "./node_modules/grunt/bin/grunt test" } }
I really enjoyed working as a frontend developer, and I am in love with the JavaScript community. Nowadays, there are a lot of awesome libraries and frameworks, and I won’t have enough time to try them all.
I first named this blog post JavaScript from the trenches, as I decided to learn everything I knew about JavaScript again. I never considered myself a frontend developer, or a JavaScript developer. I too often meet people that think JavaScript/CSS languages aren’t worth learning as they think these languages are dead simple. They are on the wrong path, I have huge respect for the frontend guys I know, the real ones.
Generally speaking, I think working on frontend applications changed my mind regarding APIs. Also, working on a real project, even a small one like TravisLight, allows you to understand things faster than ever.
By the way, if you found a typo, please fork and edit this post. Thank you so much!评论删除后,数据将无法恢复
评论(36)