0% found this document useful (0 votes)
4 views7 pages

Open Source JavaScript Toolchain Guide

The document discusses the author's experience developing an open source Javascript utility called Instant Hangouts. It describes the requirements of the project including revision control, dependency management, a development server, automatic versioning, code isolation at runtime and visibility during testing, and automatic testing. It then details how the author met each requirement using common open source tools like Git, Node.js, npm, and Express.js to build out the project's toolchain and development environment.

Uploaded by

sonurehal
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views7 pages

Open Source JavaScript Toolchain Guide

The document discusses the author's experience developing an open source Javascript utility called Instant Hangouts. It describes the requirements of the project including revision control, dependency management, a development server, automatic versioning, code isolation at runtime and visibility during testing, and automatic testing. It then details how the author met each requirement using common open source tools like Git, Node.js, npm, and Express.js to build out the project's toolchain and development environment.

Uploaded by

sonurehal
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

7/20/2015

OpenSourceJavascriptDevelopment

OpenSourceJavascriptDevelopment

25thJanuary2014

[Link],butonethingthatsbeen
[Link]
when I got a chance to write a small standalone open source Javascript utility
[[Link]
You

can

read

all

about

the

utility,

Instant

Hangouts, in my previous post


[[Link] .Briefly,ifyouwantyourusersto
beabletotalktoeachotherfacetofaceaboutawebpage,youcaninserttwolinesofHTMLandgeta
Google+ Hangout specific to that page. The project is very simple its just a shim around the existing
Google+HangoutButtonAPIbutitgavemeachancetogetbackuptodateonJavascripttooling.
[Link],itsanaccountofwhatIfound
thatIwroteontheoffchancethatitmightsaveyousometimeifyourenewtoJavascripttoolchains.

Requirements
Ineededmytoolchaintogivemesixthings:
1. Revision control. This frees you to mess up. Messing up is the hearts blood of software

development.
2. [Link],Iwantedpinnedversionsofall
[Link],[Link]
will behave, so you spend all your time dealing with integration problems rather than shipping your
[Link].
3. [Link]
the requesting server, so viewing my code locally in my browser via file:// was out. Also, my
userswillbeusingrealservers,andIwantmydevenvironmenttobeasclosetotheirsaspossibleso
Icanminimizethechancemycodeworksformebutnotthem.
4. [Link].
5. Codeisolationatruntime,[Link]
able to inspect your code for debugging. But at runtime you cant expose all your symbols because
Javascript doesnt have namespaces and collisions will break your code (and everyone elses) in
entertainingandnovelways.
6. [Link],soIliketohave
tests from the start. Even if theyre not perfectly comprehensive, tests give you the confidence you
needtodealwithcodechurnovertime,andtheyforceyoutouseyourownAPIsinwaysthatimprove
designearlyinyourproductslifecyclewhenchangeischeap.
My naive expectation was that these would all be solved problems. And they were, more or less. The
[Link]
needtocobblethesesolutionstogetherintoatoolchain,andeachtimeyouaddanewutilitythespaceof
whatcangowrongexpandsgeometrically.
Icallthistheprojectorproblem,[Link],
as everybody does. And at those meetings, someone invariably wanted to present something on their
[Link],andeveryoneknew
how to use the projector, but the minute they plugged the laptop into the projector things fell apart in
[Link]

1/7

7/20/2015

OpenSourceJavascriptDevelopment

[Link]
theprojector,[Link]
wrongresolution?Orthecableisloose?Oryoudidnthittherightbuttoninyourpresentationsoftware?
Maybe.
Theproblemisthatthetotalcomplexityofanyintegrationistheproductofthecomplexityoftheindividual
parts. This scales up faster than the expertise of whoever is dealing with the integration, so it was no
surprise that I ended up burning more time on my toolchain than on writing my small utility. Heres how
thingsendedup.

Revisioncontrol
Solvedwithgit[[Link] andGitHub[[Link] .gitisadistributedversioncontrolsystem
thatsbasicallybecomethedefactostandardfordevelopmentintheopensourceworldandinsidemany
[Link],andisenoughofastandardthataprogrammersGitHubprofile
[Link]
[Link].
There are lots of ways to install git on your system [[Link] .
Picktheonethatsrightforyou.

Dependencymanagement
Solved with [Link] [[Link] and npm [[Link] , which come together. [Link] is a
[Link],you
write a [Link] [[Link] file that
describes your project. Its just a JSON object literal. Its dependencies field lets you specify your
runtimedependencies,anditsdevDependenciesfieldletsyouspecifyyourdevelopmentdependencies.
[Link][[Link] .Picktheone
thatsrightforyou.
Oncethatsdone,youcangrabInstantHangoutswith
$gitclone[Link]
andinstalldependencieswith
$npminstall
Asidebaraboutruntimedependencies:
Youvegottwochoices:packageyourdependenciesinyourproject,[Link]
[Link]
[Link],theyreset.
[Link]

2/7

7/20/2015

OpenSourceJavascriptDevelopment

The latter gives better performance. Browsers cache the scripts they load. If two projects both load a
commonscript(say,jQuery [[Link] )itsreallywastefulforboththoseprojectstoforceusersto
[Link],itsbetterforeachofthoseprojectstoloadthe
commonscriptfromastandardlocationsobrowsercachingwillkickinonallrequestsforitpastthefirst.
Nowthatcontentdeliverynetworks [[Link] (CDNs)arecommon,
its good to load your runtime dependencies from them whenever you can. Thats what we do with our
dependencyontheGoogleHangoutButtonAPI.
Apartfromthatlibrary,[Link]
few DOM manipulation and functional programming helpers so we can avoid loading in jQuery or
[Link] [[Link] . While the world really doesnt need another Javascript
implementation of filter(), a few hours researching Javascript module loaders like [Link]
[[Link] convincedmethatthesesmallrepetitionswerecheapertowriteandfastertoexecute
thanbringinginhelperlibrariesforatinyhandfulofcallsites.
[Link]
semantic versioning [[Link] . Developers can install these dependencies
[Link],onceadeveloper
[Link].

Developmentserver
Forsimplescripts,loadingofflocaldiskviaabrowserthatsupports[Link]
[Link],so
weneedalocaldevelopmentserver.
[Link],sowealsouseitforourdevelopmentserverto
[Link]
and server implementations in the same language, which likewise decreases complexity of the project
overall.
Ourserverlivesinscripts/[Link] [[Link]
,andyoucanlaunchitwith
$nodescripts/[Link]
It serves on port 8080. For Instant Hangouts youll want to use your hostname rather than localhost
[Link],youcanloadthedev
serverfrommultiplemachinesanddoamanualendtoendtestbyjoiningtheresultingHangoutsfromtwo
differentGoogleaccounts.
Theserverimplementationissimple:
[Link]

3/7

7/20/2015

OpenSourceJavascriptDevelopment

//Loaddependencies:
//[Link].
//pathisforlocalfilesystemoperations.
varexpress=require('express')
varpath=require('path')
varapp=express()
//LogrequeststoSTDOUT.
[Link]([Link]())
//Bindrequestsfor*.jstofilesintheprojectroot.
//ThisservesourcompiledJS,notthefilesinsrc/.
[Link](/.js$/,function(request,response){
[Link]([Link]([Link](1)))
})
//[Link].
//[Link].
//ThisletsussetanypathcomponentwelikeintheURL,
//allowingustotestrooms(whichusetheURLintheirkey).
[Link]('*',function(request,response){
[Link]([Link]('[Link]'))
})
//Bindtheservertoport8080.
[Link](8080)
DuringdevelopmentIlaunchtheserverinaterminaltabsoIcanwatchthelogsgoby.

Automaticversioning
Idontexpectthisprojecttohavelotsofchurn,butitsalwaysimportanttomakesurethatyouhavean
[Link],thatmeansmakingsureusersloadanexplicit
versionoftheInstantHangoutsscript.
We use [Link] [[Link] to set the
version, then read this value when compiling the scripts our users load. These compiled files live in the
projectrootandarestrictlyadditive:everytimetheresanewversion,[Link]
[Link]
fromaCDNandpeoplecopyandpastespecificURLsintotheirHTML.

Codeisolationatruntime,andvisibilityattesttime
[Link]
youre restricted to blackbox integration tests. Since Javascript has no namespaces, though, you dont
wanttostickallofyoursymbolsonwindowbecausetheycouldcollidewithcodethatexecutesbeforeor
[Link].
The

usual

technique

for

solving

this

the Javascript module pattern


[[Link] . This is actually a family of patterns
[Link],wecanuse
thesimplestform,whichiswrappingallourcodeinananonymousclosure:
[Link]

problem

is

4/7

7/20/2015

OpenSourceJavascriptDevelopment

(function(){
//Ourcodehere.
}())
Sinceallourcodelivesinsidethefunctionsscope,noneofoursymbolsarevisibleoutsidetheclosure.
Notethelastline:wereinvokingthefunction,soallourcoderunswhenthefileisloaded.
[Link](waitforit!)it
encapsulates our code. Without exporting symbols we cant directly inspect the state or invoke the
[Link]?
Our solution is to have slightly different configurations at test time and in production. This is somewhat
heretical since any skew between test and prod keeps you from accurately testing how your code will
behave in the real world. So its important to minimize the skew and have a solid understanding of the
behaviorsitcandistort.
Inoursource files [[Link] , we dont
[Link],allthetop
[Link]
our tests as if they were defined in the test source files [[Link]
hangouts/blob/master/test/[Link]] themselves. If we had multiple source files and needed
encapsulation within our project to manage its internal complexity, this approach would not be sufficient.
Foraprojectthissimple,itworkswellenough.
At runtime we dont load the source files we load processed [[Link]
hangouts/blob/master/[Link]]

versions
[[Link]
hangouts/blob/master/[Link]] [Link]
processedfiles,wewrapourcodeinaclosuretoencapsulateit.
WeuseGrunt[[Link] ,aJavascriptautomatictaskrunner,togeneratetheseprocessedfilesin
[Link]:
instanthangouts<version>.js
instanthangouts<version>.[Link]
Grunt is configured by [Link] [[Link] .
Duringdevelopment,youinvokeitvia
$grunt
from the project root, assuming you have installed it globally. Otherwise, you can invoke it from
./node_modules/gruntcli/bin/grunt.
[Link]
[Link],thatconditionisachangeto
thecontentsofsrc/,test/,[Link].
In

the

filenames

above,

<version>

is

the

version

string

from

[Link]

[[Link]

src/*.js,[Link],andis
[Link],decreasinglatency
inouruserspages.
[Link]

5/7

7/20/2015

OpenSourceJavascriptDevelopment

We want our users to load the minified version by default, which is why the unminified version has the
longer, more obscure name. During development, this unminified version is very helpful because it is
human readable and has line numbers you can refer to in your debugger of choice. By default, the
unminifiedversionisloadedbythedevelopmentserverviathe<script>[Link]. Because
Gruntregeneratesthecompiledfilesonsave,thismeansyoucanmakeachange,savethefile,andsee
[Link]
itself in scripts/[Link] [[Link] require a
serverrestart.

Automatictesting
We also want our tests to run automatically whenever the contents of src/, test/, or [Link]
change. We could use Grunt for this, but we can get some really useful features from a dedicated test
runner.
WeuseKarma [[Link] .ThemainbenefitKarmaprovidesoverGruntis
[Link]
attach browsers to its test server [[Link] . Whenever your
testsareexecuted,theyareruninsideeachattachedbrowser,andtheresultsaresenttoyourterminal.
[Link] [[Link]
. In our configuration, we launch and attach Chrome locally. While developing, I run Karma in its own
terminalwith
$karmastart
EverytimeIchangeoneofthewatchedprojectfiles,Igetresultsinmyterminalprettymuchinstantly.
WewriteourtestsusingtheJasmine [[Link] test framework. Karma executes the
[Link]
importantlimitations:werenotsimulatingusersclickingontheHangoutcontrolsandstartingupaHangout.
[Link]
Googleaccounttotestthingsendtoend,andthatmeanswedbetestingGooglescodeinadditiontoour
[Link]:itsalotofwork,anditsofquestionablevaluebecausethatcodeisnt
ourresponsibilityorunderourcontrol.
Instead,webasicallytreatthecontrolslikeablackbox:wetesttomakesuretheyreboxshapedandthe
[Link],forexample,thatwerecreatingthe<script>tagthatloadsthe
GoogleHangoutButtonAPIcorrectly,andthatwereinsertingourrendertargetscorrectly,andthatwere
[Link],
[Link][[Link] fileourdev
serverservesasatestfixture(meaningitgivesustheDOMformanyofourtests).

Conclusion
[Link]
abunchofreallygoodtoolsthatcanmakeourlivesaloteasier,butitalsomeansthatfindingtherighttools
andgettingthemtoworktogethercanbeabitofachallengebecausetheressuchaprofusionofchoice.I
spentabout50%moretimeassemblingmytoolchaincomparedtoactuallywritingprojectcode,whichisnt
[Link],though,[Link]
saveyousometime,too.
Posted25thJanuary2014byjohnmcox
[Link]

6/7

7/20/2015

OpenSourceJavascriptDevelopment

0 Addacomment

Enteryourcomment...

Commentas:

Publish

GoogleAccount

Preview

[Link]

7/7

You might also like