JUSTIN SEARLS: Good morning everybody.
That was an excellent talk that we just
saw from Brandon. Happy Friday.
It's been a long conference.
Thanks for being here. Friday hug to you all.
This, if the house lights were
up I'd take a picture. Yes.
The title of this talk is The Rails of
JavaScript won't be a framework.
And the slightly less
provocative version of that title is, the Rails of
JavaScript will be more than just a framework.
My name is Justin. We're not gonna have time
for questions afterwards. It's gonna be a very, very
fast talk-y slide-decky thing.
So please Tweet me with
questions, feedback, praise is always
welcome, at searls, and
critical feedback is always welcome
at hello at testdouble
dot com.
Let's just talk about three of my favorite things.
One is cupcakes. Two is the planet earth. And
three is monolithic application architecture. So, on cupcakes, say
that you own a bakery and a customer walks
in and they say they want something sweet. So
you bake them up a beautiful cupcake, and they
say hey, you know, this is really good but
I like a little bit more sweetness. Maybe a
little crunch. So you put some sprinkles on top.
The customer is, like, digging the cupcake, but says
you know, on second thought, I really think I
want something like with some hot fruit filling. And
then you just think to yourself as the baker,
ah god damn it. What they really wanted was
a fresh-baked pie.
So you throw away the cupcake and you make
them a pie. And that's an honest mistake if
it happens once. But if your workflow as a
baker is to assume everyone needs a cupcake only
to have to inevitably throw it away and then
bake something else, that's a real problem, you know,
for your business.
So say you own a software studio, and a
customer walks in and says hey, I need a
web application, and so you say, oh great. What's
its name so that I can type rails new.
And you build them a little graph, you know,
you render it on the server and they say,
hey, you know, this graph is great but I
need some zooms and some filters. And so you're
like, hey, you know, I, we can do that.
Sprinkle some JavaScript on top. And then they say,
you know, this is awesome, but let's load all
of the data all at once so that the
user can really, really like just see absolutely everything
at a glance, really dynamically, like an app, you
know? And then you, the developer, are like ah,
god damn it. Cause there's no logical path from
that solution to what they really wanted, which was
a fat-client JavaScript application.
I mean, Rails is probably still involved, providing API
services. But it's not the center of the application.
That monolithic approach doesn't work. And it's an honest
mistake, if it happens once. But if part of
your workflow is to immediately assume that Rails is
the solution to every single web application, and then
you only realize later that you've guilt a gigantic
mess with JavaScript, that's a problem.
The reason that I think that a lot of
web developers fall into this trap is that Rails
is too convenient. When you're a Ruby developer, you
have all these awesome tools right at your disposal.
We've got this great convention-based framework so I can
just add a gem and it, maybe a couple
lines, and then I get all this great behavior
on the cheap. And when we ask Ruby developers
about their favorite client-side tools, they usually come up
empty. Nobody hates JavaScript more than Rubyists.
So they, they, they just can't think of any.
And of course it's not like there's no client-side
tools. I'm just kidding. There are plenty of client-side
tools available to Rubyists. But this is their reputation,
right. They're jagged and rusty and terrible. So, every
time a new story comes down the pike, we
have to make a decision, right. Where's the best
place for this to live? What's the concern here.
If a user brings me a, a user interface
card, it might be that the best place to
write that, the best place for that to live
is in the browser. But the second thing I
ask when I get a new card is like
hey, where's, what'd be the easiest thing for me
to actually do to build this? Take the least
time? Be the quickest to market? And because Rails
is so convenient, the answer is often Rails. So
even though the best place for the code to
live might be the frontend, I'm incentivised to start
solving client-side problems on the server-side, and taken to
an extreme that's really unhealthy.
So I have a provocative statement to make. Non-Rubyists
write better JavaScript. I went to a dot NET
conference, my first dot NET conference, last year in
Sophia, Bulgaria, and I was blown away by how
much we were talking the same language. We were
using great, brand new node.js based tooling. Everyone was
talking about and excited about Angular, even Ember. But
what my expectations were was it's dot NET, this
is crusty, you know. And what I found in
actually talking to people was, because dot net wasn't
so incredibly awesome, they didn't have that same moral
hazard, you know. They were willing to solve the
problem in the right place.
And when I think back over my own experience,
before Rails was easy, for me, whether that was
before 2005 or when I was doing projects in
other tech stacks, JavaScript wasn't hard. You know, I
actually really quite enjoyed JavaScript until I was told,
you know, to hate it.
And granted, we can have a long discussion. We
can have a lot, like, screencast here about why,
is asking, is JavaScript a terrible language? And I
would just like clear the air, right. Yes definitely.
I spend most of my time in JavaScript. I
agree, it is terrible. But I'm careful not to
conflate that with hey, well, is that why writing
JavaScript is terrible? The problems I have always had
with JavaScript have nothing to do with, have nothing
to do with map and parsein and fundamental problems
with the language, because I'm usually working at a
higher level of abstraction, right.
The problems I have with JavaScript are all of
the tooling. The ecosystem. The community. So I, I
challenge you to ask again later if you think
the language is the one at fault. After this
talk, hopefully I'll be able to persuade you a
little bit.
Let's talk about the planet earth. I love Ruby
and I love Ruby mostly for the community. I
love the language, but I love the community, because
they changed the world when it comes to web
application development. If you were to chart all of
the great new tools for the web that have
released over time, starting in 2005, the fantastic gems
that were sort of the foundation for, for, for
Ruby on Rails and this community. Over time, haml,
sass, all of these great extensions. Alternate stacks that
we can have an Omakase and a Prime stack.
Rspec. Cucumber. These great innovations, helping us build better
web applications. The world, Ruby with gems became this
mature market place of free stuff that would help
us write better code.
But then, right around 2012, I started to notice
that when a new feature would come out for,
like, say, webkit, it wasn't immediately followed by gems
that would exploit it. Instead I was finding JavaScript
tooling written in JavaScript on node. And that started
popping up, and in 2013 it really seemed to
take off. And you come into 2014 and a
lot of Rubyists, I think, have this latent fear
that JavaScript is gonna devour planet earth. And I'm
here to tell you that it probably will.
Where the best tools? If you were to ask
yourself this, you can add up a, add up
a bunch of fact values. For example, Ruby's tool
ecosystem, it's mature but it's crowded. That's not a
lot of room for growth because everyone already has
a lot of tools available that they, that they
love. But node's ecosystem, it's immature, right. It's innovative,
because so much new stuff gets pushed up, and
it's frustrating, but it's great, because as soon as
a new feature hits a browser, there's a tool
to exploit it. I mean, granted, I get as
frustrated as anybody else that when I run MPM
install on something, like, by the time the install
finally finishes at least two of those dependencies have
probably had updates pushed.
But that's the fantastic, that's what I loved about
Ruby in 2006 and 2007. And tool authors are
not immune to trends. I read a lot of,
like, open source tools and I want to go
where the people are. I want to go where
I'm gonna have a big impact. And so tool
authors are now gravitating to, to the world of
JavaScript, because the universe of people who have to
deal with JavaScript is about seven billion people, and
the universe of people who have to deal with
Ruby is in the tens of thousands.
Yeah. All seven billion are JavaScript developers. I realize
that's flawed.
Also, tools, they address the problems of their day.
A gem that was written in 2008 was written
to solve problems that person was facing in 2008.
Not 2014. A tool that was written in 2014
surely must be useful in 2014, and so it's
just a better fit for the web as it
exists today. You add all that up and I,
you know, I really believe that web tools in
node tend to better solve today's problems.
And this is maddening for those who insist on
only using Rails for absolutely everything. But, hey, speaking
of Rails, let's talk about monolithic application architecture.
Rails won the war, right, on web application frameworks.
It came in with a whole bunch of great
reasons that we can go into later about why
it was just the best. It was, it was
fantastic, and all of these frameworks since then have
adopted a ton of great ideas from Rails. But
what we don't often think about when we consider
that phenomenon is to ask ourselves, which war did
Rails win? All web applications? Like, generally? Or is
there some sub-set of applications for the web that
are a better fit for Rails than others?
DHH last year at RailsConf said that good frameworks
are extractions, not inventions. Extracted from real applications and
not just invented. And so when you look at
Rails, obviously the story is that the company Basecamp
made Basecamp and they extracted the good bits, the
common bits that they were seeing across a lot
of their projects into Ruby on Rails.
And those kinds of bits that are common to
many of us, almost all web applications: url routing,
to point you to custom actions that you write.
Modeling behavior of, of the models in your objects,
the validations and all of that at a fundamental
level. Persistence. Storing stuff in a database, querying for
the stuff. The relationships between stuff. Session management and,
in a way that's abstracted from where the session
stuff was stored was hugely convenient, obviously. All of
those ancillary concerns of the wheels that you don't
want to reinvent like mailers. And then there's this
last little bit that's like all these JavaScript alternatives.
Like there's sort of like the, the means by
which to sprinkle JavaScript on top. Like, AJAX erb
tags that dump a whole bunch of JavaScript into
your on-click handlers in your, in your markup, or
later on r.js, or later on unintrusive AJAX erb
tags. Or later on, turbolinks, right. It's not that
those are bad, that those alternatives are bad tools.
It's that they're there to solve, they've been abstracted
from an application that just didn't have the problem
of trying to solve and, and write JavaScript in
the way that I want to write JavaScript.
Because if you consider Basecamp, you start a page.
It's a traditional web workflow. You start on a
page, you click on a thing, you get another
page. It's a, it's a multi-break process, and that
represents a huge proportion of the web. And that
percentage of the web was almost 100% in 2005
but it's much lower now. If your app isn't
a one to one mapping of, like, CRUD in
the database and you're just exposing that as an
interface to users, if there's any layer of indirection
you, it might not be a good fit.
Yesterday, Sandi Metz made the comment, as an aside,
that there are Rails apps and then there are
apps that use Rails. I'm finding that more and
more, the apps that I'm writing are apps that
use Rails. I can love Rails and not necessarily
take advantage or, or really find a lot of
benefit from the front-end aspects.
So Rails promotes an html user interface in the
frontend, cause that's what Basecamp needed. And what I
mean when I say that is you're writing stuff
like html markup. I have an anchor tag here
with a, with a ref and, and content, or
I might have a form action here with, you
know, an input submit, and when you're writing html
like this, it feels like you're making the UI.
But you're not writing, like, UI programming. What this
is is this is the specification of a UI.
The user agent, the browser, is the thing responsible
for figuring out how to render a link and
what to do when you click it. It's how
to render and what to do when, you know,
how to paint a button and so forth.
It's, you're not, you're kind of outsourcing the UI
programming. If you're building an application with the browser
as your runtime, though, I'd call that a JavaScript
UI, and fundamentally the activity is just different and
more complex. You know, you're responsible for finding the
point and the DOM where you want to render
stuff into. Or you're responsible for binding to an
event that the user does something, and then you
need to take some custom action. You're the one
in the driver's seat. They're fundamentally different concerns.
But our tools, I think, file, I like tree,
to tree stuff out, because I think that tools
tend to betray their biases based on the layout
of the files that they give us. You know,
a naive Rails app might look like this, and
it screams MVC and it screams server-side. But, of
course, in reality, one of the kind of, like,
you know, dust-bin corners is that we have this,
this ghetto, right, under assets, and then the most,
you know, unfortunately named directory ever, javascripts, and then
application.js, and it's telling us, all this stuff at
the top - this matters. And this thing at
the bottom, just write one big long bowl of
spaghetti, and it'll work out. And that's how a
lot of people write, you know, JavaScript and Rails
applications, still.
Some people, though, that's not good enough, and so
they, they, they realize that they need to write
more structured JavaScript, and so we end up with
this new thing, like an html UI and a,
and a JavaScript UI combined. And you might notice
a pattern here, right. There is a, a, an
MVC in the back, and then it's also MVC
in the front. It makes command T really difficult,
but it, you know, we see this duplication of
backend concerns and frontend concerns, and there's also this,
this little nit, negging doubt about, do we really
need this views here? Right, if we're building a
full-blown fat-client JavaScript application, the backend views that Rails
provides just are less useful. So those often get
cut out now, and we, we just have sort
of a JSON API in Rails, and then this
deeply-nested JavaScript UI.
And so at this point, if like a new
person comes to your project and they ask, hey,
so what exactly is that thing? Right. I would
call that a vestigial appendage. Because it can only
be explained in terms of the past. You have
to pull up your, you know, your forensics of
like, well, in 2008 we were all, you know,
thinking this and now it's still like this.
What's wrong with that vestigial appendage? Well, what's fundamentally
wrong is that, a fundamental problem in, in programming,
is that when we move way faster when we
can fit the whole application in our head at
once, and when, on day one of any project,
you can fit the whole thing in your head
at once. But on day 1000 of the project
that's probably not gonna be true.
So if you build a monolithic thing up front,
as that app gets bigger, eventually you reach a
point where you can't fit it all in your
head and you start to page, right. Part of
the application that you're working in you can think
of, and then over here you sort of page
out. And if you don't modularize things well, then
that, that, that thrashing is really, really risky. Because
it might mean that, like, I'm in this part
of the app, and I just kind of have
to hope that my tests are gonna cover me.
Although by the time you're this big, your tests
in a typical Rails app are like ten hours
long. So maybe tomorrow you can find out that
it worked.
But if you, via common concerns, and find a
good module point to, to separate on, if you
were to identify that you could have, like, a
frontend app and a backend app, as those two
things grew, even if the net complexity is higher,
at some point they're not gonna fit in your
head either, but the paging story is much nicer.
Because they have a clean, well-defined separate contract. So
the application that you're working in the backend application,
if you have to work in it, you can
work in it, and then when you page out,
it's not thrashing, cause there's a clear, understood contract
between the two.
Relatedly, I like to say that late extraction costs
more than early abstraction. Yesterday, Sandi's talk was great
at telling us about wrong abstractions that have been
found and refactoring away from those, but when we've
seen the same project a dozen different times, I
would much rather extract seldom and, and, and abstract
early, and that's really confusing sounded so I'm gonna
talk about yarn now.
Imagine you have two balls of yarn. If you
decided, like, man, I really just wish instead of
these two ugly balls of yarn, I had a
big know of yarn all tangled together, that's really
easy to do, thanks to the basic laws of
entropy. But if I have a big tangled know
of yarn and decide that I really would love
two nicely-balled, you know, nice balls of yarn, turns
out that's very, very difficult to do. That doesn't
work.
So that's why, what I mean when I say
that late abstraction, all of these, like, fancy refactorings
that we can do, cost a lot more than
just knowing you needed two things in the first
place. So, back to this, this two step that
I see in a lot of Rails applications, where
one project, you've got the JSON API but you
also have all the JavaScript. This isn't problematic until
you consider this kind of stuff. You, you have
a template that renders a script tag at the
top, and then in the erb certain bits of
data are kind of taking this sneaky back door
instead of actually using the, the proper API, to
just dump data into the JavaScript application needs. When
you see this, it really means your yarn is
tangled, right. Even though you think you have separate
things. And your API is a lie. Because it
means that even though your application is mostly using
that API, if somebody were to come and say,
hey, I want to build a mobile app for
your site, they're gonna have to spend a month
figuring out how to get that token, right.
But it's hard not to cheat. And I agree.
It's very, very difficult, especially given what we talked
about earlier, where the tooling is so bad. So
my objective in the last four years of, of,
of my, my open source contributions, and now at
TestDouble, where we spend a lot of our time?
We want to help make JavaScript apps easy. As
easy as Rails.
When you think about Rails and the responsibilities of
Rails, there's really three distinct parts. We have an
application framework. Stuff that we extend - ActionController and
so forth. We have conventions and configurations that are
laid out for us, that we learn through the
community and the documentation. And we have build automation
stuff, like Rails CLI and Rake. And Rails owns
the whole stack.
If I had to grade them separately, I'd say
that Rails as an application framework - when I
first found it, I loved it. But I found
on, like, many year, five year, six year projects,
it encourages a lot of things that problematic. So
maybe I'd give that a B minus, if I
was grading it separately. But the conventions and configurations,
that's awesome. I love that I can hit a
new Rails team's project and, because of the tribal
knowledge that we have as well as the conventions
laid out and the sensible defaults, I can see
how is their app different from the norm really
easily.
Build automation stuff is pretty good. I think it's
gotten a little bit stagnant. Fantastic in 2005 and
I haven't seen a lot of really cool stuff
lately. But it's still solid. What I really want
to talk about today is convention and configuration and
the value that that can bring to our JavaScript
tooling. Also keep in mind that a lot of
people that are new in Rails or have only
ever worked in Rails just see one big things.
They don't see these as separate problems. So if
that's you, try to think about these responsibilities separately,
because I think they can be solved by separate
tools.
For example, in JavaScript, application frameworks are everywhere. If
I decided I wanted to solve that middle problem
by writing another application framework, then I'd have to,
you know, go and popularize it against all the
other application frameworks. I think that they can be
separated. You know, whether I'm writing backbone or Angular
or Ember - lately I've been writing a lot
of Ember and I love it. But every six
months I keep changing my mind. It's a fact.
So, so at this point I just wanna be
like, eh, I want to write awesome tools that
are framework agnostic that anybody can, can exploit.
From the build automation perspective, like I said, the
community is already in node.js. Worldwide. As soon as
stuff is happening, great tools are showing up in
node.js first. I just want to be this little
guy in the middle, right. I want to be
the convention and the configuration, right. And that's why
we built lineman.
Lineman, like a, like a lineman on a railroad,
is on Twitter here, and you can find his
url. And you install him with npm. So you
have node.js install and you can just say npm
install globally lineman, and you create a new app
really easily with the cli, just like Rails. Lineman
new app.
So, here's me typing in lineman new, start a
new project, and I get a little. I get
a handful of commands that I can run. But
first I'm just gonna cd in and I'm gonna
tree out all of the files that I have.
Like I said, it betrays the biases, right. One
way to learn the conventions is see what it
generates. So you can see I have an app
directory with css and images and JavaScript and then
pages that render on the backend and templates on
the front. A handful of configuration files. A whole
bunch of spec helpers to help you test. And
then places for all of your vendored third-party libraries.
And it's convenient, right. It's nice to get that
bootstrap for you. But our goal is to make
it convenient throughout, to switch between projects to reduce
duplication to make things more common across all of
our work.
One aspect of that is our productivity workflow. I
want to be able to write some code, save
the code, have that code automatically compile for me
every time I save. Have it concatenate every time
that I save, and then I want to be
able to hit command r and refresh and play
with it. But I want to be able to
do all of that in less than a hundred
milliseconds, because I want a fast feedback loop so
that I can keep working quickly.
In lineman, we do this with a command called
lineman run. So you say lineman run, it does
a whole bunch of initial build stuff, but then
it just starts watching for file changes. So I
can hit this server, the dev server. It says
Hello, World! I'm gonna make a quick changes, say
Goodbye, World! It's already updated. I refresh the page
and that's that.
Now, this is a simple app, but even on
large apps it scales very well. On our large
applications it's still roughly a hundred milliseconds.
So, this is great. But command-r driven development isn't
the whole story, right. I also like to write
tests, too. Sometimes I'm doing test-driven development. When I
do, I also want the same story to slot
in really nicely with, with tests. And I want
the same feedback cycle to be super duper fast.
Lineman ships with a cool tool called testem, written
by Toby Ho, that's really fantastic. What you do
is you open up another shell, a second shell,
and you run lineman spec. And you get this
interactive test runner, launches Chrome here, and here I'm
running a test already. Gonna just change the spec
to say that I'm specifying that that function returned
Goodbye, World!
Save it off. Got a failure. That quickly. I
can debug cause it's in the browser. I'm just
gonna fix it. Save. And that's it. My tests
are passing. In addition to the interactive runner, we
want a really solid CI story. So you just
quit out of testem with the q key, and
you can type lineman spec ci, and this is
gonna run it all in phantom.js with a nice
reporter output. And every lineman project generates a travis.yml
file when you lineman new. So you literally just
push it to GitHub, and if you use Travis
as your CI service, it's a one button thing
and now you have a CI build for your
JavaScript. Which if we were to ask people to
raise hands, I don't think every hand would go
up if, if I asked if you have one.
The deploy story is similar easy, because since lineman
is just a static asset generating tool, can your
server host static files? Then yeah, you're good. When
you write a lineman build, and then you tree
out its dist directory, which is where it puts
its built artifacts, it looks a little like this
out of the box. You have an html file
that references a css file and a JavaScript file
and both of those have already been concatted and
minified for you and they're ready to deploy.
There's a single flag in the config that you
can set, and then just like Rails, you get
asset fingerprinted that makes it really nice for deploying
when you have a CDN. Everything else that ever
is gonna end up in your dist directory is
gonna be stuff that you added, so it'll be
stuff that you understand. It's a really easy build
story.
Pushing to Heroku is also really easy. We host
most of our testable stuff on Heroku, so we
just set, we wrote a custom buildpack. You set
that up and then you say git push. It'll
build it with node.js, but then at runtime we
don't need it and so it just runs statically
without node.
And we also have a whole bunch of starter
projects to help get people up and running quickly.
Not everyone's just writing vanilla JavaScript, right. We have
some people who want to get started with Angular
quickly, Backbone or Ember. You can just clone and
go. Clone the project and get started. You'll have
a little bit of example code. It's a great
way, if you want to learn Angular or learn
Ember, just to clone our example project, because it'll
build right away. Like, you already know how to
run it.
We also have a, a really cool. It's because
it's all flexible, we also use lineman to build
all of our JavaScript libs, libs that we maintain,
as well as our blog and, and you're free
to use lineman, of course, to, to write a
markdown blog. It's really, really convenient.
So back to planet earth. We're using Grunt. We,
Grunt is a build tool descended from, you know,
a whole bunch of other build tools, that is
used for task definition. There's a lot of different,
there's a lot of competition here right now in
node.js. A lot of people using Gulp. A thing
called Broccoli came out recently. It's really cool. But
what we use Grunt for, primarily, is a place
to get awesome stuff from the community.
All these tasks ship with lineman out of the
box. Or are, and, and so many more are
available. We really, really love that we're able to
so easily pull in new behavior through Grunt in
a consistent manner. Lineman itself is comically extensible. We
have a plugin system that is built a little
bit around this mental model. We'll talk about it
in a second. But it's really easy from a
user's perspective. All you do is save it. npm
install, then you save the, save the dependency. Run,
like, lineman-bower. When you do that, after you run
lineman run, the next time after you save that,
lineman will pick it up from your packaged JSON,
know that it needs to load it, and bower
will be slotted in at the appropriate step into
your build's workflow. No more configuration. It even generates
your bower JSON for you if it's not there.
Cause deep down, there is an npm module out
there, bower, right, published by Twitter, and around it
is the, a, a grunt-bower-task that somebody in the
community published, and then at the top we have
this lineman-bower plugin that we maintain. Bower is the
thing that actually does the thing. That's where most
of the hard work is.
This, this power-task here, from Grunt, it automates the
thing. There's a lot of hard work there, too.
What lineman does is it just knows, given lineman's
conventions, how to configure the thing for you. And
so we have this kind of boxed approached to,
to how we conceptualize plugins.
So you, in your application, you might have a
lineman-bower plugin that you use, but you can also
have a lineman-ember plugin that's gonna handle all your
templates the way that Ember likes to see it.
And recently we, we learned and were really excited
that RackSpace is adopting lineman for its frontend development,
and I encouraged them to write a metaplugin, because
you can have recursively arbitrarily many plugins down the
line. So this plugin here - name it whatever
you want. Maybe your company's stack or something. It
can bundle as many plugins at the appropriate versions
that you want, but you can also override any
of the configurations in those plugins, get them just
how you like. That way you don't have all
this duplicated configuration across all of your team's files,
team's project.
Back to monolithic application architecture, I've painted a picture
where we can separate into two things. But I
want to talk a little bit more about the
benefits of doing that. So say that you have
a client in the server. One of the first
questions that comes up is like, hey, well, how
am I gonna run stuff in development, but it
still needs to see the server? I'm not gonna
build all these extra stubs for my server side.
And we agree. That would be really onerous. So
we built a feature into lineman that we call
API Proxying. Basically, think of the browser hitting lineman,
and maybe we have Sinatra in the backend. The
browser's only gonna know about lineman. It's gonna make
all of its requests to lineman. But whenever they
ask for any API routes that lineman doesn't know
how to respond to, we've got it configured to
call back to Sinatra. Sinatra responds and then lineman
proxies that request back to the browser.
So it's a seamless environment. It's as if you're
developing on one thing at runtime even though the
code has all the benefits of, of, of physical
separation.
It looks a little bit like this. So here
I'm gonna uncomment a little bit of configuration that
we give you. Change the port to 4567, for
Sinatra. My application's real simple. It's just got a
simple route hi. It gets it and then it
paints it onto the screen, whatever the text is.
And my Sinatra app just returns I heart Ruby
at that particular route.
So when I write lineman run, you can see
it, instead of proxying I'm gonna look at Sinatra's
logs. I refresh, and it got the request from
lineman and it returned through the browser. Super easy.
Now there's other cases, too, cause the benefit of
separating frontend and backend, a big part of that
story is that now development of those two things
doesn't have to run in lock step, right. We
can make a little bit of extra progress in
the frontend, maybe do some prototyping. We can have
a separate backend team after we get big. But
a lot of times we have, like, you know,
it being handy to be able to stub stuff
out that doesn't actually exist on the server yet,
so we can get faster feedback cycles while we're
developing our frontend.
And we offered this in lineman with a tool
that we called API stubbing. So same situation. We
have a browser and it's gonna be hitting lineman.
And instead of actually phoning through to Sinatra, we're
gonna kind of stub our a particular route and
prevent Sinatra from getting it. And we're gonna return
that stub back to the browser.
So same, same, same exact code base. We're gonna
go into config slash server.js. This is a, an
express application that's just kind of bundled in. We
can define any route we'd like. We can overwrite
that hi route. And we're gonna, we're gonna troll
our coworkers here by sending that We heart Node
Even More. Sacrilege.
So run lineman. Refresh the page. And now our
stubbing is in place. You can build entire toy
applications inside of that express application. We've had clients
in the past, TestDouble is an agency, and so
we're, we're as consultants. We've had clients in the
past who've asked us, hey just give us the
specifications of the services that you want, and our
specification is a living document of, well, just make
it do this. And it's been a really, really
seamless - it's certainly better than traditional documentation.
Another case that I like a lot is I
had a project once with a thirty-minute long test
build, and I split it up into, I split
the application up into two. A frontend and a
backend, just like we're talking about. Then I went
to recover that new application with tests, and I
found that the frontend tests had a runtime of
only four minutes. That made me very worried about
the state of affairs in the backend. I figured
that might mean that the twenty-six minutes was hiding
there somewhere. But as it turns out, I wrote
that, and that only took four minutes, too.
So then I got really suspicious and I'm like,
I should probably have some smoke test to make
sure that when this is all plugged into, plugged
together correctly, it works. And the smoke test, of
course, when you plug it in both, it's a
little bit slower, and that ran at a whole
two minutes.
So this thirty-minute test suite somehow got reduce to
a ten minute build, even though the next, the
logical and physical complexity of the system increased. And
if you understand how build duration tends to build
super linearly, any savings that you can get upfront
in the beginning are going to mean a big
difference, you're going to get a lot longer runway
and traction out of the build suite in the
far future.
And, additionally, it's habit-forming, right. I mean, having a,
a, there's a lot of operational problems that you
have to solve when you have two different things
to maintain and manage and version, as a deploy
story, two different projects. You can make it simple,
but I mean, once you solve that problem, once,
you can have arbitrarily many microservices popping up.
And if you're viewing the world as going in
that direction, it's a great problem to solve now
with a problem that you already understand really well.
Frontends and backends.
Additionally, this is not a frontend versus Rails talk.
It's an and. We love Rails. We use Rails
all the time for our services. And lineman and
Rails play together really nicely. We've got a gem
called Rails lineman and lineman plugin called lineman-rails. You
install both those things and you just magically, everything
gets auto-configured. And, and your development story is great
and assets precompile is just wrapped with a lineman
build first.
You can learn more about that at linemanjs dot
com dlash rails dot html. And we have this
fantastic little documentation site put together for us by
Derrick Briggs from neo. More recently, you can actually
see me do this myself, live coding, unedited, in
an Ember screencast that I did - how to
get setup, like we would setup a project. And
that's at our blog. It's the current, most recent
article. So just hit the blog dot testdouble dot
com and you'll see the, the embedded screencast.
It's a fantastic tool. We love working with it.
I also, real quickly, I just want to thank
my friend Marissa Hile. She's a visual designer who's
available for contract. She did all of the good
illustrations in this talk. And, and, you know, we'd
love to help you. If these are problems that
are, that are, that are new and hard for
your team, let us know. You know, we are
consultants, and we'd love to like, engage with your
company and, and, and work on great stuff alongside
you, but we'd also just love to answer your
questions, because I think we want to all make
an impact and, and move the conversation forward.
Also, like everyone else at RailsConf, we are hiring.
Just set an email to join at testdouble dot
com and we'll respond to you promptly and have,
start the conversation. Also, a couple of my fellow
double agents, Todd Coffman and Zack Briggs, are giving
a, a workshop this afternoon on JavaScript testing. I
think they'll probably be using lineman. So it might
be a good place to practice both of those
things.
And I want to thank you. You know, please
reach out. I'd love to hear from you. It
was an absolute honor and a privilege to get
to speak to you today. Thank you very much.