Summarized using AI

To a Single Page Web App and Back Again

Nicholas Simmons • June 27, 2014 • Singapore • Talk

In the talk "To a Single Page Web App and Back Again," Nicholas Simmons discusses Shopify's journey with their admin interface, which was originally built as a single page web application (SPA) using their own JavaScript MVC framework, Batman.js. Over time, they reconsidered their approach and opted to transition back to a non-SPA model, culminating in a new hybrid solution, "admin next," which combines aspects of Turbolinks and a lightweight binding system.

Key Points Discussed:
- Initial Motivation: The move to a SPA aimed to create a more dynamic experience and facilitate a shared JSON API for both mobile and web platforms.
- Challenges with Batman.js: Developers faced a steep learning curve, complex documentation, and difficulties with onboarding. This complexity led to frustration among the team and limited widespread adoption of Batman.js during hack days.
- Problem of Business Logic: A significant lesson learned was the importance of minimizing business logic in the client and centralizing it on the server, which helps maintain data consistency and reliability.
- Performance Issues: Users experienced jank during transitions, where certain sections would load asynchronously, resulting in a disjointed user experience. This was primarily attributed to how Batman operated and its rendering approach which required excessive asset loading.
- Reboot to Admin Next: After evaluating the shortcomings of Batman, a decision was made to develop admin next. This new approach aims to be simpler and faster, maintaining some SPA benefits while shifting rendering back to the server.
- Benefits of Admin Next: The prototype has been well-received, with faster load times and reduced complexity in client-side logic. New frameworks are designed to facilitate easier onboarding for new employees at Shopify.

In conclusion, while the initial venture into single page applications was promising, it was ultimately not the right fit for Shopify’s admin interface. Lessons learned emphasize the value of solid documentation, minimizing client-side business logic, and creating systems that are easy to use and maintain, ultimately leading to a successful pivot to a hybrid model. Simmons expresses openness to exploring other JS frameworks in the future, as advancements may address the issues encountered with Batman.js.

To a Single Page Web App and Back Again
Nicholas Simmons • June 27, 2014 • Singapore • Talk

Single page web applications have been all the rage recently. At Shopify, we wanted to make our admin interface a dynamic and fluid experience for our users. We created our own JS MVC framework and used it to rebuild our admin. Now we have decided to change course. What fueled this decision? What lessons have we learned? What worked and what didn’t? This talk will share our experiences, as well as our new hybrid approach: A modified version of Turbolinks combined with a lightweight binding system.

Help us caption & translate this video!

http://amara.org/v/FGY8/

Red Dot Ruby Conference 2014

00:00:20.320 all right now that i've suffered through
00:00:21.760 that um so hi everyone my name is nick
00:00:24.880 simmons
00:00:27.039 and here i'm uh today i'm here to talk
00:00:29.760 to you about uh how shopify we built a
00:00:32.640 single page web app
00:00:34.160 and why in the end we decided to
00:00:37.440 go back to
00:00:39.040 a non-single page while that
00:00:42.640 so before i start i'd like to say uh
00:00:44.800 this is actually my first time speaking
00:00:46.399 at a conference um so it's
00:00:48.719 very exciting for me
00:00:55.039 so it's very exciting and also very
00:00:56.559 terrifying so if i make any mistakes
00:00:58.800 please bear with me
00:01:00.320 um
00:01:02.160 so let's get started
00:01:03.680 uh tell you a little bit more about
00:01:05.280 myself
00:01:07.200 so first of all uh i'm canadian
00:01:11.840 there's some very uh stereotypical
00:01:13.200 canadian things you might have heard of
00:01:14.320 and i would say that i'm very similar to
00:01:16.320 a very stereotypical canadian uh so
00:01:18.560 first of all
00:01:19.680 my favorite sport is hockey uh how many
00:01:22.400 how many people here are hockey fans his
00:01:24.320 hand
00:01:25.439 wow five more people than i expected
00:01:27.439 that's amazing
00:01:28.560 uh
00:01:30.400 second of all um canada's not really
00:01:32.720 that well known for food
00:01:34.560 but
00:01:35.600 maple syrup
00:01:36.960 my absolutely
00:01:38.400 favorite thing to to eat um whenever i
00:01:41.119 have pancakes or waffles if i don't have
00:01:43.439 maple syrup i'm extremely disappointed
00:01:46.399 uh and last of all
00:01:48.079 uh in canada we unfortunately have to do
00:01:50.240 with winter so
00:01:52.079 this is a picture of the city where i
00:01:54.479 live
00:01:55.360 and uh you see those things there on the
00:01:57.520 right those are actually cars
00:02:00.479 so a very important thing when you live
00:02:02.399 in canada is to get underground parking
00:02:04.399 cannot tell you how important that is
00:02:07.680 so the other interesting fact about me
00:02:09.440 is that i actually used to live in
00:02:10.560 singapore um so i was here for about a
00:02:12.640 year and a half
00:02:14.000 and i was working for lucas arts so
00:02:16.560 it was super cool getting to work on
00:02:18.080 star wars stuff living on the other side
00:02:19.760 of the planet getting to travel a lot it
00:02:21.920 was great
00:02:23.360 i was actually a back-end developer for
00:02:24.959 some online games that we were working
00:02:26.640 on unfortunately none of them shipped
00:02:29.360 and there's a good reason for that
00:02:31.360 about six months after i had started at
00:02:33.599 lucas arts
00:02:34.879 we were acquired by disney
00:02:38.239 so
00:02:39.760 you know
00:02:42.080 disney
00:02:48.239 disney seems like a really nice you know
00:02:50.480 family-oriented company and they are uh
00:02:52.560 but they're a little bit ruthless when
00:02:53.599 it comes to the business so when they
00:02:55.280 bought lucas arts or lucasfilm i should
00:02:57.200 say they decided that they were really
00:02:58.800 into the movie idea but not so much into
00:03:00.480 making games
00:03:01.840 so
00:03:02.560 in the end well
00:03:04.800 that was the end of that
00:03:08.640 but it's not all bad news
00:03:10.480 in the end i ended up moving back to
00:03:12.159 canada and i got this awesome gig at
00:03:14.239 shopify so this is basically what i'm
00:03:16.000 doing now
00:03:17.280 i've been in shop 5 for a little over a
00:03:18.800 year
00:03:19.920 and this is actually the first time
00:03:21.920 i started working with ruby and rails so
00:03:23.840 i'm still relatively new to it
00:03:25.920 actually another interesting fact is
00:03:27.120 that it was also the first time i've
00:03:28.159 ever used a mac
00:03:29.440 not programming mac i mean literally
00:03:31.120 using a mac i had no idea how to even
00:03:33.519 install an application
00:03:35.519 but yeah it's been a wild ride and i
00:03:37.360 really loved it
00:03:38.879 so specifically at shopify
00:03:40.799 i'm working on the admin interface
00:03:43.440 so this gives you an idea what it looks
00:03:45.040 like basically it's a pretty large web
00:03:47.920 app
00:03:49.280 there's lots of different sections
00:03:51.120 lots of different configurations that
00:03:52.480 our shop owners can do
00:03:55.280 so it has as i said lots of pages
00:03:58.080 basically all form submissions um and
00:04:00.959 lots and lots of data going on
00:04:04.400 so i'd like to talk a little bit about
00:04:05.519 the evolution of the shopify admin
00:04:09.360 so in the early days
00:04:11.280 the classic version of admin was
00:04:14.560 rails app using some templating with erb
00:04:17.919 and some jquery sprinkled around to do
00:04:20.000 any sort of cool stuff we wanted to do
00:04:21.280 in the clients
00:04:23.120 but a couple years back a decision was
00:04:25.360 made that they wanted to
00:04:27.280 build a single page web app now the
00:04:28.960 original reasoning for that was they
00:04:30.720 were thinking well hey if we could have
00:04:33.520 the same
00:04:34.960 application for both
00:04:37.440 mobile devices and for the web that
00:04:40.080 would be great basically just to
00:04:41.360 abstract
00:04:42.560 abstract the client away from
00:04:44.800 the server and also to be able to build
00:04:47.120 our json api which the time did not
00:04:48.880 exist
00:04:49.840 and just treat the client as another
00:04:52.000 consumer of this api
00:04:54.160 so when they were initially evaluating
00:04:56.000 the js nbc frameworks that existed none
00:04:58.240 of the solutions that were out there at
00:04:59.360 the time really met
00:05:00.960 the needs uh for the team so they
00:05:03.600 decided to build their own
00:05:05.759 and from this uh batman js was created
00:05:10.080 so when we started building admin 2 this
00:05:12.000 was still before my time
00:05:14.720 batman gs was the framework that it was
00:05:17.039 built on top of
00:05:19.360 so we finally released admin 2 in july
00:05:21.520 of last year
00:05:22.840 2013. and funny enough six months after
00:05:26.479 releasing admin 2 we decided that it was
00:05:29.360 time to move away from this framework
00:05:32.160 uh so our new admin is called admin next
00:05:35.039 because i'm getting tired of using
00:05:36.840 numbers um so you might be curious what
00:05:40.160 admin next is about
00:05:41.680 well
00:05:43.199 i'll talk about that soon but when i say
00:05:45.120 soon i'll only briefly mention it in
00:05:46.960 this talk at the end
00:05:48.800 to be honest we're not completely
00:05:50.000 finished with what we're doing
00:05:52.560 and i'd like to make sure that maybe in
00:05:54.000 the future we'll give another talk
00:05:55.759 we'll explain exactly what we've done
00:05:58.319 and
00:05:59.440 hopefully we'll open source it
00:06:04.400 so
00:06:05.199 start my story with uh
00:06:07.440 when i began working at shopify so when
00:06:10.080 i come in um i was sort of interested in
00:06:12.319 the idea of doing a jsnbc app in a
00:06:13.919 single page web app you know it sounded
00:06:15.440 like a really cool thing um really
00:06:17.840 interested in it but i never actually
00:06:19.520 got to work on anything like that before
00:06:21.280 so when i joined shopify batman was
00:06:23.759 basically finished admin 2 was almost
00:06:25.759 out the door
00:06:27.440 and everyone was really excited about
00:06:28.880 this new direction that we were going
00:06:30.639 i mean with this me we had no more full
00:06:32.240 page reloads on paint transitions that's
00:06:34.319 really cool all of our html endpoints
00:06:36.560 that we had in the code were completely
00:06:38.319 removed and we had all of our templates
00:06:40.160 stored in the client
00:06:42.720 json api which was shared between admin
00:06:45.440 as well as any third-party apps
00:06:47.600 so that was cool basically the server no
00:06:49.599 longer cares about any of the ui
00:06:51.039 concerns
00:06:52.160 and the admin api i said it's just
00:06:53.680 another api client great
00:06:56.400 but there's a little problem
00:06:58.880 batman is super hard to use at first i
00:07:02.800 thought it was just me
00:07:04.080 like okay i'm new to this stuff i've
00:07:05.759 never done it before so just there's a
00:07:07.039 learning curve there
00:07:08.720 i'll pick it up eventually
00:07:10.800 but it turned out that a lot of people
00:07:12.000 were having this problem
00:07:14.400 so
00:07:15.280 when i first started
00:07:16.560 at shopify i assumed there would be a
00:07:18.560 certain learning curve and it would look
00:07:19.919 something like this so
00:07:22.160 over time i would slowly pick up more
00:07:23.919 and more of the framework and have an
00:07:25.280 understanding everything works and by
00:07:26.560 the end of it maybe a couple months
00:07:27.759 later i feel like i'm basically an
00:07:29.280 expert
00:07:30.560 unfortunately
00:07:32.000 i found my learning was a little bit
00:07:33.199 like this
00:07:34.639 so it took a lot longer to wrap my head
00:07:36.479 around what was going on
00:07:39.520 so to explain this sort of learning
00:07:41.840 curve
00:07:43.120 initially as most of us do whenever you
00:07:45.280 need to solve a problem you try to look
00:07:46.800 for other examples uh throughout the
00:07:48.560 code base
00:07:50.479 the problem was
00:07:51.759 admin 2 is a pretty large code base so
00:07:54.879 there's a lot of stuff going on
00:07:56.639 because of the complexity of batman of
00:07:58.240 stuff living in multiple places it was
00:08:00.479 really hard to sort of piece everything
00:08:01.840 together and figure out what's going on
00:08:03.440 so the next logical step is all right
00:08:05.120 let's dig into the into the docs so
00:08:07.919 batman docks existed
00:08:10.080 but i would say they were far from
00:08:11.599 complete uh there were many pieces that
00:08:14.240 were missing uh and the most important
00:08:16.240 part was that there wasn't really a good
00:08:17.840 onboarding into batman you couldn't just
00:08:19.840 uh follow a simple tutorial get started
00:08:22.080 and have a batman app up and running
00:08:23.520 very quickly
00:08:26.000 so
00:08:27.360 uh i gathered a little bit from that you
00:08:29.520 know good overviews some of the some of
00:08:31.360 the things were covered so i felt okay i
00:08:33.120 don't have a full understanding but i i
00:08:35.120 think i'm ready to uh to dig back into
00:08:37.200 the admin code
00:08:38.880 and shortly after doing that i started
00:08:40.800 running into those things were
00:08:41.839 undocumented so now i'm kind of stuck
00:08:44.080 what do i do all right well i'm on the
00:08:46.000 admin team obviously there's people on
00:08:47.360 the team that can help me out so i
00:08:49.200 started asking for help
00:08:51.360 problem was
00:08:52.560 is that batman was built by
00:08:54.959 several developers at shopify and most
00:08:57.120 of them had actually moved on to other
00:08:58.640 projects so on the admin team uh there
00:09:01.680 were two people that were really the
00:09:03.440 experts at batman and the rest of them
00:09:06.480 were all new hires including me
00:09:09.200 so there just wasn't enough experts to
00:09:10.959 go around to help us out all the time
00:09:14.320 so finally the ultimate way to learn how
00:09:16.560 to use batman was to dig into the source
00:09:18.320 code of batman itself now in the end
00:09:20.480 this is always a good idea if you really
00:09:21.760 want to understand the underlying stuff
00:09:23.040 that you're doing but as a newbie trying
00:09:25.440 to ramp up and be productive quickly
00:09:27.360 this was a daunting challenge and a very
00:09:29.279 slow uh
00:09:32.399 it took a long time to get through it
00:09:36.080 so uh a month later was hack days uh so
00:09:40.240 hack days at chop fish you get a couple
00:09:42.640 days everyone in the company can work on
00:09:44.240 whatever they want to
00:09:45.760 and a lot of people had decided that
00:09:47.760 with i've been to shipping uh soon that
00:09:50.320 they wanted to try out batman for their
00:09:51.600 own projects and see what they could do
00:09:52.800 with it
00:09:54.160 so
00:09:54.880 people were like yeah let's use batman
00:09:56.720 let's see what we can do
00:09:58.000 uh so okay where do i start
00:10:00.160 they follow the same natural progression
00:10:01.680 as me okay let's look in the docs you
00:10:03.760 know let's get something up and running
00:10:06.000 okay that's not really working so well
00:10:07.920 so oh crap someone please help me please
00:10:10.320 help and of course a lot of them were
00:10:12.079 coming to me and this was still at the
00:10:14.399 very beginning of my learning curve i
00:10:15.760 had no idea what's going on still
00:10:17.760 freaking stuff out um so it turned out
00:10:20.000 that most people were just like well
00:10:21.839 that's enough of that and nobody ended
00:10:23.600 up using batman for the project so that
00:10:25.600 was definitely like a big hit to the
00:10:27.120 team like wow that sucks you know this
00:10:29.120 is what we're moving forward with and
00:10:30.959 other people in the company aren't
00:10:32.079 really comfortable using it
00:10:35.760 so the first big lesson we learned
00:10:37.760 was that solid documentation and
00:10:40.640 excellent examples are so important if
00:10:42.959 you want people to use your framework
00:10:44.800 brandon the other day had touched on
00:10:46.000 this uh really guarding the open source
00:10:48.560 projects well we were not very good
00:10:50.399 gardeners
00:10:51.600 um so after hack days
00:10:54.160 we set about improving our documentation
00:10:56.560 uh making sure that all the gaps were
00:10:58.240 filled in and
00:11:00.240 we moved on from there
00:11:03.839 so for the next couple of months after
00:11:05.360 we'd shipped admin 2
00:11:07.440 the focus was on new features we had to
00:11:09.519 expand our feature set and keep our shop
00:11:11.680 owners happy
00:11:13.279 now as i mentioned before most of the
00:11:14.720 admin team was actually new to shopify
00:11:17.760 and on top of that many of them were new
00:11:19.839 to rails
00:11:21.040 so we were spending most of our time
00:11:23.440 in the client which was written in
00:11:24.640 coffeescript
00:11:26.480 now the thing with batman is batman
00:11:29.040 our approach or the approach that they
00:11:30.720 take him with batman was that it was mvc
00:11:32.880 to the max so we had all of our models
00:11:35.519 including all the associations in the
00:11:37.519 client you had the controllers and you
00:11:39.040 had view state you had everything you
00:11:40.399 could possibly ask for so that meant
00:11:42.320 that we could do a lot of things in the
00:11:44.320 clients
00:11:46.399 so first question we'd always ask
00:11:47.760 ourselves on a new feature is
00:11:49.839 where should we put this code
00:11:51.920 well
00:11:53.279 frontend dev uh client has all the state
00:11:55.519 that i need so let's
00:11:57.600 do what we can there
00:12:01.680 now
00:12:02.720 there's an obvious problem that comes up
00:12:04.240 with this
00:12:05.760 we weren't just building our features
00:12:07.360 for the admin a lot of these features
00:12:09.040 were to be used by other applications so
00:12:11.839 along comes pos which is our point of
00:12:14.079 sale application
00:12:15.360 they were developing in parallel to the
00:12:17.200 admin maybe a couple months behind us
00:12:19.920 so what would happen is they will come
00:12:21.440 along to a feature that they needed to
00:12:22.800 implement that we'd already done in the
00:12:24.079 web admin and say oh okay well not
00:12:26.880 everything is supported in the api so
00:12:29.120 we're kind of comfortable developing in
00:12:30.880 in
00:12:31.680 objective c
00:12:32.880 so they followed the same path as us and
00:12:34.639 implemented stuff in their client
00:12:37.680 a lot of duplication not ideal but the
00:12:40.160 worst part was that there were just
00:12:42.000 these tiny subtle differences between
00:12:43.920 how we implemented it and how they
00:12:45.360 implemented it which ended up leading to
00:12:47.200 a lot of bugs
00:12:48.880 um specifically related to how we handle
00:12:51.360 orders
00:12:53.200 so when you have problems like this it
00:12:54.720 becomes very difficult um
00:12:57.200 for third party especially third-party
00:12:58.560 apps that are pulling down this data and
00:13:00.000 then trying to understand what are the
00:13:01.120 sudden discrepancies and
00:13:03.200 why why does this data not all look the
00:13:04.800 same so we weren't doing a very good job
00:13:06.639 of enforcing uh consistency throughout
00:13:09.680 our system
00:13:10.880 so in the end what we really should have
00:13:12.160 done is we should have been moving as
00:13:13.839 much of this business logic into the
00:13:15.600 server the server is the authority on
00:13:17.839 the data
00:13:18.839 um and on top of that you can't really
00:13:22.079 trust the client anyways
00:13:23.920 the client especially in a web client
00:13:25.680 all of your code is just there and
00:13:26.880 someone can go in and manipulate it and
00:13:28.480 do whatever they want
00:13:31.200 so the second big lesson that we learned
00:13:33.200 so we really need to minimize the
00:13:34.639 business logic we have in the client put
00:13:36.639 stuff into the api
00:13:43.120 so it was around december
00:13:44.800 2013
00:13:46.399 that i personally started my super deep
00:13:48.880 dive into batman towards the end of my
00:13:50.639 learning curve in the graph i had before
00:13:52.240 and trying to really understand the
00:13:53.279 fundamentals of how it works uh and what
00:13:55.600 i can do to help make it better
00:13:57.760 at the same time there were a lot of
00:13:58.720 people on the team that were starting to
00:13:59.920 say you know what the admin looks pretty
00:14:01.760 janky like it's not loading as fast or
00:14:03.839 as smooth as we would have hoped so you
00:14:05.600 know what's what's going on here
00:14:07.760 the expectation was that the initial
00:14:09.680 load downloading all the assets would be
00:14:11.279 a little bit slow but from then on it
00:14:12.560 should be pretty smooth
00:14:17.279 so here's where i have a little video
00:14:19.839 uh that shows
00:14:21.920 the first clip uh shows what we would
00:14:24.880 hope that the admin would look like and
00:14:26.959 the second part of it shows what was
00:14:28.480 actually happening in admin 2.
00:14:40.639 so here i'm clicking on a link going to
00:14:42.560 an order
00:14:44.720 and when the order loads everything's
00:14:46.000 snapped into place now here this is in
00:14:48.399 admin 2 and you noticed that some of the
00:14:50.560 sections sort of popped in
00:14:52.160 over time it wasn't all just like
00:14:54.320 loading immediately so let me show that
00:14:55.600 one more time
00:14:58.560 so this is the desired effect we would
00:15:00.480 hope to have
00:15:01.600 everything's just there
00:15:03.199 and this is what was happening admin 2.
00:15:06.000 so we considered this a form of jank it
00:15:08.079 was it was not something that we wanted
00:15:09.600 to happen
00:15:10.720 and actually it's a little bit of
00:15:12.000 foreshadowing the first example was how
00:15:14.320 admin next is working but the second one
00:15:16.240 was admin too
00:15:18.720 so the reason behind this
00:15:20.959 uh was related to how batman's binding
00:15:24.320 and rendering was working
00:15:27.600 so for any of you that aren't familiar
00:15:28.880 with bindings
00:15:30.079 i have another quick example here that
00:15:31.680 shows a great application of a binding
00:15:33.759 system
00:15:46.240 so here i'm typing in something in the
00:15:47.759 title
00:15:48.720 you'll notice down below it's a little
00:15:49.920 hard to see
00:15:50.959 that that section was being updated at
00:15:53.040 the same time so we have some client
00:15:55.279 state
00:15:56.720 hasn't been persistent to the server yet
00:15:58.320 we want to make sure that those two
00:15:59.600 fields are tied together
00:16:01.360 that is a great example of how you can
00:16:02.800 use bindings
00:16:05.199 to basically tie two fields together or
00:16:07.199 possibly to link some of your javascript
00:16:09.199 objects to html
00:16:14.959 so now if we look at
00:16:17.120 another example of the order page in the
00:16:18.639 admin
00:16:20.480 how many bindings do we have on this
00:16:21.680 page well let's see
00:16:23.680 if we got a binding up here for the time
00:16:26.000 stamp when this order was created
00:16:28.240 uh we also have another binding here for
00:16:30.639 whether it's a test order or not we just
00:16:32.000 put a little warning message
00:16:33.759 some more bindings here related to the
00:16:35.440 line items on the order and the details
00:16:37.519 about the pricing
00:16:39.199 for tags notes that we can associate the
00:16:41.680 address
00:16:42.880 and also all of these events so
00:16:45.040 there's a hell of a lot of things going
00:16:46.240 on there but how many of those bindings
00:16:49.600 are actually like dynamic and just kind
00:16:51.440 of happening on the client well the
00:16:53.040 reality is all of that stuff only
00:16:55.040 changes if we do a request to the server
00:16:57.120 and when we get back the response then
00:16:58.880 we apply any updates on the bindings so
00:17:02.079 the thing is like wow we can kind of do
00:17:04.240 the same thing if we just done a an html
00:17:06.959 request and let the server take care of
00:17:08.240 it so not really getting much on this
00:17:09.839 page out of the binding system
00:17:11.760 um and the problem with that as well is
00:17:13.839 that there's an overhead to having this
00:17:15.520 sort of binding system in the client and
00:17:17.439 rendering everything in the client
00:17:21.120 one of the primary overheads that we had
00:17:24.480 was our asset bundle
00:17:26.640 so you might be wondering well how do
00:17:28.400 you how are you rendering all of this
00:17:29.600 stuff uh client-side where's all your
00:17:31.600 html coming from
00:17:33.039 our solution was to bundle every single
00:17:35.919 page in our app which as you saw was a
00:17:37.520 lot uh from the first slide i showed how
00:17:39.840 the admin looked every single page
00:17:41.760 whether you used it or not was bundled
00:17:43.679 together converted into basically a
00:17:45.919 string
00:17:47.280 and
00:17:49.280 put into a js file and bundled up like
00:17:52.720 that so we had our two main ones was
00:17:54.799 batman itself
00:17:56.480 and the admin 2 templates so this is a
00:17:59.039 lot of overhead for possibly a user
00:18:00.960 that's only visiting maybe one or two
00:18:02.559 pages
00:18:03.679 now obviously you have some advantages
00:18:05.440 if you if you uh some caching in the
00:18:07.440 browser but at shopify we tend to deploy
00:18:10.080 a lot sometimes a dozen times a day so
00:18:12.480 the cache is constantly being busted as
00:18:14.320 we change these templates
00:18:16.400 and
00:18:17.200 for someone that's using a very slow
00:18:18.880 client or a slow connection 3d
00:18:21.440 or
00:18:22.240 just doesn't have very good internet
00:18:23.840 this is obviously a lot of overhead
00:18:25.120 that's not really desirable
00:18:30.559 so
00:18:32.160 the big lesson we learned in the end was
00:18:33.840 that starting to feel like jsnbc we
00:18:36.720 still liked the idea of it but it wasn't
00:18:38.320 really working that well for our app we
00:18:40.160 had a lot of state that was only
00:18:42.559 changing we would do a request response
00:18:44.640 from the server
00:18:45.919 and there was all this overhead with
00:18:48.000 really that much of a of a benefit
00:18:50.400 so everyone agreed that there was some
00:18:51.760 parts of it that were really great and a
00:18:53.120 big improvement over admin classic the
00:18:54.720 main one being bindings there were
00:18:56.080 certain cases where we weren't we really
00:18:57.520 wanted to keep those bindings the first
00:18:59.520 example i had shown with basically that
00:19:01.760 updating a title and another section is
00:19:03.440 being updated that was a great case this
00:19:04.960 is not something that's coming from the
00:19:06.080 server something that's changing
00:19:07.440 dynamically in the browser that's great
00:19:09.840 but for using bindings to update stuff
00:19:12.559 when it comes back from the server well
00:19:14.080 it wasn't really helping us that much
00:19:17.679 so
00:19:18.480 in the end we decided that
00:19:20.720 pros versus cons was better off to see
00:19:23.280 if we could try a new approach
00:19:25.919 try to get all the same benefits that we
00:19:27.280 had in mn2 but at a much
00:19:30.320 much cheaper cost in terms of asset size
00:19:33.360 and also complexity
00:19:36.880 so decision was made to reboot the admin
00:19:39.200 and kill batman
00:19:46.400 so some of the key goals for admin next
00:19:49.440 was it had to be easy to use we learned
00:19:51.919 from that hack days that people really
00:19:53.600 struggled
00:19:54.640 ramping up and onboarding with batman so
00:19:57.120 any any new framework we would build it
00:19:58.880 had to be something that we could bring
00:20:00.160 in someone new they could mess around
00:20:01.600 with it for a day and be comfortable
00:20:02.880 using
00:20:04.840 it we wanted to keep the good bits so
00:20:08.080 full page reloads
00:20:09.520 didn't like that we definitely wanted to
00:20:11.200 keep the ability to have uh pages
00:20:14.000 basically just load the sections that we
00:20:15.280 needed to change
00:20:16.559 um but at the same time minimize our
00:20:18.799 client states
00:20:21.440 really wanted to make sure that if we
00:20:23.039 were going to make the switch it better
00:20:24.400 at least be as fast as batman or better
00:20:28.799 so the other key thing we were thinking
00:20:30.480 is
00:20:32.840 that at shopify we become very very good
00:20:35.760 at scaling the server
00:20:37.440 so
00:20:38.559 um
00:20:39.520 by building batman and pushing more
00:20:41.679 stuff to the client one of the big
00:20:43.039 challenges we had is that we have no
00:20:44.640 control over what our customers are
00:20:46.400 using so they might be using a super
00:20:48.159 fast mac macbook pro or they might be
00:20:50.480 using some crappy phone
00:20:52.400 that's only supporting 3g so because we
00:20:54.320 have no control over that there's only a
00:20:56.159 limited amount we can do to help scale
00:20:57.760 the client but on the server we can just
00:20:59.840 keep throwing more servers at it or we
00:21:01.600 can improve caching or whatever so
00:21:03.600 pushing the rendering back to the server
00:21:05.840 seemed like a good idea
00:21:09.039 so
00:21:09.840 what exactly is admin next well for the
00:21:12.400 most part it's just rails um
00:21:17.679 plus we started using turbo links and
00:21:20.240 this is the part where i'm expecting
00:21:21.360 somebody to throw something at me
00:21:24.080 but to be fair we took turbo links the
00:21:26.159 idea of turbo links and modified it for
00:21:29.200 our own purposes so the general idea of
00:21:31.280 triple links is basically that instead
00:21:33.520 of doing a full page reload it just does
00:21:35.520 an ajax request and replaces the body
00:21:38.159 so we like that idea but that was a
00:21:39.600 little bit too
00:21:42.400 a little bit too simple we wanted the
00:21:44.720 ability to replace specific sections of
00:21:46.960 the admin depending on what was
00:21:48.640 happening so a good example of that is
00:21:50.480 let's say we update an order
00:21:52.640 uh update the let's say we capture some
00:21:54.799 funds the only thing that really changes
00:21:56.480 is the total amount that's been captured
00:21:58.080 maybe a small little text section
00:22:00.640 um and
00:22:02.080 something simple like that so we added
00:22:04.400 the ability similar to how pjax works
00:22:06.159 actually
00:22:07.360 that we could just specifically replace
00:22:10.000 a set of nodes
00:22:11.520 on the page with the response that comes
00:22:13.200 back from the server
00:22:14.480 but on top of that we weren't forced on
00:22:16.480 the server side to necessarily
00:22:17.760 understand what the client was doing so
00:22:19.760 the server could render any amount of
00:22:22.159 the html respond back with it and the
00:22:24.960 client would be able to decide what bar
00:22:27.039 what parts of that html i wanted to
00:22:28.640 insert into the dom
00:22:33.679 so we're still using the same json api
00:22:36.400 endpoints that we had before just the
00:22:37.919 difference now is that if you're in the
00:22:39.360 admin it's responding back with html
00:22:42.720 and as i mentioned we wanted to keep a
00:22:44.559 binding system so we built a new binding
00:22:47.200 system in only 255 lines of javascript
00:22:50.480 very very simple and basically works the
00:22:52.559 same as it did in batman
00:22:57.039 so that's what we've called
00:22:58.000 bindings.coffee
00:23:01.039 so really what we have here is not
00:23:02.480 necessarily a full-size framework we're
00:23:04.240 just using a few simple technologies to
00:23:06.480 achieve the same goal as what we did
00:23:07.760 with batman
00:23:11.120 so the big lesson we learned in doing
00:23:13.120 this reboot is we really want to try to
00:23:15.440 keep things as simple as possible so
00:23:17.520 that it scales well now when i say scale
00:23:19.360 i don't just mean the performance of
00:23:21.600 in the browser i also mean scaling with
00:23:23.600 the number of employees we have at
00:23:24.720 shopify we're growing rapidly and it's
00:23:26.799 really important that we can onboard new
00:23:28.320 people quickly and have them comfortable
00:23:30.240 working in our stack
00:23:33.280 so how's it going so far
00:23:35.039 well we're not finished yet we've got a
00:23:37.280 couple sections that we've shipped we've
00:23:39.200 seen great results so far
00:23:42.000 the biggest difference that we've seen
00:23:43.840 is that people are saying wow this is
00:23:45.760 just so easy to use and that's great
00:23:48.400 after our experiences with batman
00:23:51.600 the client side logic has been
00:23:53.039 significantly reduced most of the
00:23:54.799 decisions we make now we can just do an
00:23:56.480 erb
00:23:58.320 now any logic that we do have
00:24:00.080 client-side is specifically related to
00:24:02.640 ui concerns
00:24:06.720 and even after building some of the most
00:24:08.080 complicated views specifically being
00:24:10.000 orders
00:24:11.200 we found that very very little
00:24:12.640 client-side code has has has been added
00:24:16.840 so the fact that the client is just so
00:24:19.520 simple to understand and so little code
00:24:21.600 and we still have all the same
00:24:22.559 functionality batman is really a
00:24:24.000 testament
00:24:25.600 to
00:24:29.600 to the testament to how uh
00:24:32.080 sorry lost my train of thought anyways
00:24:33.840 it's been a great thing
00:24:37.679 so before we ship this open source um
00:24:40.880 we definitely want to improve the
00:24:42.080 documentation a lot more we don't want
00:24:43.360 to make the same mistake we did with
00:24:44.480 batman
00:24:46.080 there's certainly some optimizations we
00:24:47.679 can do as i mentioned when we're
00:24:48.960 rendering stuff on the server uh
00:24:50.640 sometimes we're rendering far more html
00:24:52.400 than is actually required by the client
00:24:53.840 so there's some things we could do there
00:24:56.640 but overall we're very satisfied with
00:24:58.240 our decision to move away from a full
00:25:01.360 single page web app now
00:25:03.679 i'm saying it didn't really work for us
00:25:05.120 but i still believe that jsnbc makes a
00:25:06.960 lot of sense for certain applications
00:25:09.039 and in our case
00:25:10.960 it wasn't for us
00:25:12.480 so
00:25:13.679 batman is dead but for us it's terrible
00:25:16.000 time
00:25:16.799 thank you
00:25:24.720 thanks nate
00:25:25.760 any questions for him
00:25:28.080 a question for you um
00:25:30.720 would you reconsider
00:25:33.279 doing a single page app
00:25:35.200 with sort of the developments in a lot
00:25:37.679 of frameworks such as ember require.js
00:25:40.720 angular and stuff like that
00:25:43.200 uh for me personally yes i i would be
00:25:45.279 interested in exploring other frameworks
00:25:47.279 uh i think
00:25:48.640 part of it now is that we've uh with our
00:25:50.799 experience with batman we've sort of
00:25:52.559 shied away from it but i do believe that
00:25:54.559 uh as jsnbc frameworks are improving
00:25:57.279 that a lot of these problems are being
00:25:58.720 solved that we had i would actually
00:26:00.559 attribute a lot of our problems
00:26:01.679 specifically to batman and how we've
00:26:03.200 built batman not necessarily jsnbc
00:26:05.200 frameworks as a whole
00:26:07.679 cool
00:26:08.480 second question it
00:26:10.799 doesn't look like anyone else um
00:26:13.679 with
00:26:14.720 how much of a role would you say
00:26:17.360 jason api played in the decisions he
00:26:20.400 made on the front end
00:26:22.720 and stuff like that inspiring
00:26:25.919 how are your diet reloads and stuff like
00:26:27.840 that
00:26:30.240 um sorry in terms of what
00:26:32.400 i um the way in which your data is
00:26:35.120 structured and yes sent through to your
00:26:37.279 front end
00:26:38.559 so if you're sending ids that then
00:26:41.600 require another
00:26:43.200 fetch from the api for more data right
00:26:46.000 he showed that
00:26:47.520 um page where it was loading data and
00:26:50.080 conventional
00:26:51.679 that just a um
00:26:53.600 artifact of the way you designed your
00:26:55.600 api
00:26:57.200 actually the api was returning
00:26:58.720 everything in one response so we just
00:27:01.679 had one json request that was coming
00:27:03.520 back
00:27:04.320 the problem you were seeing there was
00:27:05.919 totally related to how batman was
00:27:07.360 handling that response it's it's related
00:27:09.440 to some of the details of how we we did
00:27:11.200 uh some of the bindings how the bindings
00:27:13.600 would basically render uh render out the
00:27:16.000 html um it's
00:27:18.799 it's beyond the scope of this talk for
00:27:20.799 sure there's some deep complexities in
00:27:22.640 there that i would prefer to forget
00:27:25.600 um but yeah it was it wasn't related to
00:27:27.760 to the how the api was responding
00:27:29.919 cool thank you
00:27:35.039 hey tried to uh did you try to
00:27:37.279 contribute to batman or like contact
00:27:39.200 maintainers and talk to them about these
00:27:41.600 issues that you had i mean i'm wondering
00:27:43.840 if it's developed and if your experience
00:27:47.679 somehow made maintainers to to to change
00:27:50.640 to improve the library
00:27:52.960 so
00:27:53.679 actually uh it was around december when
00:27:55.520 i was doing that batman deep dive that
00:27:57.840 uh we had started to discover um some of
00:28:00.559 the flaws in batman and i started to to
00:28:03.600 come up some for uh come up with some
00:28:05.279 solutions for this
00:28:06.720 but there was a lot of work that would
00:28:08.480 have been involved
00:28:10.080 one of the problems with batman is the
00:28:12.080 amount of complexity that was built into
00:28:13.520 there was a very large framework there
00:28:15.200 was a lot of things going on and making
00:28:16.960 any change was was very difficult
00:28:19.600 whereas we figured it's probably going
00:28:21.840 to be just as expensive to just do a
00:28:23.440 reboot and go from there so that's why
00:28:25.840 we went the the prototyping
00:28:28.240 solution
00:28:32.159 any more questions
00:28:34.640 if not thank you nick
00:28:47.039 so
00:29:01.039 you
Explore all talks recorded at Red Dot Ruby Conference 2014
+20