Building Isomorphic Applications in JavaScript
Langholm Vullum, Eirik
As developers we want to get our products in the hands of our users as quickly as possible, while we strive to keep complexity and context switching overhead down to a minimum. Moving towards unifying the server and the client presents some very appealing advantages, suggesting you could get the best of both worlds (performance, SEO, graceful degradation, code sharing, etc.) This talk will explore the available options out there for building isomorphic JavaScript applications, showing both the advantages and drawbacks. Using node.js, React, the Flux pattern and compatible routing solutions, we’ll see that this is in many cases a viable solution already used for notable production applications today.
 Okay, so, hi everyone. You hear me? Okay, so I'm here today to talk about isomorphic JavaScript applications and what that string of words mean, why you should be excited about it and how you can build one. So, my name is Erik Vullum and I'm a tech lead at Scandinavia Online where we do a lot of JavaScript development, yeah, web development. So, you might remember Scandinavia Online as good old Sule dot NO, one of the trusted gateways of the Norwegian parts of the internet in a not so distant past. Times have changed and today we're a news aggregator and a technology company where we do a lot of JavaScript development. So at Scandinavia Online we started experimenting with isomorphic JavaScript about a year ago, just about the same time that we started playing with Facebook's React library. And through this talk I'll hopefully get to show you why we've continued on that path and why we think that it's great. So what is all this fuss about isomorphic JavaScript apps and why should you care? Is it just another fad or does it actually have some practical use to make your apps and your life as a developer better? And I know it's a huge buzzword alert. And as I said earlier, we do a lot of JavaScript development at Sule and I have a lot of empathy for fellow JavaScript developers. But I feel outright sorry for those who are just getting into JavaScript. There's so much happening that you can barely follow along unless you live on hacker news, GitHub or at tech conferences. And so how many days has there been since the last JavaScript framework? Just guessing. I would guess about zero by a fair margin. Also about every day there's a new JavaScript framework in some form or another. Ryan Florence came up with this fancy name here in the talk he had. And the same goes for buzzwords in web development. About every week there's a new buzzword that you have to learn about. It's both amazing and terrifying at the same time. And this gives me the opportunity to show you one of my favorite Norwegian comedy sketches that shows you how I often feel in the world of web development. And I hope it's not just me. Five of I'm sure you're cool! I'm sure you're cool! I'm sure you're cool! I didn't know what the fuck I'm sure you're cool! I just gave him some tape rast! I'm sure you're cool! Oh, you're flirty! Here's the one who came back! I don't know what he gave me but it was wrong. So then I just had to take a wild shot and I said the word. Camelosa? I should say Cameloso! Camelosa! I didn't know what Camelosa was. In general, I must say it's not a nice cramped store and nobody knows what things are called. So I guess if you replace ice and cramped store with web development, it's a pretty decent translation. But even if isomorphic JavaScript sounds terrifying, it isn't that scary actually. So at least I'll give it my best shot to explain what it's all about. So in the context of web development, it simply describes JavaScript code that can run in several environments. And those environments could be on a server running on Node.js. It could be on a client running in a web browser. Or it could be other JavaScript runtimes like JavaScript Core on an iOS device. So we can say that isomorphic JavaScript is environment agnostic as we're abstracting away the environment and the differences from the application itself. And later on we're going to see why this is handy. But before I go any deeper, let's first take a step back and look at the status before we started talking about isomorphic web applications. So old-school server rendered pages. Think ASP.net, PHP, any other server-side rendering language. You would just re-render the whole thing on each request, just ship a new page from scratch. And that's really easy to reason about. But the user experience starts to suffer as your application grows in complexity because every action is a refresh. And that just wasn't good enough. So we wanted more dynamic web pages that didn't refresh every time we clicked a button to submit a form. And then came Ajax and the single-page app. And that meant dynamic web pages without any reloads. And the infamous loading spinner. So on a slow connection you probably wouldn't see anything else for quite a while because we forgot to minify and compress our JavaScript. And when the site finally loaded, you wouldn't dare to click the browser back button in the middle of something instead of the proprietary one provided by the app because all your stuff would be gone and you would end up back at vg.no. And you could forget about SEO unless you created a separate response for Google or the other crawler bots using things like Phantom.js. Things have gotten better now, though, with Google executing JavaScript and everything. But let's look at the pros and cons of these two approaches. So the good thing about server-endered pages and applications are that it's really easy to reason about because you're serving a fresh page every time the user interacts with your application. And you get all of that SEO stuff out of the box. And the not-so-good things are that every action is a page refresh, which means that you often have to load a lot of redundant data because just a small part of the UI might change, but you reload everything. And also all that refreshing gives you a poor user experience if you have a very dynamic app where the user interacts with it a lot. And the pros of the client-side single-page app is that you can now make really dynamic apps that don't refresh for every user action. And you have less redundancy because you're only updating the parts that change. And you can create a much better user experience using asynchronous JavaScript. And the not-so-good things about single-page apps is that since everything is happening in the browser, there's no content before the client-side JavaScript has loaded, which in turn might result in a poor perceived performance as you'll first wait for that loading spinner to load, and then you'll wait for that application itself to load. And if you need to have your pages indexed by crawlers, this can be a pain. But I want it all, we say. So we do a mix of server-side rendered pages with a dash of plain JavaScript, some jQuery, and maybe some other favorite library or framework that magically makes our site come alive. And the good thing about this approach is that it gets all of our stuff done, and we can make that really cool application we want, and we can get the benefits of both the server rendered pages and the client-side single-page app by hacking this together. But the not-so-good thing is that you'll now have two separate code bases to maintain and to keep in sync. You'll have a lot of implicit coupling between those server rendered results and the client-side JavaScript, and this makes development harder and the chances of regression bigger. Because what happens server-side and what happens client-side, that divide can start to blur after a while if the app grows large in complexity. And more often than not, this turns into a not-so-enjoyable experience. So by covering that, I'm going to present a few bold statements. So with isomorphic JavaScript applications, you can have all of the good parts of both the server-side rendering and the client-side rendering in one package. And at the same time, you'll have none of the cons mentioned. This is a bit of a stretch, but I'm going to stick with it for now. So as I said, we started experimenting with isomorphic JavaScript about a year ago when we were making a new prototype for our mobile web application. And the meaning of isomorphic in this context, it really just boils down to that there's no more conceptual divide between the server and the client when it comes to the actual application code. So this means that your JavaScript application can be rendered both on the server and on the client. So this would be like the request flow for an isomorphic JavaScript application. You would first get a request from the user via HTTP, and the application then gets rendered on the server using your JavaScript application. And the server then responds with the HTML generated from rendering your app server-side. And then the client uses the same JavaScript code and takes over where the server left off. So this approach requires us to use abstractions that are environment agnostic in the sense that abstractions that doesn't care if it's running on the server or the client, but it should work either way. So what do we need to make this possible? So there's a lot of options out there now which have a lot of the same capabilities, but they solve the problem using very different approaches. So I'll focus on the approach we've chosen at Sule, which is React. And how many of you guys have used React or at least heard of React? Yeah, cool. So we chose React for our apps because we think it's a great tool to build user interfaces in addition to having all of the stuff we need to make our apps isomorphic. And it's also a big plus that in some form or another has been in production at Facebook since 2011, and you simply can't find much better battle testing than that. So the core selling point of React is that it enables you to build composable UI components and that it helps you structure the UI part of your web application. But let's look at how React facilitates isomorphic JavaScript apps. So on the server, you would render your app to a string representation of the HTML by using the render to string method. And on the client, you would render your app to the DOM using another method called render. And this means that you can now render your application both on the server and the client. So, but instead of just talking about isomorphic JavaScript apps, let's do a walkthrough of how you can actually build one. So let's build a really simple isomorphic web app and we'll build an app that fetches the 10 latest videos from NDC, from the Vimeo API, and then show them in a horrible looking app. So let's look at the building blocks for the app. So for the server part, we'll use Node.js and the magic of NPM. And this will give us the ability to run JavaScript code on the server. And we'll use Express as a simple but powerful framework to serve our web application in Node.js. And for the user interface part, we'll use React. And for managing and building our client-side JavaScript, we'll use Webpack. So for those of you who don't know Webpack, Webpack is a module bundler, which in our case enables us to use the same kind of module system as Node.js in the browser. So that we're able to use the same NPM packages. And this is crucial to the isomorphic JavaScript approach as we need to make our code runnable in the browser as well. There's also a tool called Browserify that does the same thing in a slightly different way. But for this example, we'll stick with Webpack because it's a bit easier to get the basics up and running. So this should be everything that we need to make a simple isomorphic app. And this is what our finished app should look like. Simply just listing the 10 latest NDC videos from Vimeo using the Vimeo API. So here's the folder structure of our application. So we have a root folder which contains our Node.js server app script called App.js. And we have a Webpack configuration file. And then in addition to that, we have one folder for all of our React components. And this is the actual Web app. Inside of components here, this is the actual Web app which results in our HTML or DOM. So we have another folder containing our different rendering code. So we have one for the server and we have one for the client. And we also have a folder containing a data fetching service, which in our case is just a function to fetch the latest NDC videos from the Vimeo API. So let's just go through each part and then just put this thing together into an isomorphic JavaScript application. So first of all, we have a React component called App, which is the main container of our React application. Can everyone see this? So this only contains a render method. And in this render method, we expect that whatever calls this component will supply it with an array of data containing the metadata about the 10 latest videos from NDC. And we'll map each of those array entries into video components with the appropriate properties. And that gives us an array of video components, which we will then insert into an unordered list. So this React component, this whole app, it just produces an unordered list in HTML, just a UL element. That's like the top element of this app. And next up is a video component that we used in App.jsx. So this component has a render method that generates a list item out of the data we passed to it through the mapping we did in App.jsx. So each video component is just a list item. It's just an L-I element to be placed inside of a list. And each list item has an image, a title, and a description. And next up is the function we'll use to pull data from the Vimeo API. It's just a simple function that uses an NPM module called Vimeo, which simplifies fetching data from the Vimeo API. So the result of calling this Vimeo.request function and supplying it some options and a callback will in our case be an array of the 10 latest videos by NDC on Vimeo. And next up is the render entry point that we're going to use server side. So this is the function that will be called when the browser does a request to our application. So in our server render entry point, we'll first use the service that we created to fetch the 10 latest NDC videos as JSON. And when we have that JSON data, we'll pass that to our React app component as a property. And then we'll use React render to string to render our whole app to a string. So the app markup variable here will just contain a string of HTML. But let's take a closer look at the stuff in the middle here, because this is where the magic of isomorphic gaps are. So to make a complete HTML markup that we can deliver to the browser, we'll use, in this case, we're using ES6 templating strings. So finally in JavaScript, you're able to have multi-line strings without doing this kind of concatenation with plus and all that stuff. So let's see if this makes any sense. So here we're just placing that markup generated by React render to string inside of a div element. And we'll give that div element an ID of app so that we can fetch it again on the client. So that means that what we're doing here is that we're just placing an unordered list inside of a div. And in addition, we'll attach the video data we got from Vimeo to the document as a script element. And this is popularly called dehydration, or you could call it serialization. So we're stringifying that JavaScript object, and we are attaching it to the global window variable, to a variable called underscore underscore app data. And we need to do this because React has to have the same data available on the client that you have on the server. So really, we're just bootstrapping the client-side application the same as we're doing on the server. So we're just attaching data to the document. And the last thing we'll do is to attach another script tag. And this script tag will reference the client-side JavaScript bundle that we're going to build using Webpack, which will package our app for running in the browser. And in our case, this file is going to be called bundle.js. And when all of this is done, we just ship this string of HTML as the result of the HTTP request we got from the browser. And next up is the render entry point we're going to use on the client in the browser. So when the client-side JavaScript has loaded in the browser, we first want to make sure that the DOM is finished loading its content by attaching our code as a callback to the DOM content loaded event. So what happens then is that we should be able to access the data that we attached as a script element when we rendered it on the server, as we'll need that data to be able to render our app correctly in the browser. And this again is called, in the case of isomorphic JavaScript, this is often called rehydration. But you can also say, unserealization or any other fancy word. So on the server, you dehydrate data, and on the client, you rehydrate. So you're kind of just passing data through the wire. So now we can use the React render function and render the same app into the existing markup that we got from the server, just by specifying the DOM element we want to hook into, which in our case was the div element with the idea of app. And this won't actually render anything to the DOM, but it will just seamlessly hook into the existing DOM. Now I'll explain why and how in a few slides. So we'll go over to our server application, AppJS, which will run as a node process. So the first thing we do here is just to import the modules that we need and then create an express app. I've omitted these require and then module parts from the other files just to get it small enough. And we then state that we want to, for every request for a static asset for which there's no route assignment, we'll just look in the public folder. And then we'll attach a single route handler for the root of our app, which we'll use to, where we'll use our server render function to create a response for the user. And the last part here is just attaching the express app to a port and start listening. So last up is the configuration file for Webpack. And this states how we want to bundle up the JavaScript we need for running our application in the browser. So it just contains a simple JavaScript object that states our configuration. And it looks like this. So the first part named entry, it just states which file should be the entry point for our client side bundle. And in our case, that would be the client.js file from the render folder. And we also state that we want the output file to be placed in the public folder with the name of bundle.js. And that way we can access this bundle through the static file serving that we set up in Express. And the last part, it just states which loaders the source files should be transformed with. And in our case, we're using both JSX in our React app. And we're using a lot of new stuff from ECMAScript 6. So a loader called Babel will transform all of that stuff into executable ES5 JavaScript in bundle.js for us. So that we can be sure that this can run in any browser that supports at least ECMAScript 5. So what happens is that Webpack processes client.js from the render folder. And it bundles together all the scripts referenced in client.js as well as the NPM modules. And then it creates a single browser bundle which contains everything that we need to run this in the browser. And then it places it in the public folder as bundle.js. And if we take a look at this by requesting it in the browser, it looks something like this, containing a lot of Webpack-specific code in addition to our own. So now we should have everything we need to get our app running. So let's imagine that we run Webpack to package our client side the script first. That means creating the public folder and inserting bundle.js. Then we just start the app by using Node to run app.js. And at the end we just open our browser to localhost 3000. And this would be a result, the same list that we saw in the beginning. But let's look at the Chrome debugger. So here we can now see the markup we designed in our server rendering function. We have our development containing the React rendered application. We have the script tag where we attached the dehydrated data. And we have a script tag where we tell the browser to load our client's JavaScript bundle that we made with Webpack. And if we inspect the dehydrated data a bit closer, we'll see that it's just a JSON object, which we have attached to the global window namespace as window.underscore.appdata. And inside the development we now have our React app, which is just an unordered list containing list items. But here we can also see some of the magic behind the isomorphic rendering in React. Because when React renders something server-side, it attaches a checksum to the topmost element. And when the same app is rendered in JavaScript on the client and you try to mount it into the DOM, it'll do a diff against that checksum. And if the checksum is identical, it will instead of re-rendering anything, it'll just hook on to the existing DOM and then attach any applicable event handlers or whatever React needs to control your app. Basically just continuing where the server left off. And if the checksum doesn't match, it'll discard the existing DOM that it got from the server. And it'll give you an error message telling you that something is wrong since your server and client-side rendering isn't corresponding. And if you look at the scripts loaded by the network, you'll see that our client-side bundle is loaded and that everything is working as it should be with no error messages. So now we have a nice,omorphic JavaScript application. A very bare-bones one that is, which doesn't really make any use of the fact that it's isomorphic. But what's the point of all this? So the great thing about isomorphic JavaScript, at least for us at Sule, it hasn't been things like performance or load times or that we're able to use the latest hype, even if that in itself is great. But it's a developer experience and the maintainability and how much easier it is to add features to our apps since we now have the same code for both the server and the browser. And that layer of abstraction, it creates so much more cohesion in the app instead of having this completely separate JavaScript application manipulating a server-rendered result. And that pretty much enabled us to quietly sneak our tangled mess of client-side JavaScript with jQuery and all that stuff out the back door and just put it out of its misery. And yeah, it feels like a level up. And we're having a lot more fun in the process. But just to sum up some of the good parts. So the best thing about this is maintainability because you now have everything in the same language and everything is the same code base. Not everything is perfect because you still have to do all of that orchestration around rendering on the server and on the client. But in our case, that trade-off is a lot easier to make because everything else is a single code base. And there's no more messing around with phantom.js and all that stuff to get crawlers to index your site because everything is rendered on the server as well. And you get progressive enhancement out of the box. So the initial response is created by the server. And when the client-side JavaScript has loaded your page, then everything comes alive. And I still haven't figured out the difference between progressive enhancement and the graceful degradation, so I just put them both there. But the best thing of all is that you're abstracting away the conceptual gap between the server and the client. Because it's kind of an artificial gap, which makes it easier to not have to think about it. So what I've showed you up to now isn't really enough to build a fully isomorphic JavaScript application because there's several parts of an application that can be isomorphic. And in our demo app, we just mainly looked at one of them, which is rendering. And React has made it really simple for us to render an application both on the server and on the client. And you get that support out of the box. And by rendering here, I just simply mean something that is consumable by a browser, either as HTML text response from a server or as DOM objects produced by JavaScript. But there's another important part of web applications, which is routing. And routing is also something that can happen both on the server and on the client. And on the server, you would serve the appropriate page by looking at... So in Node, this is the Request URL. But in the browser, you would look at something like window location, and you would use the history API to manipulate the location. So making routing isomorphic would then mean to be able to use the same routing mechanism both on the server and the client so that you're not replicating the routes for both the server and the client. So, and this is exactly what React Router does. So it's a community-made routing solution that works both on the server and on the client. It uses the same API for both, for different inputs, so that it enables you to reuse the same routes on both the server and the client. And another pretty integral part of web applications is data fetching, so requesting resources over HTTP. On NPM, there's a module called Superagent, and it's a great example of an isomorphic request library. So doing an HTTP request on the server is very different from doing an HTTP request in the browser. And Node.js has the built-in HTTP module to handle this, and in the browser, you have the XML HTTP request. So what Superagent does is to create a layer of abstraction on top of these two vastly different APIs, and then it just exposes a single API on top so that this would work in both the server and the client. So that means that you have two completely different implementations underneath, but you have the same API on top. So in Webpack or Browserify, packages, an app that uses Superagent, there's a completely different piece of code being included in that bundle than what is being used on the server. Because the application, but the application that consumes that API doesn't have to worry about being on the server or the client because it will produce the same results either way. So the rule in quotes for isomorphic applications is that all the abstractions you use inside of your app has to be isomorphic, meaning that they have to work both on the server and the client and producing the same results. And if a library or a module doesn't depend on the environment it runs in, then it's isomorphic by default. So let's look at an example that is fully isomorphic, meaning that it has isomorphic rendering, isomorphic routing, and isomorphic data fetching. So let's see. So here's an app we have running. It's pretty much the same as the demo app that we were building earlier, except it's just a bit more advanced. So we can see that if we go back and forth here, now we're at the login page, we have a signup page, you can go back to the landing, and if we check, if we just observe like the fabric on the reload button here, you can see that everything is happening client side. So we're not reloading anything from the server here. Everything is happening on the client, so the routing, everything happening on the client. So let's try to sign up for this page doing something like... So that automatically signed us into the page here. So on the side here, we just have a list of videos that was loaded by the API. We can browse through videos from NDC. And still we can see that everything here is happening on the client. And I think that if we open up the network tab here, let's see, all... Let's see that if we request... Oh, failed, that's not good. Oh yeah, I have no internet, so the images started to fail when the cache went out. Let's not disable cache then. Okay, so you can see here at least that whenever I click something in the app, it does another request to fetch the data for that item. Yeah, so we can just log out. But what happens if I just disable JavaScript in the browser? Usually on a client-side app, that would just render a blank page, nothing. Or if maybe an Angular app, you'd get the template flashed at you, just like the naked template from Angular. So we have disabled JavaScript. Okay, the landing still works. What about if I try to go to the login page? Yeah, still works. Now you can see that it's actually refreshing the page. So now nothing can possibly happen on the client-side because we've disabled all the browser JavaScript. So let's see if I can sign up again. Let's sign up. Yeah, we're into the app. I can still browse through here. Some of the images work. So now you can see that now everything is actually happening on the server. And there's not any... This is the same app. There's no replication that we have the same thing on the server and the same thing on the client, just two different code bases. But it actually works even if you don't have client-side JavaScript. So that means that this is where the progressive enhancement part comes in because you can still use this app even if the JavaScript hasn't loaded on the client yet. Because the sign in the login form, if the client-side app hasn't attached any events yet, then it's just a simple form that would send that login data as a post request to your API. Let's see. So let's just do a recap of why isomorphic JavaScript is worth looking into. So one thing is that you have a lot less context switching because the application code for the server and the client are the same. And it's all JavaScript. And since we're sharing all the code, it's easier to maintain because there's only one single place to change the code. And you get the best of both server-side rendering and client-side rendering. And an added bonus for us at Scandinavia Online has been that we've been able to push features faster, although this is highly anecdotal. So if you want to play around with any of the examples I've shown you today, they're all available on GitHub. And I'll post the slides and the links on Twitter afterwards. And that pretty much concludes what I have to show you today, finishing a bit early since everyone probably a bit tired. So if anyone has any questions, then I'll be happy to answer. Yeah, you... Yeah, that's a really good question. So the way we've solved this is that we have this API layer so that everything is HTTP request. So if we request any data from the database, we have this layer of abstraction on top which uses SuperAgen in our case. So because it wouldn't make sense to try to make like an SQL... my SQL request or like a MongoDB request on the client because that just doesn't make sense. So that's why I was mentioning that everything has to be environment-agnostic, like an abstraction layer on top. Yeah. So kind of like the opposite to that question. So this works when your pages are kind of static and you're like following me. If you have some pages that have like interaction and that could only really be rendered with JavaScript, how do you handle like if you use and navigate to that page and your JavaScript hasn't loaded but they start interacting with the page? Yeah, so that's... So for example, if they're on a mobile connection and you've got like, I don't know, something involving controls that they can move to that settings and they start doing that, because also you can't like shift the jazz on the server. No. Do you like repress directions when your JavaScript fits in or...? So we've been experimenting with some approaches there because that's the issue, right? Some things you just can't replicate simply by doing everything on the server. So to try to kind of get the best out of that, we can make every button a form so that every action on the site is a form. So if the client-side JavaScript hasn't loaded yet, you're firing off a form request, like a post or anything to your API. That would then like handle this on the server and give you back the correct results. But if you have things like sliders or anything that is like purely JavaScript, that has to be... that has to wait for the client-side JavaScript to load. So some things you can't replicate. Like are we thinking you could use jQuery to attach to clickable elements to then store click events, which you can then replay against the IT React tips then? But I don't know if there's anyone solved the problem so far. At least I haven't solved it properly yet. It's really good when you have your home page as your landing page. It's like basically just a fancy version of the spinner. Like if your home page is your app, like the kind of interaction basically you have. Like for example, you go to Facebook and it's like your wall. And if you start interacting with it but it's not loaded, how do you deal with that? Yeah, so that's what I was talking about. So say that you had the Facebook page. The Facebook page is a great example that could be isomorphic. And in fact, for a long time, Instagram.com was fully isomorphic. So that means that if you've loaded your news feed on Facebook, and you want to click like on a post, but if the JavaScript hasn't loaded, that click has to be a post request that goes to the server and then redirects you back and then shows you like the updated state. So that's basically how I solved this one is that in like the React component where I used a form, I attach a form action so that if the JavaScript hasn't loaded, it's just a regular form instead of an event that is triggered. So yeah, there's a lot of like tricks you can use, but yeah, I think it would be hard to get like a one to one conversion there. But it's fun though. Yeah. My question is kind of related to that. And it's really how do you integrate with the third party, front end, library, like for example, in your app, what if you wanted your video component to actually use video.js because you wanted to have a fancy player for the videos instead of just a static image. How does that affect server side rendering? Obviously they can't render on the server. Yeah, that's a good question. So, yeah, he was wondering, so what if you wanted to use some JavaScript libraries to like spruce up your app, like using video.js to render the videos or something, because you obviously couldn't do that on the server side. But yeah, as I said, it's hard to replicate everything back to the server. That's why some things are just purely client side, but those things will just be ignored on the server because React has these life cycle events and some of them only run on the server, some of them run on the client and the server, and some of them run just on the client. So it's just a matter of where you attach those things. So that means that from the server, it could just be an image or it could be like an HTML5 video element. And when you arrive at the client, that would just take over and like enhance whatever you have there to. How does that work in the case you mentioned that checks some that errors out when the two DOMs don't match. So, I mean, I don't know, forget about video.js specifically. But suppose it's just some library that modifies the DOM as part of the rendering on the client, you know, fancy select or something like that. So now longer it's the same, it's not even the same DOM that was rendered on the server. There's a bunch of other elements rendered by this third party library, which is pretty common. Yeah, yeah, yeah. How does that work in the case of? Yeah, should I repeat the question? Yeah, so he was asking what if you, for example, want to use jQuery to manipulate some of the DOM elements that has been rendered on the server. Will that like affect the fact that the checksum would be different or that you would kind of miss that isomorphic thing. So when it arrives at the client, it'll just do the exact same rendering that it did on the server so that none of that stuff, like the purely client side stuff will run on that initial render. So when that has rendered and the component lifecycle method that explains that now your app has mounted into the DOM, whatever happens next, it doesn't affect that stage of the rendering. So you're kind of just trying to pick up where the server left off and then, yeah, it's like, yeah, you could just call it progressive enhancement from there on. Any more questions? Yeah. Yeah, so, yeah, that's the, so you're thinking about stuff like Polymer or Web Components. Yeah, because as you say, Web Components or Polymer can just, it's just a purely client side thing, just like Angular or jQuery or, yeah. So that obviously wouldn't be suitable for this kind of isomorphic approach. But I think that React here and Polymer and Web Components are trying to solve kind of the same thing but different because React is much more of a complete UI library. Whereas I see Web Components and Polymer more as a really good way to make this kind of isolated components that you want to drop in anywhere that you want them. And you could easily use Web Components together with React.js, like say that nothing is rendered on the server, but as soon as it gets on the client, you inject a Web Component that you have ready. So, yeah, I see your point there. And yeah, I'm not sure what Web Components or Polymer is going to be. I'm just curious, I guess I would love to hear people talk about that more because it seems like it's a bit of a conflict. We had a crisis meeting at work recently where the debate was Polymer versus React. And for now, the safe answer is, okay, both. I have a question kind of related to the last one, related to your crisis meeting at work. So we're using React and isomorphic stuff on my project. And we're doing it for SEO, server side rendering and then rich user interface on the client. It's working really well, but just like you're talking about, what are some of the practical difficulties you've run into? Tell me more about which stuff have you run into at work where you have more crisis meetings. How are we going to solve this? And maybe something that you didn't want to talk about today because there's such a problem. Or maybe there's none. I think the main issue with us using isomorphic React is kind of not understanding what it is because there's been a lot of confusion. What happens on the server and what happens on the client? And when you try to include MongoDB and attach it to your client script, weird stuff started to happen. Like everything works on the server and when it arrives on the client, everything is borked. Just getting your head around what isomorphic JavaScript is and what you're trying to solve by making that abstraction has kind of been, yeah, like the main problem. But I don't know any specific issues. If you have a more specific question, then that would be awesome. I want to hear more about crisis stories. Yeah, maybe afterwards. That's a good sign if you haven't heard anything. Yeah, that's kind of the best thing about this is that we've just had a lot more fun developing our apps because earlier the issue has been that we wanted to do, if we wanted to do like fun real time stuff or just dynamic JavaScript stuff, the issue has been that we have to slap on some kind of thing on top of that server-rendered result. But now we can just do it from scratch and all of that fancy stuff just doesn't happen until you actually reach the client. You don't have to think about that divide anymore. Everything is in the same place. Any more questions? Yeah. Yeah. Yeah. Yeah. So actually the project that has benefited most from this, at least using React, is different kind of internal tools we have like admin interfaces and that kind of stuff. And we've been using React and Flux there now and it has just made everything so much easier, just easier to kind of structure your app and mitigate errors. But there again, we don't use the isomorphic approach because why would we need isomorphic on our internal admin app? So you might have a point there that this is mostly useful in apps where you need to have stuff rendered on the server first. And the kind of the last example I've showed you there is probably not that useful for everyone. But yeah, mostly for the case where you want to make a single page app but you also want to have this rendered on the server because you're indexing stuff. So yeah, I guess that's a good point. So any more questions? Okay, thanks for listening. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you.
 Okay, so, hi everyone. You hear me? Okay, so I'm here today to talk about isomorphic  JavaScript applications and what that string of words mean, why you should be excited about  it and how you can build one. So, my name is Erik Vullum and I'm a tech lead at Scandinavia  Online where we do a lot of JavaScript development, yeah, web development. So, you might remember  Scandinavia Online as good old Sule dot NO, one of the trusted gateways of the Norwegian  parts of the internet in a not so distant past. Times have changed and today we're a  news aggregator and a technology company where we do a lot of JavaScript development.  So at Scandinavia Online we started experimenting with isomorphic JavaScript about a year ago,  just about the same time that we started playing with Facebook's React library. And through  this talk I'll hopefully get to show you why we've continued on that path and why we think  that it's great. So what is all this fuss about isomorphic JavaScript apps and why should  you care? Is it just another fad or does it actually have some practical use to make your  apps and your life as a developer better? And I know it's a huge buzzword alert. And  as I said earlier, we do a lot of JavaScript development at Sule and I have a lot of empathy  for fellow JavaScript developers. But I feel outright sorry for those who are just getting  into JavaScript. There's so much happening that you can barely follow along unless you  live on hacker news, GitHub or at tech conferences. And so how many days has there been since  the last JavaScript framework? Just guessing. I would guess about zero by a fair margin.  Also about every day there's a new JavaScript framework in some form or another. Ryan Florence  came up with this fancy name here in the talk he had. And the same goes for buzzwords in  web development. About every week there's a new buzzword that you have to learn about.  It's both amazing and terrifying at the same time. And this gives me the opportunity to  show you one of my favorite Norwegian comedy sketches that shows you how I often feel in  the world of web development. And I hope it's not just me.  Five of  I'm sure you're cool!  I'm sure you're cool!  I'm sure you're cool!  I didn't know what the fuck I'm sure you're cool!  I just gave him some tape rast!  I'm sure you're cool!  Oh, you're flirty!  Here's the one who came back!  I don't know what he gave me but it was wrong.  So then I just had to take a wild shot and I said the word.  Camelosa? I should say Cameloso!  Camelosa!  I didn't know what Camelosa was.  In general, I must say it's not a nice cramped store and nobody knows what things are called.  So I guess if you replace ice and cramped store with web development, it's a pretty decent translation.  But even if isomorphic JavaScript sounds terrifying, it isn't that scary actually.  So at least I'll give it my best shot to explain what it's all about.  So in the context of web development, it simply describes JavaScript code that can run in several environments.  And those environments could be on a server running on Node.js.  It could be on a client running in a web browser.  Or it could be other JavaScript runtimes like JavaScript Core on an iOS device.  So we can say that isomorphic JavaScript is environment agnostic as we're abstracting away the environment  and the differences from the application itself.  And later on we're going to see why this is handy.  But before I go any deeper, let's first take a step back and look at the status  before we started talking about isomorphic web applications.  So old-school server rendered pages.  Think ASP.net, PHP, any other server-side rendering language.  You would just re-render the whole thing on each request, just ship a new page from scratch.  And that's really easy to reason about.  But the user experience starts to suffer as your application grows in complexity  because every action is a refresh.  And that just wasn't good enough.  So we wanted more dynamic web pages that didn't refresh every time we clicked a button to submit a form.  And then came Ajax and the single-page app.  And that meant dynamic web pages without any reloads.  And the infamous loading spinner.  So on a slow connection you probably wouldn't see anything else for quite a while  because we forgot to minify and compress our JavaScript.  And when the site finally loaded, you wouldn't dare to click the browser back button in the middle of something  instead of the proprietary one provided by the app because all your stuff would be gone  and you would end up back at vg.no.  And you could forget about SEO unless you created a separate response  for Google or the other crawler bots using things like Phantom.js.  Things have gotten better now, though, with Google executing JavaScript and everything.  But let's look at the pros and cons of these two approaches.  So the good thing about server-endered pages and applications are that it's really easy to reason about  because you're serving a fresh page every time the user interacts with your application.  And you get all of that SEO stuff out of the box.  And the not-so-good things are that every action is a page refresh,  which means that you often have to load a lot of redundant data  because just a small part of the UI might change, but you reload everything.  And also all that refreshing gives you a poor user experience  if you have a very dynamic app where the user interacts with it a lot.  And the pros of the client-side single-page app is that you can now make really dynamic apps  that don't refresh for every user action.  And you have less redundancy because you're only updating the parts that change.  And you can create a much better user experience using asynchronous JavaScript.  And the not-so-good things about single-page apps is that since everything is happening in the browser,  there's no content before the client-side JavaScript has loaded,  which in turn might result in a poor perceived performance  as you'll first wait for that loading spinner to load, and then you'll wait for that application itself to load.  And if you need to have your pages indexed by crawlers, this can be a pain.  But I want it all, we say.  So we do a mix of server-side rendered pages with a dash of plain JavaScript,  some jQuery, and maybe some other favorite library or framework that magically makes our site come alive.  And the good thing about this approach is that it gets all of our stuff done,  and we can make that really cool application we want,  and we can get the benefits of both the server rendered pages and the client-side single-page app by hacking this together.  But the not-so-good thing is that you'll now have two separate code bases to maintain and to keep in sync.  You'll have a lot of implicit coupling between those server rendered results and the client-side JavaScript,  and this makes development harder and the chances of regression bigger.  Because what happens server-side and what happens client-side,  that divide can start to blur after a while if the app grows large in complexity.  And more often than not, this turns into a not-so-enjoyable experience.  So by covering that, I'm going to present a few bold statements.  So with isomorphic JavaScript applications, you can have all of the good parts of both the server-side rendering  and the client-side rendering in one package.  And at the same time, you'll have none of the cons mentioned.  This is a bit of a stretch, but I'm going to stick with it for now.  So as I said, we started experimenting with isomorphic JavaScript about a year ago  when we were making a new prototype for our mobile web application.  And the meaning of isomorphic in this context, it really just boils down to  that there's no more conceptual divide between the server and the client when it comes to the actual application code.  So this means that your JavaScript application can be rendered both on the server and on the client.  So this would be like the request flow for an isomorphic JavaScript application.  You would first get a request from the user via HTTP,  and the application then gets rendered on the server using your JavaScript application.  And the server then responds with the HTML generated from rendering your app server-side.  And then the client uses the same JavaScript code and takes over where the server left off.  So this approach requires us to use abstractions that are environment agnostic  in the sense that abstractions that doesn't care if it's running on the server or the client,  but it should work either way.  So what do we need to make this possible?  So there's a lot of options out there now which have a lot of the same capabilities,  but they solve the problem using very different approaches.  So I'll focus on the approach we've chosen at Sule, which is React.  And how many of you guys have used React or at least heard of React?  Yeah, cool.  So we chose React for our apps because we think it's a great tool to build user interfaces  in addition to having all of the stuff we need to make our apps isomorphic.  And it's also a big plus that in some form or another has been in production at Facebook since 2011,  and you simply can't find much better battle testing than that.  So the core selling point of React is that it enables you to build composable UI components  and that it helps you structure the UI part of your web application.  But let's look at how React facilitates isomorphic JavaScript apps.  So on the server, you would render your app to a string representation of the HTML  by using the render to string method.  And on the client, you would render your app to the DOM using another method called render.  And this means that you can now render your application both on the server and the client.  So, but instead of just talking about isomorphic JavaScript apps,  let's do a walkthrough of how you can actually build one.  So let's build a really simple isomorphic web app  and we'll build an app that fetches the 10 latest videos from NDC, from the Vimeo API,  and then show them in a horrible looking app.  So let's look at the building blocks for the app.  So for the server part, we'll use Node.js and the magic of NPM.  And this will give us the ability to run JavaScript code on the server.  And we'll use Express as a simple but powerful framework to serve our web application in Node.js.  And for the user interface part, we'll use React.  And for managing and building our client-side JavaScript, we'll use Webpack.  So for those of you who don't know Webpack, Webpack is a module bundler,  which in our case enables us to use the same kind of module system as Node.js in the browser.  So that we're able to use the same NPM packages.  And this is crucial to the isomorphic JavaScript approach  as we need to make our code runnable in the browser as well.  There's also a tool called Browserify that does the same thing in a slightly different way.  But for this example, we'll stick with Webpack because it's a bit easier to get the basics up and running.  So this should be everything that we need to make a simple isomorphic app.  And this is what our finished app should look like.  Simply just listing the 10 latest NDC videos from Vimeo using the Vimeo API.  So here's the folder structure of our application.  So we have a root folder which contains our Node.js server app script called App.js.  And we have a Webpack configuration file.  And then in addition to that, we have one folder for all of our React components.  And this is the actual Web app. Inside of components here, this is the actual Web app  which results in our HTML or DOM.  So we have another folder containing our different rendering code.  So we have one for the server and we have one for the client.  And we also have a folder containing a data fetching service,  which in our case is just a function to fetch the latest NDC videos from the Vimeo API.  So let's just go through each part and then just put this thing together  into an isomorphic JavaScript application.  So first of all, we have a React component called App,  which is the main container of our React application.  Can everyone see this?  So this only contains a render method.  And in this render method, we expect that whatever calls this component  will supply it with an array of data containing the metadata about the 10 latest videos from NDC.  And we'll map each of those array entries into video components  with the appropriate properties.  And that gives us an array of video components,  which we will then insert into an unordered list.  So this React component, this whole app, it just produces an unordered list in HTML,  just a UL element.  That's like the top element of this app.  And next up is a video component that we used in App.jsx.  So this component has a render method that generates a list item out of the data we passed to it  through the mapping we did in App.jsx.  So each video component is just a list item.  It's just an L-I element to be placed inside of a list.  And each list item has an image, a title, and a description.  And next up is the function we'll use to pull data from the Vimeo API.  It's just a simple function that uses an NPM module called Vimeo,  which simplifies fetching data from the Vimeo API.  So the result of calling this Vimeo.request function and supplying it some options and a callback  will in our case be an array of the 10 latest videos by NDC on Vimeo.  And next up is the render entry point that we're going to use server side.  So this is the function that will be called when the browser does a request to our application.  So in our server render entry point, we'll first use the service that we created  to fetch the 10 latest NDC videos as JSON.  And when we have that JSON data, we'll pass that to our React app component as a property.  And then we'll use React render to string to render our whole app to a string.  So the app markup variable here will just contain a string of HTML.  But let's take a closer look at the stuff in the middle here,  because this is where the magic of isomorphic gaps are.  So to make a complete HTML markup that we can deliver to the browser,  we'll use, in this case, we're using ES6 templating strings.  So finally in JavaScript, you're able to have multi-line strings  without doing this kind of concatenation with plus and all that stuff.  So let's see if this makes any sense.  So here we're just placing that markup generated by React render to string inside of a div element.  And we'll give that div element an ID of app so that we can fetch it again on the client.  So that means that what we're doing here is that we're just placing an unordered list inside of a div.  And in addition, we'll attach the video data we got from Vimeo to the document as a script element.  And this is popularly called dehydration, or you could call it serialization.  So we're stringifying that JavaScript object,  and we are attaching it to the global window variable, to a variable called underscore underscore app data.  And we need to do this because React has to have the same data available on the client that you have on the server.  So really, we're just bootstrapping the client-side application the same as we're doing on the server.  So we're just attaching data to the document.  And the last thing we'll do is to attach another script tag.  And this script tag will reference the client-side JavaScript bundle that we're going to build using Webpack,  which will package our app for running in the browser.  And in our case, this file is going to be called bundle.js.  And when all of this is done, we just ship this string of HTML as the result of the HTTP request we got from the browser.  And next up is the render entry point we're going to use on the client in the browser.  So when the client-side JavaScript has loaded in the browser,  we first want to make sure that the DOM is finished loading its content  by attaching our code as a callback to the DOM content loaded event.  So what happens then is that we should be able to access the data that we attached as a script element  when we rendered it on the server, as we'll need that data to be able to render our app correctly in the browser.  And this again is called, in the case of isomorphic JavaScript, this is often called rehydration.  But you can also say, unserealization or any other fancy word.  So on the server, you dehydrate data, and on the client, you rehydrate.  So you're kind of just passing data through the wire.  So now we can use the React render function and render the same app into the existing markup that we got from the server,  just by specifying the DOM element we want to hook into, which in our case was the div element with the idea of app.  And this won't actually render anything to the DOM, but it will just seamlessly hook into the existing DOM.  Now I'll explain why and how in a few slides.  So we'll go over to our server application, AppJS, which will run as a node process.  So the first thing we do here is just to import the modules that we need and then create an express app.  I've omitted these require and then module parts from the other files just to get it small enough.  And we then state that we want to, for every request for a static asset for which there's no route assignment,  we'll just look in the public folder.  And then we'll attach a single route handler for the root of our app,  which we'll use to, where we'll use our server render function to create a response for the user.  And the last part here is just attaching the express app to a port and start listening.  So last up is the configuration file for Webpack.  And this states how we want to bundle up the JavaScript we need for running our application in the browser.  So it just contains a simple JavaScript object that states our configuration.  And it looks like this.  So the first part named entry, it just states which file should be the entry point for our client side bundle.  And in our case, that would be the client.js file from the render folder.  And we also state that we want the output file to be placed in the public folder with the name of bundle.js.  And that way we can access this bundle through the static file serving that we set up in Express.  And the last part, it just states which loaders the source files should be transformed with.  And in our case, we're using both JSX in our React app.  And we're using a lot of new stuff from ECMAScript 6.  So a loader called Babel will transform all of that stuff into executable ES5 JavaScript in bundle.js for us.  So that we can be sure that this can run in any browser that supports at least ECMAScript 5.  So what happens is that Webpack processes client.js from the render folder.  And it bundles together all the scripts referenced in client.js as well as the NPM modules.  And then it creates a single browser bundle which contains everything that we need to run this in the browser.  And then it places it in the public folder as bundle.js.  And if we take a look at this by requesting it in the browser, it looks something like this,  containing a lot of Webpack-specific code in addition to our own.  So now we should have everything we need to get our app running.  So let's imagine that we run Webpack to package our client side the script first.  That means creating the public folder and inserting bundle.js.  Then we just start the app by using Node to run app.js.  And at the end we just open our browser to localhost 3000.  And this would be a result, the same list that we saw in the beginning.  But let's look at the Chrome debugger.  So here we can now see the markup we designed in our server rendering function.  We have our development containing the React rendered application.  We have the script tag where we attached the dehydrated data.  And we have a script tag where we tell the browser to load our client's JavaScript bundle that we made with Webpack.  And if we inspect the dehydrated data a bit closer, we'll see that it's just a JSON object,  which we have attached to the global window namespace as window.underscore.appdata.  And inside the development we now have our React app, which is just an unordered list containing list items.  But here we can also see some of the magic behind the isomorphic rendering in React.  Because when React renders something server-side, it attaches a checksum to the topmost element.  And when the same app is rendered in JavaScript on the client and you try to mount it into the DOM,  it'll do a diff against that checksum.  And if the checksum is identical, it will instead of re-rendering anything,  it'll just hook on to the existing DOM and then attach any applicable event handlers  or whatever React needs to control your app.  Basically just continuing where the server left off.  And if the checksum doesn't match, it'll discard the existing DOM that it got from the server.  And it'll give you an error message telling you that something is wrong  since your server and client-side rendering isn't corresponding.  And if you look at the scripts loaded by the network,  you'll see that our client-side bundle is loaded and that everything is working as it should be with no error messages.  So now we have a nice,omorphic JavaScript application.  A very bare-bones one that is, which doesn't really make any use of the fact that it's isomorphic.  But what's the point of all this?  So the great thing about isomorphic JavaScript, at least for us at Sule,  it hasn't been things like performance or load times or that we're able to use the latest hype,  even if that in itself is great.  But it's a developer experience and the maintainability  and how much easier it is to add features to our apps  since we now have the same code for both the server and the browser.  And that layer of abstraction, it creates so much more cohesion in the app  instead of having this completely separate JavaScript application manipulating a server-rendered result.  And that pretty much enabled us to quietly sneak our tangled mess of client-side JavaScript  with jQuery and all that stuff out the back door and just put it out of its misery.  And yeah, it feels like a level up.  And we're having a lot more fun in the process.  But just to sum up some of the good parts.  So the best thing about this is maintainability  because you now have everything in the same language and everything is the same code base.  Not everything is perfect because you still have to do all of that orchestration  around rendering on the server and on the client.  But in our case, that trade-off is a lot easier to make  because everything else is a single code base.  And there's no more messing around with phantom.js and all that stuff  to get crawlers to index your site because everything is rendered on the server as well.  And you get progressive enhancement out of the box.  So the initial response is created by the server.  And when the client-side JavaScript has loaded your page, then everything comes alive.  And I still haven't figured out the difference between progressive enhancement  and the graceful degradation, so I just put them both there.  But the best thing of all is that you're abstracting away the conceptual gap  between the server and the client.  Because it's kind of an artificial gap,  which makes it easier to not have to think about it.  So what I've showed you up to now isn't really enough to build a fully isomorphic JavaScript application  because there's several parts of an application that can be isomorphic.  And in our demo app, we just mainly looked at one of them, which is rendering.  And React has made it really simple for us to render an application both on the server and on the client.  And you get that support out of the box.  And by rendering here, I just simply mean something that is consumable by a browser,  either as HTML text response from a server or as DOM objects produced by JavaScript.  But there's another important part of web applications, which is routing.  And routing is also something that can happen both on the server and on the client.  And on the server, you would serve the appropriate page by looking at...  So in Node, this is the Request URL.  But in the browser, you would look at something like window location,  and you would use the history API to manipulate the location.  So making routing isomorphic would then mean to be able to use the same routing mechanism  both on the server and the client so that you're not replicating the routes for both the server and the client.  So, and this is exactly what React Router does.  So it's a community-made routing solution that works both on the server and on the client.  It uses the same API for both, for different inputs,  so that it enables you to reuse the same routes on both the server and the client.  And another pretty integral part of web applications is data fetching,  so requesting resources over HTTP.  On NPM, there's a module called Superagent,  and it's a great example of an isomorphic request library.  So doing an HTTP request on the server is very different from doing an HTTP request in the browser.  And Node.js has the built-in HTTP module to handle this,  and in the browser, you have the XML HTTP request.  So what Superagent does is to create a layer of abstraction on top of these two vastly different APIs,  and then it just exposes a single API on top so that this would work in both the server and the client.  So that means that you have two completely different implementations underneath,  but you have the same API on top.  So in Webpack or Browserify, packages, an app that uses Superagent,  there's a completely different piece of code being included in that bundle  than what is being used on the server.  Because the application, but the application that consumes that API  doesn't have to worry about being on the server or the client  because it will produce the same results either way.  So the rule in quotes for isomorphic applications is that all the abstractions you use inside of your app  has to be isomorphic, meaning that they have to work both on the server and the client  and producing the same results.  And if a library or a module doesn't depend on the environment it runs in,  then it's isomorphic by default.  So let's look at an example that is fully isomorphic,  meaning that it has isomorphic rendering, isomorphic routing, and isomorphic data fetching.  So let's see.  So here's an app we have running.  It's pretty much the same as the demo app that we were building earlier,  except it's just a bit more advanced.  So we can see that if we go back and forth here, now we're at the login page,  we have a signup page, you can go back to the landing,  and if we check, if we just observe like the fabric on the reload button here,  you can see that everything is happening client side.  So we're not reloading anything from the server here.  Everything is happening on the client, so the routing, everything happening on the client.  So let's try to sign up for this page doing something like...  So that automatically signed us into the page here.  So on the side here, we just have a list of videos that was loaded by the API.  We can browse through videos from NDC.  And still we can see that everything here is happening on the client.  And I think that if we open up the network tab here,  let's see, all...  Let's see that if we request... Oh, failed, that's not good.  Oh yeah, I have no internet, so the images started to fail when the cache went out.  Let's not disable cache then.  Okay, so you can see here at least that whenever I click something in the app,  it does another request to fetch the data for that item.  Yeah, so we can just log out.  But what happens if I just disable JavaScript in the browser?  Usually on a client-side app, that would just render a blank page, nothing.  Or if maybe an Angular app, you'd get the template flashed at you,  just like the naked template from Angular.  So we have disabled JavaScript.  Okay, the landing still works.  What about if I try to go to the login page?  Yeah, still works.  Now you can see that it's actually refreshing the page.  So now nothing can possibly happen on the client-side  because we've disabled all the browser JavaScript.  So let's see if I can sign up again.  Let's sign up.  Yeah, we're into the app.  I can still browse through here.  Some of the images work.  So now you can see that now everything is actually happening on the server.  And there's not any...  This is the same app.  There's no replication that we have the same thing on the server  and the same thing on the client, just two different code bases.  But it actually works even if you don't have client-side JavaScript.  So that means that this is where the progressive enhancement part comes in  because you can still use this app even if the JavaScript hasn't loaded on the client yet.  Because the sign in the login form,  if the client-side app hasn't attached any events yet,  then it's just a simple form that would send that login data  as a post request to your API.  Let's see.  So let's just do a recap of why isomorphic JavaScript is worth looking into.  So one thing is that you have a lot less context switching  because the application code for the server and the client are the same.  And it's all JavaScript.  And since we're sharing all the code, it's easier to maintain  because there's only one single place to change the code.  And you get the best of both server-side rendering and client-side rendering.  And an added bonus for us at Scandinavia Online has been that  we've been able to push features faster, although this is highly anecdotal.  So if you want to play around with any of the examples I've shown you today,  they're all available on GitHub.  And I'll post the slides and the links on Twitter afterwards.  And that pretty much concludes what I have to show you today,  finishing a bit early since everyone probably a bit tired.  So if anyone has any questions, then I'll be happy to answer.  Yeah, you...  Yeah, that's a really good question.  So the way we've solved this is that we have this API layer  so that everything is HTTP request.  So if we request any data from the database,  we have this layer of abstraction on top which uses SuperAgen in our case.  So because it wouldn't make sense to try to make like an SQL...  my SQL request or like a MongoDB request on the client  because that just doesn't make sense.  So that's why I was mentioning that everything has to be environment-agnostic,  like an abstraction layer on top.  Yeah.  So kind of like the opposite to that question.  So this works when your pages are kind of static and you're like following me.  If you have some pages that have like interaction  and that could only really be rendered with JavaScript,  how do you handle like if you use and navigate to that page  and your JavaScript hasn't loaded but they start interacting with the page?  Yeah, so that's...  So for example, if they're on a mobile connection  and you've got like, I don't know, something involving controls  that they can move to that settings and they start doing that,  because also you can't like shift the jazz on the server.  No.  Do you like repress directions when your JavaScript fits in or...?  So we've been experimenting with some approaches there  because that's the issue, right?  Some things you just can't replicate simply by doing everything on the server.  So to try to kind of get the best out of that,  we can make every button a form so that every action on the site is a form.  So if the client-side JavaScript hasn't loaded yet,  you're firing off a form request, like a post or anything to your API.  That would then like handle this on the server and give you back the correct results.  But if you have things like sliders or anything that is like purely JavaScript,  that has to be...  that has to wait for the client-side JavaScript to load.  So some things you can't replicate.  Like are we thinking you could use jQuery to attach to clickable elements to then store click events,  which you can then replay against the IT React tips then?  But I don't know if there's anyone solved the problem so far.  At least I haven't solved it properly yet.  It's really good when you have your home page as your landing page.  It's like basically just a fancy version of the spinner.  Like if your home page is your app, like the kind of interaction basically you have.  Like for example, you go to Facebook and it's like your wall.  And if you start interacting with it but it's not loaded, how do you deal with that?  Yeah, so that's what I was talking about.  So say that you had the Facebook page.  The Facebook page is a great example that could be isomorphic.  And in fact, for a long time, Instagram.com was fully isomorphic.  So that means that if you've loaded your news feed on Facebook,  and you want to click like on a post,  but if the JavaScript hasn't loaded, that click has to be a post request  that goes to the server and then redirects you back and then shows you like the updated state.  So that's basically how I solved this one is that in like the React component  where I used a form, I attach a form action so that if the JavaScript hasn't loaded,  it's just a regular form instead of an event that is triggered.  So yeah, there's a lot of like tricks you can use, but yeah,  I think it would be hard to get like a one to one conversion there.  But it's fun though.  Yeah.  My question is kind of related to that. And it's really how do you integrate with the third party, front end, library, like for example, in your app,  what if you wanted your video component to actually use video.js because you wanted to have a fancy player for the videos instead of just a static image.  How does that affect server side rendering? Obviously they can't render on the server.  Yeah, that's a good question.  So, yeah, he was wondering, so what if you wanted to use some JavaScript libraries to like spruce up your app,  like using video.js to render the videos or something, because you obviously couldn't do that on the server side.  But yeah, as I said, it's hard to replicate everything back to the server.  That's why some things are just purely client side, but those things will just be ignored on the server because React has these life cycle events  and some of them only run on the server, some of them run on the client and the server, and some of them run just on the client.  So it's just a matter of where you attach those things.  So that means that from the server, it could just be an image or it could be like an HTML5 video element.  And when you arrive at the client, that would just take over and like enhance whatever you have there to.  How does that work in the case you mentioned that checks some that errors out when the two DOMs don't match.  So, I mean, I don't know, forget about video.js specifically.  But suppose it's just some library that modifies the DOM as part of the rendering on the client, you know, fancy select or something like that.  So now longer it's the same, it's not even the same DOM that was rendered on the server.  There's a bunch of other elements rendered by this third party library, which is pretty common.  Yeah, yeah, yeah.  How does that work in the case of?  Yeah, should I repeat the question?  Yeah, so he was asking what if you, for example, want to use jQuery to manipulate some of the DOM elements that has been rendered on the server.  Will that like affect the fact that the checksum would be different or that you would kind of miss that isomorphic thing.  So when it arrives at the client, it'll just do the exact same rendering that it did on the server so that none of that stuff,  like the purely client side stuff will run on that initial render.  So when that has rendered and the component lifecycle method that explains that now your app has mounted into the DOM,  whatever happens next, it doesn't affect that stage of the rendering.  So you're kind of just trying to pick up where the server left off and then, yeah, it's like, yeah, you could just call it progressive enhancement from there on.  Any more questions?  Yeah.  Yeah, so, yeah, that's the, so you're thinking about stuff like Polymer or Web Components.  Yeah, because as you say, Web Components or Polymer can just, it's just a purely client side thing, just like Angular or jQuery or, yeah.  So that obviously wouldn't be suitable for this kind of isomorphic approach.  But I think that React here and Polymer and Web Components are trying to solve kind of the same thing but different because React is much more of a complete UI library.  Whereas I see Web Components and Polymer more as a really good way to make this kind of isolated components that you want to drop in anywhere that you want them.  And you could easily use Web Components together with React.js, like say that nothing is rendered on the server, but as soon as it gets on the client, you inject a Web Component that you have ready.  So, yeah, I see your point there. And yeah, I'm not sure what Web Components or Polymer is going to be.  I'm just curious, I guess I would love to hear people talk about that more because it seems like it's a bit of a conflict.  We had a crisis meeting at work recently where the debate was Polymer versus React.  And for now, the safe answer is, okay, both.  I have a question kind of related to the last one, related to your crisis meeting at work. So we're using React and isomorphic stuff on my project.  And we're doing it for SEO, server side rendering and then rich user interface on the client.  It's working really well, but just like you're talking about, what are some of the practical difficulties you've run into?  Tell me more about which stuff have you run into at work where you have more crisis meetings.  How are we going to solve this? And maybe something that you didn't want to talk about today because there's such a problem.  Or maybe there's none.  I think the main issue with us using isomorphic React is kind of not understanding what it is because there's been a lot of confusion.  What happens on the server and what happens on the client?  And when you try to include MongoDB and attach it to your client script, weird stuff started to happen.  Like everything works on the server and when it arrives on the client, everything is borked.  Just getting your head around what isomorphic JavaScript is and what you're trying to solve by making that abstraction has kind of been, yeah, like the main problem.  But I don't know any specific issues. If you have a more specific question, then that would be awesome.  I want to hear more about crisis stories.  Yeah, maybe afterwards.  That's a good sign if you haven't heard anything.  Yeah, that's kind of the best thing about this is that we've just had a lot more fun developing our apps because earlier the issue has been that we wanted to do, if we wanted to do like fun real time stuff or just dynamic JavaScript stuff,  the issue has been that we have to slap on some kind of thing on top of that server-rendered result. But now we can just do it from scratch and all of that fancy stuff just doesn't happen until you actually reach the client.  You don't have to think about that divide anymore.  Everything is in the same place. Any more questions?  Yeah.  Yeah.  Yeah.  Yeah.  So actually the project that has benefited most from this, at least using React, is different kind of internal tools we have like admin interfaces and that kind of stuff.  And we've been using React and Flux there now and it has just made everything so much easier, just easier to kind of structure your app and mitigate errors.  But there again, we don't use the isomorphic approach because why would we need isomorphic on our internal admin app?  So you might have a point there that this is mostly useful in apps where you need to have stuff rendered on the server first.  And the kind of the last example I've showed you there is probably not that useful for everyone.  But yeah, mostly for the case where you want to make a single page app but you also want to have this rendered on the server because you're indexing stuff.  So yeah, I guess that's a good point.  So any more questions?  Okay, thanks for listening.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.
Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_0_2231.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_2232_2663.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_2664_8783.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_8784_13847.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_13848_15743.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_15744_15959.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_15960_16247.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_16248_16379.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_16380_18563.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_18564_18731.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_18732_19847.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_19848_22403.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_22404_22775.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_22776_24431.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_24432_26447.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_26448_26975.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_26976_28259.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_28260_29159.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_29160_29363.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_29364_35459.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_35460_35735.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_35736_36179.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_36180_36227.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_36228_37595.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_37596_37811.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_37812_38039.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_38040_39827.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_39828_42407.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_42408_43823.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_43824_47531.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_47532_49475.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_49476_52847.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_52848_54995.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_54996_56099.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_56100_58319.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_58320_58595.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_58596_59015.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_59016_60299.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_60300_60515.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_60516_60695.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_60696_61955.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_61956_62003.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_62004_62375.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_62376_62435.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_62436_63803.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_63804_63899.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_63900_63995.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_63996_64727.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_64728_64823.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_64824_65063.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_65064_65147.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_65148_66035.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_66036_67199.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_67200_93119.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_93120_93203.png Building_Isomorphic_Applications_in_JavaScript_-_Eirik_Langholm_Vullum_93204_99836.png
Okay, so, hi everyone. You hear me? Okay, so I'm here today to talk about isomorphic JavaScript applications and what that string of words mean, why you should be excited about it and how you can build one. So, my name is Erik Vullum and I'm a tech lead at Scandinavia Online where we do a lot of JavaScript development, yeah, web development. So, you might remember Scandinavia Online as good old Sule dot NO, one of the trusted gateways of the Norwegian parts of the internet in a not so distant past. Times have changed and today we're a news aggregator and a technology company where we do a lot of JavaScript development. So at Scandinavia Online we started experimenting with isomorphic JavaScript about a year ago, just about the same time that we started playing with Facebook's React library. And through this talk I'll hopefully get to show you why we've continued on that path and why we think that it's great. So what is all this fuss about isomorphic JavaScript apps and why should you care? Is it just another fad or does it actually have some practical use to make your apps and your life as a developer better? And I know it's a huge buzzword alert. And as I said earlier, we do a lot of JavaScript development at Sule and I have a lot of empathy for fellow JavaScript developers. But I feel outright sorry for those who are just getting into JavaScript. There's so much happening that you can barely follow along unless you live on hacker news, GitHub or at tech conferences. And so how many days has there been since the last JavaScript framework? Just guessing. I would guess about zero by a fair margin. Also about every day there's a new JavaScript framework in some form or another. Ryan Florence came up with this fancy name here in the talk he had. And the same goes for buzzwords in web development. About every week there's a new buzzword that you have to learn about. It's both amazing and terrifying at the same time. And this gives me the opportunity to show you one of my favorite Norwegian comedy sketches that shows you how I often feel in the world of web development. And I hope it's not just me. Five of I'm sure you're cool! I'm sure you're cool! I'm sure you're cool! I didn't know what the fuck I'm sure you're cool! I just gave him some tape rast! I'm sure you're cool! Oh, you're flirty! Here's the one who came back! I don't know what he gave me but it was wrong. So then I just had to take a wild shot and I said the word. Camelosa? I should say Cameloso! Camelosa! I didn't know what Camelosa was. In general, I must say it's not a nice cramped store and nobody knows what things are called. So I guess if you replace ice and cramped store with web development, it's a pretty decent translation. But even if isomorphic JavaScript sounds terrifying, it isn't that scary actually. So at least I'll give it my best shot to explain what it's all about. So in the context of web development, it simply describes JavaScript code that can run in several environments. And those environments could be on a server running on Node.js. It could be on a client running in a web browser. Or it could be other JavaScript runtimes like JavaScript Core on an iOS device. So we can say that isomorphic JavaScript is environment agnostic as we're abstracting away the environment and the differences from the application itself. And later on we're going to see why this is handy. But before I go any deeper, let's first take a step back and look at the status before we started talking about isomorphic web applications. So old-school server rendered pages. Think ASP.net, PHP, any other server-side rendering language. You would just re-render the whole thing on each request, just ship a new page from scratch. And that's really easy to reason about. But the user experience starts to suffer as your application grows in complexity because every action is a refresh. And that just wasn't good enough. So we wanted more dynamic web pages that didn't refresh every time we clicked a button to submit a form. And then came Ajax and the single-page app. And that meant dynamic web pages without any reloads. And the infamous loading spinner. So on a slow connection you probably wouldn't see anything else for quite a while because we forgot to minify and compress our JavaScript. And when the site finally loaded, you wouldn't dare to click the browser back button in the middle of something instead of the proprietary one provided by the app because all your stuff would be gone and you would end up back at vg.no. And you could forget about SEO unless you created a separate response for Google or the other crawler bots using things like Phantom.js. Things have gotten better now, though, with Google executing JavaScript and everything. But let's look at the pros and cons of these two approaches. So the good thing about server-endered pages and applications are that it's really easy to reason about because you're serving a fresh page every time the user interacts with your application. And you get all of that SEO stuff out of the box. And the not-so-good things are that every action is a page refresh, which means that you often have to load a lot of redundant data because just a small part of the UI might change, but you reload everything. And also all that refreshing gives you a poor user experience if you have a very dynamic app where the user interacts with it a lot. And the pros of the client-side single-page app is that you can now make really dynamic apps that don't refresh for every user action. And you have less redundancy because you're only updating the parts that change. And you can create a much better user experience using asynchronous JavaScript. And the not-so-good things about single-page apps is that since everything is happening in the browser, there's no content before the client-side JavaScript has loaded, which in turn might result in a poor perceived performance as you'll first wait for that loading spinner to load, and then you'll wait for that application itself to load. And if you need to have your pages indexed by crawlers, this can be a pain. But I want it all, we say. So we do a mix of server-side rendered pages with a dash of plain JavaScript, some jQuery, and maybe some other favorite library or framework that magically makes our site come alive. And the good thing about this approach is that it gets all of our stuff done, and we can make that really cool application we want, and we can get the benefits of both the server rendered pages and the client-side single-page app by hacking this together. But the not-so-good thing is that you'll now have two separate code bases to maintain and to keep in sync. You'll have a lot of implicit coupling between those server rendered results and the client-side JavaScript, and this makes development harder and the chances of regression bigger. Because what happens server-side and what happens client-side, that divide can start to blur after a while if the app grows large in complexity. And more often than not, this turns into a not-so-enjoyable experience. So by covering that, I'm going to present a few bold statements. So with isomorphic JavaScript applications, you can have all of the good parts of both the server-side rendering and the client-side rendering in one package. And at the same time, you'll have none of the cons mentioned. This is a bit of a stretch, but I'm going to stick with it for now. So as I said, we started experimenting with isomorphic JavaScript about a year ago when we were making a new prototype for our mobile web application. And the meaning of isomorphic in this context, it really just boils down to that there's no more conceptual divide between the server and the client when it comes to the actual application code. So this means that your JavaScript application can be rendered both on the server and on the client. So this would be like the request flow for an isomorphic JavaScript application. You would first get a request from the user via HTTP, and the application then gets rendered on the server using your JavaScript application. And the server then responds with the HTML generated from rendering your app server-side. And then the client uses the same JavaScript code and takes over where the server left off. So this approach requires us to use abstractions that are environment agnostic in the sense that abstractions that doesn't care if it's running on the server or the client, but it should work either way. So what do we need to make this possible? So there's a lot of options out there now which have a lot of the same capabilities, but they solve the problem using very different approaches. So I'll focus on the approach we've chosen at Sule, which is React. And how many of you guys have used React or at least heard of React? Yeah, cool. So we chose React for our apps because we think it's a great tool to build user interfaces in addition to having all of the stuff we need to make our apps isomorphic. And it's also a big plus that in some form or another has been in production at Facebook since 2011, and you simply can't find much better battle testing than that. So the core selling point of React is that it enables you to build composable UI components and that it helps you structure the UI part of your web application. But let's look at how React facilitates isomorphic JavaScript apps. So on the server, you would render your app to a string representation of the HTML by using the render to string method. And on the client, you would render your app to the DOM using another method called render. And this means that you can now render your application both on the server and the client. So, but instead of just talking about isomorphic JavaScript apps, let's do a walkthrough of how you can actually build one. So let's build a really simple isomorphic web app and we'll build an app that fetches the 10 latest videos from NDC, from the Vimeo API, and then show them in a horrible looking app. So let's look at the building blocks for the app. So for the server part, we'll use Node.js and the magic of NPM. And this will give us the ability to run JavaScript code on the server. And we'll use Express as a simple but powerful framework to serve our web application in Node.js. And for the user interface part, we'll use React. And for managing and building our client-side JavaScript, we'll use Webpack. So for those of you who don't know Webpack, Webpack is a module bundler, which in our case enables us to use the same kind of module system as Node.js in the browser. So that we're able to use the same NPM packages. And this is crucial to the isomorphic JavaScript approach as we need to make our code runnable in the browser as well. There's also a tool called Browserify that does the same thing in a slightly different way. But for this example, we'll stick with Webpack because it's a bit easier to get the basics up and running. So this should be everything that we need to make a simple isomorphic app. And this is what our finished app should look like. Simply just listing the 10 latest NDC videos from Vimeo using the Vimeo API. So here's the folder structure of our application. So we have a root folder which contains our Node.js server app script called App.js. And we have a Webpack configuration file. And then in addition to that, we have one folder for all of our React components. And this is the actual Web app. Inside of components here, this is the actual Web app which results in our HTML or DOM. So we have another folder containing our different rendering code. So we have one for the server and we have one for the client. And we also have a folder containing a data fetching service, which in our case is just a function to fetch the latest NDC videos from the Vimeo API. So let's just go through each part and then just put this thing together into an isomorphic JavaScript application. So first of all, we have a React component called App, which is the main container of our React application. Can everyone see this? So this only contains a render method. And in this render method, we expect that whatever calls this component will supply it with an array of data containing the metadata about the 10 latest videos from NDC. And we'll map each of those array entries into video components with the appropriate properties. And that gives us an array of video components, which we will then insert into an unordered list. So this React component, this whole app, it just produces an unordered list in HTML, just a UL element. That's like the top element of this app. And next up is a video component that we used in App.jsx. So this component has a render method that generates a list item out of the data we passed to it through the mapping we did in App.jsx. So each video component is just a list item. It's just an L-I element to be placed inside of a list. And each list item has an image, a title, and a description. And next up is the function we'll use to pull data from the Vimeo API. It's just a simple function that uses an NPM module called Vimeo, which simplifies fetching data from the Vimeo API. So the result of calling this Vimeo.request function and supplying it some options and a callback will in our case be an array of the 10 latest videos by NDC on Vimeo. And next up is the render entry point that we're going to use server side. So this is the function that will be called when the browser does a request to our application. So in our server render entry point, we'll first use the service that we created to fetch the 10 latest NDC videos as JSON. And when we have that JSON data, we'll pass that to our React app component as a property. And then we'll use React render to string to render our whole app to a string. So the app markup variable here will just contain a string of HTML. But let's take a closer look at the stuff in the middle here, because this is where the magic of isomorphic gaps are. So to make a complete HTML markup that we can deliver to the browser, we'll use, in this case, we're using ES6 templating strings. So finally in JavaScript, you're able to have multi-line strings without doing this kind of concatenation with plus and all that stuff. So let's see if this makes any sense. So here we're just placing that markup generated by React render to string inside of a div element. And we'll give that div element an ID of app so that we can fetch it again on the client. So that means that what we're doing here is that we're just placing an unordered list inside of a div. And in addition, we'll attach the video data we got from Vimeo to the document as a script element. And this is popularly called dehydration, or you could call it serialization. So we're stringifying that JavaScript object, and we are attaching it to the global window variable, to a variable called underscore underscore app data. And we need to do this because React has to have the same data available on the client that you have on the server. So really, we're just bootstrapping the client-side application the same as we're doing on the server. So we're just attaching data to the document. And the last thing we'll do is to attach another script tag. And this script tag will reference the client-side JavaScript bundle that we're going to build using Webpack, which will package our app for running in the browser. And in our case, this file is going to be called bundle.js. And when all of this is done, we just ship this string of HTML as the result of the HTTP request we got from the browser. And next up is the render entry point we're going to use on the client in the browser. So when the client-side JavaScript has loaded in the browser, we first want to make sure that the DOM is finished loading its content by attaching our code as a callback to the DOM content loaded event. So what happens then is that we should be able to access the data that we attached as a script element when we rendered it on the server, as we'll need that data to be able to render our app correctly in the browser. And this again is called, in the case of isomorphic JavaScript, this is often called rehydration. But you can also say, unserealization or any other fancy word. So on the server, you dehydrate data, and on the client, you rehydrate. So you're kind of just passing data through the wire. So now we can use the React render function and render the same app into the existing markup that we got from the server, just by specifying the DOM element we want to hook into, which in our case was the div element with the idea of app. And this won't actually render anything to the DOM, but it will just seamlessly hook into the existing DOM. Now I'll explain why and how in a few slides. So we'll go over to our server application, AppJS, which will run as a node process. So the first thing we do here is just to import the modules that we need and then create an express app. I've omitted these require and then module parts from the other files just to get it small enough. And we then state that we want to, for every request for a static asset for which there's no route assignment, we'll just look in the public folder. And then we'll attach a single route handler for the root of our app, which we'll use to, where we'll use our server render function to create a response for the user. And the last part here is just attaching the express app to a port and start listening. So last up is the configuration file for Webpack. And this states how we want to bundle up the JavaScript we need for running our application in the browser. So it just contains a simple JavaScript object that states our configuration. And it looks like this. So the first part named entry, it just states which file should be the entry point for our client side bundle. And in our case, that would be the client.js file from the render folder. And we also state that we want the output file to be placed in the public folder with the name of bundle.js. And that way we can access this bundle through the static file serving that we set up in Express. And the last part, it just states which loaders the source files should be transformed with. And in our case, we're using both JSX in our React app. And we're using a lot of new stuff from ECMAScript 6. So a loader called Babel will transform all of that stuff into executable ES5 JavaScript in bundle.js for us. So that we can be sure that this can run in any browser that supports at least ECMAScript 5. So what happens is that Webpack processes client.js from the render folder. And it bundles together all the scripts referenced in client.js as well as the NPM modules. And then it creates a single browser bundle which contains everything that we need to run this in the browser. And then it places it in the public folder as bundle.js. And if we take a look at this by requesting it in the browser, it looks something like this, containing a lot of Webpack-specific code in addition to our own. So now we should have everything we need to get our app running. So let's imagine that we run Webpack to package our client side the script first. That means creating the public folder and inserting bundle.js. Then we just start the app by using Node to run app.js. And at the end we just open our browser to localhost 3000. And this would be a result, the same list that we saw in the beginning. But let's look at the Chrome debugger. So here we can now see the markup we designed in our server rendering function. We have our development containing the React rendered application. We have the script tag where we attached the dehydrated data. And we have a script tag where we tell the browser to load our client's JavaScript bundle that we made with Webpack. And if we inspect the dehydrated data a bit closer, we'll see that it's just a JSON object, which we have attached to the global window namespace as window.underscore.appdata. And inside the development we now have our React app, which is just an unordered list containing list items. But here we can also see some of the magic behind the isomorphic rendering in React. Because when React renders something server-side, it attaches a checksum to the topmost element. And when the same app is rendered in JavaScript on the client and you try to mount it into the DOM, it'll do a diff against that checksum. And if the checksum is identical, it will instead of re-rendering anything, it'll just hook on to the existing DOM and then attach any applicable event handlers or whatever React needs to control your app. Basically just continuing where the server left off. And if the checksum doesn't match, it'll discard the existing DOM that it got from the server. And it'll give you an error message telling you that something is wrong since your server and client-side rendering isn't corresponding. And if you look at the scripts loaded by the network, you'll see that our client-side bundle is loaded and that everything is working as it should be with no error messages. So now we have a nice,omorphic JavaScript application. A very bare-bones one that is, which doesn't really make any use of the fact that it's isomorphic. But what's the point of all this? So the great thing about isomorphic JavaScript, at least for us at Sule, it hasn't been things like performance or load times or that we're able to use the latest hype, even if that in itself is great. But it's a developer experience and the maintainability and how much easier it is to add features to our apps since we now have the same code for both the server and the browser. And that layer of abstraction, it creates so much more cohesion in the app instead of having this completely separate JavaScript application manipulating a server-rendered result. And that pretty much enabled us to quietly sneak our tangled mess of client-side JavaScript with jQuery and all that stuff out the back door and just put it out of its misery. And yeah, it feels like a level up. And we're having a lot more fun in the process. But just to sum up some of the good parts. So the best thing about this is maintainability because you now have everything in the same language and everything is the same code base. Not everything is perfect because you still have to do all of that orchestration around rendering on the server and on the client. But in our case, that trade-off is a lot easier to make because everything else is a single code base. And there's no more messing around with phantom.js and all that stuff to get crawlers to index your site because everything is rendered on the server as well. And you get progressive enhancement out of the box. So the initial response is created by the server. And when the client-side JavaScript has loaded your page, then everything comes alive. And I still haven't figured out the difference between progressive enhancement and the graceful degradation, so I just put them both there. But the best thing of all is that you're abstracting away the conceptual gap between the server and the client. Because it's kind of an artificial gap, which makes it easier to not have to think about it. So what I've showed you up to now isn't really enough to build a fully isomorphic JavaScript application because there's several parts of an application that can be isomorphic. And in our demo app, we just mainly looked at one of them, which is rendering. And React has made it really simple for us to render an application both on the server and on the client. And you get that support out of the box. And by rendering here, I just simply mean something that is consumable by a browser, either as HTML text response from a server or as DOM objects produced by JavaScript. But there's another important part of web applications, which is routing. And routing is also something that can happen both on the server and on the client. And on the server, you would serve the appropriate page by looking at... So in Node, this is the Request URL. But in the browser, you would look at something like window location, and you would use the history API to manipulate the location. So making routing isomorphic would then mean to be able to use the same routing mechanism both on the server and the client so that you're not replicating the routes for both the server and the client. So, and this is exactly what React Router does. So it's a community-made routing solution that works both on the server and on the client. It uses the same API for both, for different inputs, so that it enables you to reuse the same routes on both the server and the client. And another pretty integral part of web applications is data fetching, so requesting resources over HTTP. On NPM, there's a module called Superagent, and it's a great example of an isomorphic request library. So doing an HTTP request on the server is very different from doing an HTTP request in the browser. And Node.js has the built-in HTTP module to handle this, and in the browser, you have the XML HTTP request. So what Superagent does is to create a layer of abstraction on top of these two vastly different APIs, and then it just exposes a single API on top so that this would work in both the server and the client. So that means that you have two completely different implementations underneath, but you have the same API on top. So in Webpack or Browserify, packages, an app that uses Superagent, there's a completely different piece of code being included in that bundle than what is being used on the server. Because the application, but the application that consumes that API doesn't have to worry about being on the server or the client because it will produce the same results either way. So the rule in quotes for isomorphic applications is that all the abstractions you use inside of your app has to be isomorphic, meaning that they have to work both on the server and the client and producing the same results. And if a library or a module doesn't depend on the environment it runs in, then it's isomorphic by default. So let's look at an example that is fully isomorphic, meaning that it has isomorphic rendering, isomorphic routing, and isomorphic data fetching. So let's see. So here's an app we have running. It's pretty much the same as the demo app that we were building earlier, except it's just a bit more advanced. So we can see that if we go back and forth here, now we're at the login page, we have a signup page, you can go back to the landing, and if we check, if we just observe like the fabric on the reload button here, you can see that everything is happening client side. So we're not reloading anything from the server here. Everything is happening on the client, so the routing, everything happening on the client. So let's try to sign up for this page doing something like... So that automatically signed us into the page here. So on the side here, we just have a list of videos that was loaded by the API. We can browse through videos from NDC. And still we can see that everything here is happening on the client. And I think that if we open up the network tab here, let's see, all... Let's see that if we request... Oh, failed, that's not good. Oh yeah, I have no internet, so the images started to fail when the cache went out. Let's not disable cache then. Okay, so you can see here at least that whenever I click something in the app, it does another request to fetch the data for that item. Yeah, so we can just log out. But what happens if I just disable JavaScript in the browser? Usually on a client-side app, that would just render a blank page, nothing. Or if maybe an Angular app, you'd get the template flashed at you, just like the naked template from Angular. So we have disabled JavaScript. Okay, the landing still works. What about if I try to go to the login page? Yeah, still works. Now you can see that it's actually refreshing the page. So now nothing can possibly happen on the client-side because we've disabled all the browser JavaScript. So let's see if I can sign up again. Let's sign up. Yeah, we're into the app. I can still browse through here. Some of the images work. So now you can see that now everything is actually happening on the server. And there's not any... This is the same app. There's no replication that we have the same thing on the server and the same thing on the client, just two different code bases. But it actually works even if you don't have client-side JavaScript. So that means that this is where the progressive enhancement part comes in because you can still use this app even if the JavaScript hasn't loaded on the client yet. Because the sign in the login form, if the client-side app hasn't attached any events yet, then it's just a simple form that would send that login data as a post request to your API. Let's see. So let's just do a recap of why isomorphic JavaScript is worth looking into. So one thing is that you have a lot less context switching because the application code for the server and the client are the same. And it's all JavaScript. And since we're sharing all the code, it's easier to maintain because there's only one single place to change the code. And you get the best of both server-side rendering and client-side rendering. And an added bonus for us at Scandinavia Online has been that we've been able to push features faster, although this is highly anecdotal. So if you want to play around with any of the examples I've shown you today, they're all available on GitHub. And I'll post the slides and the links on Twitter afterwards. And that pretty much concludes what I have to show you today, finishing a bit early since everyone probably a bit tired. So if anyone has any questions, then I'll be happy to answer. Yeah, you... Yeah, that's a really good question. So the way we've solved this is that we have this API layer so that everything is HTTP request. So if we request any data from the database, we have this layer of abstraction on top which uses SuperAgen in our case. So because it wouldn't make sense to try to make like an SQL... my SQL request or like a MongoDB request on the client because that just doesn't make sense. So that's why I was mentioning that everything has to be environment-agnostic, like an abstraction layer on top. Yeah. So kind of like the opposite to that question. So this works when your pages are kind of static and you're like following me. If you have some pages that have like interaction and that could only really be rendered with JavaScript, how do you handle like if you use and navigate to that page and your JavaScript hasn't loaded but they start interacting with the page? Yeah, so that's... So for example, if they're on a mobile connection and you've got like, I don't know, something involving controls that they can move to that settings and they start doing that, because also you can't like shift the jazz on the server. No. Do you like repress directions when your JavaScript fits in or...? So we've been experimenting with some approaches there because that's the issue, right? Some things you just can't replicate simply by doing everything on the server. So to try to kind of get the best out of that, we can make every button a form so that every action on the site is a form. So if the client-side JavaScript hasn't loaded yet, you're firing off a form request, like a post or anything to your API. That would then like handle this on the server and give you back the correct results. But if you have things like sliders or anything that is like purely JavaScript, that has to be... that has to wait for the client-side JavaScript to load. So some things you can't replicate. Like are we thinking you could use jQuery to attach to clickable elements to then store click events, which you can then replay against the IT React tips then? But I don't know if there's anyone solved the problem so far. At least I haven't solved it properly yet. It's really good when you have your home page as your landing page. It's like basically just a fancy version of the spinner. Like if your home page is your app, like the kind of interaction basically you have. Like for example, you go to Facebook and it's like your wall. And if you start interacting with it but it's not loaded, how do you deal with that? Yeah, so that's what I was talking about. So say that you had the Facebook page. The Facebook page is a great example that could be isomorphic. And in fact, for a long time, Instagram.com was fully isomorphic. So that means that if you've loaded your news feed on Facebook, and you want to click like on a post, but if the JavaScript hasn't loaded, that click has to be a post request that goes to the server and then redirects you back and then shows you like the updated state. So that's basically how I solved this one is that in like the React component where I used a form, I attach a form action so that if the JavaScript hasn't loaded, it's just a regular form instead of an event that is triggered. So yeah, there's a lot of like tricks you can use, but yeah, I think it would be hard to get like a one to one conversion there. But it's fun though. Yeah. My question is kind of related to that. And it's really how do you integrate with the third party, front end, library, like for example, in your app, what if you wanted your video component to actually use video.js because you wanted to have a fancy player for the videos instead of just a static image. How does that affect server side rendering? Obviously they can't render on the server. Yeah, that's a good question. So, yeah, he was wondering, so what if you wanted to use some JavaScript libraries to like spruce up your app, like using video.js to render the videos or something, because you obviously couldn't do that on the server side. But yeah, as I said, it's hard to replicate everything back to the server. That's why some things are just purely client side, but those things will just be ignored on the server because React has these life cycle events and some of them only run on the server, some of them run on the client and the server, and some of them run just on the client. So it's just a matter of where you attach those things. So that means that from the server, it could just be an image or it could be like an HTML5 video element. And when you arrive at the client, that would just take over and like enhance whatever you have there to. How does that work in the case you mentioned that checks some that errors out when the two DOMs don't match. So, I mean, I don't know, forget about video.js specifically. But suppose it's just some library that modifies the DOM as part of the rendering on the client, you know, fancy select or something like that. So now longer it's the same, it's not even the same DOM that was rendered on the server. There's a bunch of other elements rendered by this third party library, which is pretty common. Yeah, yeah, yeah. How does that work in the case of? Yeah, should I repeat the question? Yeah, so he was asking what if you, for example, want to use jQuery to manipulate some of the DOM elements that has been rendered on the server. Will that like affect the fact that the checksum would be different or that you would kind of miss that isomorphic thing. So when it arrives at the client, it'll just do the exact same rendering that it did on the server so that none of that stuff, like the purely client side stuff will run on that initial render. So when that has rendered and the component lifecycle method that explains that now your app has mounted into the DOM, whatever happens next, it doesn't affect that stage of the rendering. So you're kind of just trying to pick up where the server left off and then, yeah, it's like, yeah, you could just call it progressive enhancement from there on. Any more questions? Yeah. Yeah, so, yeah, that's the, so you're thinking about stuff like Polymer or Web Components. Yeah, because as you say, Web Components or Polymer can just, it's just a purely client side thing, just like Angular or jQuery or, yeah. So that obviously wouldn't be suitable for this kind of isomorphic approach. But I think that React here and Polymer and Web Components are trying to solve kind of the same thing but different because React is much more of a complete UI library. Whereas I see Web Components and Polymer more as a really good way to make this kind of isolated components that you want to drop in anywhere that you want them. And you could easily use Web Components together with React.js, like say that nothing is rendered on the server, but as soon as it gets on the client, you inject a Web Component that you have ready. So, yeah, I see your point there. And yeah, I'm not sure what Web Components or Polymer is going to be. I'm just curious, I guess I would love to hear people talk about that more because it seems like it's a bit of a conflict. We had a crisis meeting at work recently where the debate was Polymer versus React. And for now, the safe answer is, okay, both. I have a question kind of related to the last one, related to your crisis meeting at work. So we're using React and isomorphic stuff on my project. And we're doing it for SEO, server side rendering and then rich user interface on the client. It's working really well, but just like you're talking about, what are some of the practical difficulties you've run into? Tell me more about which stuff have you run into at work where you have more crisis meetings. How are we going to solve this? And maybe something that you didn't want to talk about today because there's such a problem. Or maybe there's none. I think the main issue with us using isomorphic React is kind of not understanding what it is because there's been a lot of confusion. What happens on the server and what happens on the client? And when you try to include MongoDB and attach it to your client script, weird stuff started to happen. Like everything works on the server and when it arrives on the client, everything is borked. Just getting your head around what isomorphic JavaScript is and what you're trying to solve by making that abstraction has kind of been, yeah, like the main problem. But I don't know any specific issues. If you have a more specific question, then that would be awesome. I want to hear more about crisis stories. Yeah, maybe afterwards. That's a good sign if you haven't heard anything. Yeah, that's kind of the best thing about this is that we've just had a lot more fun developing our apps because earlier the issue has been that we wanted to do, if we wanted to do like fun real time stuff or just dynamic JavaScript stuff, the issue has been that we have to slap on some kind of thing on top of that server-rendered result. But now we can just do it from scratch and all of that fancy stuff just doesn't happen until you actually reach the client. You don't have to think about that divide anymore. Everything is in the same place. Any more questions? Yeah. Yeah. Yeah. Yeah. So actually the project that has benefited most from this, at least using React, is different kind of internal tools we have like admin interfaces and that kind of stuff. And we've been using React and Flux there now and it has just made everything so much easier, just easier to kind of structure your app and mitigate errors. But there again, we don't use the isomorphic approach because why would we need isomorphic on our internal admin app? So you might have a point there that this is mostly useful in apps where you need to have stuff rendered on the server first. And the kind of the last example I've showed you there is probably not that useful for everyone. But yeah, mostly for the case where you want to make a single page app but you also want to have this rendered on the server because you're indexing stuff. So yeah, I guess that's a good point. So any more questions? Okay, thanks for listening. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you.
here today to talk about isomorphic JavaScript back at vg.no. And you could forget about SEO application we want, and we can get the benefits maintain and to keep in sync. You'll have a lot JavaScript applications, you can have all of the just boils down to that there's no more make this possible? So there's a lot of options out there now which have a lot of the same as we need to make our code runnable in the for all of our React components. And this is the now we should have everything we need to get our bit closer, we'll see that it's just a JSON for both the server and the client. So, and this community-made routing solution that works both less context switching because the application And you get the best of both server-side