00:00:17.730
Good morning, everybody! That was an excellent talk we just saw from Brandon. Happy Friday!
00:00:22.990
It's been a long conference, and thanks for being here. A Friday hug to you all.
00:00:28.480
This talk is titled 'The Rails of JavaScript Won't Be a Framework.' A slightly less provocative version of that title could be 'The Rails of JavaScript Will Be More Than Just a Framework.' My name is Justin.
00:00:40.809
We are not going to have time for questions afterward as it's going to be a very fast-paced, talky slide show. So please tweet me questions, feedback, or praise at @Searls. Critical feedback is always welcome at [email protected]. This talk is about three of my favorite things: cupcakes, the planet Earth, and monolithic application architecture.
00:00:58.150
Imagine you own a bakery, and a customer walks in wanting something sweet. You bake them a beautiful cupcake. They taste it and say, 'This is really good, but I would like a bit more sweetness and maybe a little crunch.' So you add some sprinkles on top.
00:01:17.140
The customer enjoys the cupcake but then insists they actually want something with hot fruit filling. In your mind, you realize that what they truly wanted was a fresh-baked pie. So you throw away the cupcake and make them a pie. That's not a mistake if it happens once, but if your workflow as a baker is to believe that everyone wants a cupcake, only to throw it away repeatedly to bake something else, that's a real problem for your business.
00:01:39.670
Now, consider software. If a customer walks in and says, 'I need a web application,' and you respond, 'Great! What's the name?' so you can type 'rails new' and build a little graph, the customer might then say, 'This graph is great, but I need zooms and filters.' You think, 'Sure, I can sprinkle some JavaScript on top,' but they might then want to load all the data at once so users can see absolutely everything at a glance.
00:02:07.479
As a developer, you might think, 'God dammit,' because there's no logical path from that request back to what they really wanted, which was a fat client JavaScript application. Rails could still be involved, providing API services, but it is not at the center of the application. The monolithic approach doesn’t work.
00:02:30.170
It’s an honest mistake if it occurs once, but if your workflow is to always assume that Rails is the solution to every single web application, only to realize later that you've built a gigantic mess with JavaScript, that’s a problem. I believe a lot of Rails developers fall into this trap because Rails is too convenient. When you are a Ruby developer, having all these great tools at your disposal is amazing.
00:03:07.390
With our convention-based framework, it’s simple to add a gem—maybe just a couple of lines—and gain great behavior quickly. But when you ask Ruby developers about their favorite client-side tools, they usually struggle to find any. Nobody hates JavaScript more than Rubyists; they often can’t think of any good tools.
00:03:24.320
Of course, there are plenty of client-side tools available. This is their reputation: they're jagged, rusty, and terrible. Whenever new stories emerge about tools, we have to decide where the best place for things to live is. If a user brings me a user interface card, it may be that the best place for it to live is in the browser.
00:03:47.980
However, the next thing I ask when I get a new card is: what's the easiest way for me to build this? How can I take the least time and get to market quickly? Because Rails is so convenient, the answer is often Rails. Even though the best place for the code to live might be on the front-end, I am incentivized to solve client-side problems on the server side, which can lead to unhealthy extremes.
00:04:18.769
So, I have a provocative statement to share with you: non-Rubyists write better JavaScript. I attended my first .NET conference last year in Sofia, Bulgaria, and I was blown away by how much we were speaking the same language. We were discussing great, brand-new Node.js-based tooling, and everyone was excited about Angular, even Ember.
00:04:33.170
What I expected from .NET was crusty, but what I found was that because .NET wasn't incredibly awesome, they didn't face the same moral hazard. They were willing to solve problems in the right place, and I recall my own experience before Rails. Before 2005, I was working on projects with other tech stacks where I actually quite enjoyed JavaScript.
00:05:04.850
Even though we can have an ongoing discussion about whether JavaScript is a terrible language, I will say that yes, it definitely has its flaws. I often find that the problems I’ve had with JavaScript have little to do with the language itself and more to do with the tooling, the ecosystem, and the community.
00:05:29.570
I challenge you to reconsider what you believe about the language being at fault after this talk. Let's talk about the planet Earth. I love Ruby and especially the Ruby community because they changed the world of web application development. If you were to chart all the great new tools released for the web over time starting in 2005, you’d find fantastic gems that became the foundation for Ruby on Rails in this community.
00:06:03.020
Over time, tools like Haml, Sass, and others have emerged, enabling us to build better web applications. RubyGems developed into a mature marketplace of resources that help us write better code. However, around 2012, I started noticing that when new features came out for something like WebKit, they weren't immediately followed by new gems to exploit them.
00:06:29.320
Instead, I saw JavaScript tooling written in JavaScript on Node start to pop up. By 2013, it really seemed to take off, and by 2014, many Rubyists seemed to harbor a latent fear that JavaScript would devour the planet Earth. I'm here to tell you that it probably will.
00:06:56.790
If you were to assess the tool ecosystems, you’d find that Ruby’s ecosystem is mature but crowded. There's not much room for growth because everyone already has tools they love. On the other hand, Node's ecosystem is immature yet innovative, pushing out new tools rapidly.
00:07:20.819
It can be frustrating, but it’s great because once a new feature hits a browser, there’s a tool to support it. Yes, it drives me nuts when I run 'npm install,' and by the time it finishes, a couple of those dependencies have updates, but that's what I loved about Ruby in 2006 and 2007.
00:07:39.660
Tool authors are not immune to trends. I read a lot of open-source tools and want to go where people are. Tool authors gravitate toward the JavaScript universe because it encompasses around seven billion developers, whereas Ruby’s universe is in the tens of thousands. Admittedly, this perspective has its flaws.
00:08:00.480
Tools must address the problems of their day. For instance, a gem written in 2008 will address problems that were relevant then, not in 2014. A tool created in 2014 should be relevant today. Thus, tools in Node may offer better solutions to current web challenges.
00:08:20.700
This reality is maddening for those who insist on using Rails for absolutely everything. Speaking of Rails, let's discuss monolithic application architecture. Rails won the battle in web application frameworks, coming in with many compelling advantages.
00:08:46.740
All other frameworks have adopted great ideas from Rails, but we often overlook asking which applications Rails truly suits. Is it that Rails won for all web applications, or is there a subset of web applications that fit Rails better than others? DHH remarked last year that good frameworks are extractions, not inventions.
00:09:12.060
These frameworks are extracted from real applications, not just invented. When you look at Rails, you can see that Basecamp created it and extracted its effective components, which are relevant to many web applications: URL routing, model behavior, validation, and database persistence.
00:09:37.260
Those ancillary concerns are the things you want to avoid reinventing, like mailers. Meanwhile, all these JavaScript alternatives serve a similar purpose—providing avenues to sprinkle JavaScript on top, like Ajax tags or TurboLinks.
00:09:57.200
It’s not that these alternatives are bad; it’s simply that they address problems that modern applications face differently than JavaScript applications do.
00:10:25.900
If you consider Basecamp's application flow, it follows a traditional web workflow where you start a page, click on something to load another page, and so on. This multi-step process once accounted for nearly 100 percent of web applications but has significantly declined. If your app doesn’t map one-on-one to CRUD in a database and just act as an interface for users, it may not be a good fit for Rails.
00:10:46.530
Yesterday, Sandi Metz made the comment that there are Rails apps and then there are apps that use Rails. I've found that more and more of the applications I create are not directly utilizing Rails' front-end aspects.
00:11:07.800
Rails encourages an HTML user interface in the front end because that’s what Basecamp required. I mean that when you write HTML markup—like an anchor tag or a form action—you are specifying what the user interface looks like, but you're not actually programming the UI. It's the browser that determines how to render a link or what to do when it’s clicked, and so forth.
00:11:35.790
When you're building a JavaScript application with the browser as your runtime, though, the activity becomes fundamentally different. You're responsible for figuring out where in the DOM to render elements and binding to user events to take actions.
00:12:04.290
These two tasks involve more complexity. I believe our tools reveal biases based on how they lay out files. A naive Rails app might exemplify MVC architecture, strongly signaling server-side, but in reality, one of the corners has a ghetto labeled 'assets,' with a directory terribly named 'JavaScripts,' and a single large file of spaghetti code.
00:12:31.590
Therefore, many developers recognize that writing structured JavaScript is essential. However, we often end up combining an HTML UI with a JavaScript UI. You might notice that there's an MVC architecture on both the back and front end, complicating things.
00:13:06.510
This duplication of back-end and front-end concerns raises the question of the necessity of backend views if we're striving for a full-fledged fat client JavaScript application. Typically, the views provided by Rails become less useful, and we resort to using only a JSON API and a deeply nested JavaScript UI.
00:13:37.170
At this point, if a newcomer arrives on the project and asks, 'What exactly is that thing?' I would call it a vestigial appendage, as it can only be explained in terms of the past.
00:14:06.630
Building a monolithic application upfront means that as it expands, eventually you won't be able to fit it all in your head easily, which leads to excessive page thrashing. This can be a dangerous scenario, as you might find yourself relying on testing to cover you.
00:14:31.860
However, if you can identify common concerns and separate your application logically, you may end up with a front-end app and a back-end app. Even as complexity increases, their clear separation allows for better management.
00:14:57.370
Relatedly, I want to state that late extraction costs more than early abstraction. I appreciate Sandi's insights into bad abstractions that need refactoring, but if we revisit the same project multiple times, I would prefer to abstract early.
00:15:22.580
Now, let’s talk about yarn. Imagine you have two balls of yarn and wish you had a single, beautifully tangled ball of yarn instead. While creating a big knot of yarn is easy due to the laws of entropy, untangling that knot into nice balls is quite challenging.
00:15:44.910
This notion illustrates that late extractions and refactorings can be more difficult and costly than recognizing you need distinct parts from the beginning.
00:16:07.860
Returning to the two-step process I've observed in many Rails applications, you get a JSON API while also maintaining the JavaScript infrastructure. While it may not be problematic at first, it raises concerns.
00:16:29.490
For instance, template rendering might involve inserting script tags on the page, resulting in data being sneaked in rather than utilizing the proper API to feed data into the JavaScript application.
00:16:54.680
This situation clearly indicates that your yarn is tangled, leading to misleading assumptions about your application's API.
00:17:02.310
It's easy to cheat—it’s tempting to cut corners, especially with poor tooling. This has become my objective over the last four years in my open-source contributions.
00:17:25.469
At Test Double, we aim to make JavaScript apps as user-friendly as Rails. Think about the responsibilities that Rails encapsulates: application framework, conventions, configurations, and build automation.
00:17:49.720
If I had to grade them individually, I'd give Rails a B-minus for its application framework. I loved it initially, but I've found that over time, it promotes practices that can be problematic. Its conventions and configurations are excellent; I appreciate how newcomers can quickly adapt because of community knowledge and sensible defaults.
00:18:14.670
However, I feel Rails' build automation has stagnated. While it was fantastic in 2005, I haven't witnessed remarkable advancements since.
00:18:40.889
What I want to discuss today is conventions and configurations and how they can be enhanced in JavaScript tooling. It's essential for newcomers to Rails to understand these as separate problems.
00:19:04.640
JavaScript application frameworks proliferate everywhere. If I decide to tackle that middleware challenge by creating another app framework, I would have to compete against all the existing frameworks.
00:19:21.099
I'd rather develop tools that are framework-agnostic, allowing anyone to use them, regardless of their chosen framework.
00:19:34.107
Regarding build automation, I believe the community is already shifting towards Node.js. As soon as significant events occur, great tools seem to emerge in Node.js first.
00:19:50.890
I want to play a role in bridging conventions and configurations, which is why we built Lineman. Just like a lineman on a railroad, you can find Lineman on Twitter and install it via npm.
00:20:05.000
You can quickly create a new app, much like in Rails, by running 'lineman new app.' This generates files stripped down to their essentials and highlights prevailing biases.
00:20:21.720
You will have an app directory for CSS, images, JavaScript, backend-rendered pages, templates, and many configuration files to assist in testing.
00:20:44.440
While it’s great to have bootstrap for starting out, our goal is to maintain consistency across projects, promote the sharing of experiences, and minimize duplication in setup.
00:21:08.440
One significant aspect of this is our productivity workflow. I want to write some code and have it automatically compile upon save, along with concatenation, resulting in a rapid feedback loop of less than 100 milliseconds.
00:21:31.580
In the Lineman environment, we achieve this with a command called 'lineman run.' This initiates a build process and continues to monitor for file changes, allowing instant reloading on server-side.
00:21:55.130
It's straightforward; after making a small change, simply refresh the page to see updates. This applies even to larger applications, where it scales effectively.
00:22:19.470
Command-driven development isn't the only focus; I also prioritize writing tests. When engaging in test-driven development, I want that feedback process to be seamless.
00:22:42.390
Lineman comes packaged with an interactive test runner called Karma. You open a second shell and run 'lineman spec,' launching Chrome to execute tests interactively.
00:23:06.240
You can adjust the functionality, save your work, and quickly debug errors since everything runs directly in the browser.
00:23:27.490
In addition to the interactive setup, we also offer a robust continuous integration (CI) process. You can exit the test runner and run 'lineman spec CI,' which executes everything within PhantomJS.
00:23:50.830
Every Lineman project auto-generates a Travis configuration file when you initialize it, making it easy to set up with GitHub.
00:24:12.470
The deployment story is simplified as well; because Lineman operates as a static asset-generating tool, it can easily integrate with servers that host static files.
00:24:37.530
Simply run 'lineman build,' and you'll receive a directory filled with an HTML file referencing your CSS and JavaScript files, all of which have been concatenated and minified ready for deployment.
00:25:00.120
There's even an easy option for asset fingerprinting, making it convenient when deploying CDN-like services. The final output is a directory of files that any developer can easily understand.
00:25:24.200
Pushing to Heroku is just as simple. We host most of our Test Double projects on Heroku, using a customized buildpack. You push your code, it builds using Node.js, and runs statically without Node at runtime.
00:25:47.920
Additionally, we offer a plethora of starter projects to help newcomers get acquainted quickly, whether they want to dive into Angular, Backbone, or Ember.
00:26:09.650
Just clone our example project, and you'll find included code that incorporates all essential elements to help you hit the ground running.
00:26:27.800
Lineman is even versatile enough that we utilize it to build our JavaScript libraries and blogs as well. This flexibility contributes to its appeal for various project types.
00:26:45.460
Let’s return to the planet Earth concept. We've adopted tools like Grunt, which is an expansive build tool for task definition, among various other competitors like Gulp and Broccoli.
00:27:03.080
We primarily use Grunt to access remarkable community resources. Many of the tasks included in Lineman come pre-packaged, making it simple to bring in new functionality.
00:27:19.760
Lineman is designed to be extremely extensible. We have a plugin system centered around this mental model, allowing you to rapidly integrate functionality.
00:27:40.320
To utilize this, simply save it via npm, and after you run 'lineman run,' it will recognize the change within your package.json file and apply it seamlessly. There's no additional configuration required.
00:27:57.390
This automated process even generates Bower.json on its own if necessary, taking some of the burden off developers.
00:28:15.420
Deep down, Lineman integrates various tasks into its ecosystem, allowing the tough work of dependency management to happen under the hood.
00:28:31.770
The approach with Lineman is effectively boxed; while you might use a lineman Bower plugin within your application, you can also have other plugins like lineman ember for specific templating needs.
00:28:49.040
We're thrilled that Rackspace has recently adopted Lineman for its development purposes, encouraging their team to create a meta-plugin that bundles various plugins together.
00:29:05.440
This meta-plugin can house as many plugins as desired at the right versions, pooling together configurations to avoid redundant setups across teams.
00:29:24.980
Returning to the topic of monolithic application architecture, I’ve illustrated a need to separate applications into front-end and back-end and want to further clarify the benefits of doing so.
00:29:43.380
Whenever a client-server relationship arises, one of the initial points raised is about developing each end without needing to maintain constant synchronization.
00:30:03.640
Our platform allows for faster development cycles, with the front end incorporating stubs for routes not yet available on the back end. Lineman simplifies this with API stubbing, ensuring real-time prototyping.
00:30:22.680
Through Lineman, we can define routes in a straightforward Express application, easily returning specific stubs while keeping everything functioning seamlessly.
00:30:40.180
This brings an efficiency to our processes, significantly enhancing our workflow compared to traditional documentation methods by creating a living document.
00:31:06.000
In one project, I encountered a 30-minute test build, which I managed to reduce to four minutes by separating the app back into front and back components.
00:31:30.670
Surprisingly, when everything was pulled together, the lowered complexity resulted in a total build time of just 10 minutes. This shows that even as logical complexity increases, the response time can improve.
00:31:51.680
This also creates opportunities for microservices to emerge efficiently, having no doubt that we can leverage our expertise in both front-end and back-end development.
00:32:08.680
Keep in mind, this is not a front-end versus Rails standoff. We embrace Rails in our services in conjunction with Lineman, and the two work together harmoniously.
00:32:26.890
We offer a gem called 'rails-lineman' and an associated plugin, 'lineman-rails,' which automatically configures your environment and streamlines the development process.
00:32:47.560
You can discover more at linemanjs.com/rails.html, and our documentation features live coding examples and guides for setting up projects.
00:33:09.370
I want to thank my friend Marissa Heil for her fantastic visual design work for this presentation. If these challenges are new or complicated for your team, reach out! We’re eager to collaborate and provide assistance.
00:33:25.230
Lastly, like everyone else at RailsConf, we’re hiring. Just email [email protected], and we’ll respond promptly.
00:33:30.990
A couple of my colleagues, Todd Kaufman and Zach Briggs, are conducting a workshop this afternoon on JavaScript testing and will likely be using Lineman.
00:33:42.660
Thank you all for your time! Reach out; I’d love to hear from you. It was an absolute honor and privilege to speak to you today.