I've been reading articles online about what universal javascript is but I'm still not comfortable with the definitions each site is giving which is, "code that can run on the client and server." Does this mean that a node.js app is inherently universal javascript because it will have javascript running in the client side and server side. Or does universal javascript have to do with server side rendering then client side rendering?
I've been reading articles online about what universal javascript is but I'm still not comfortable with the definitions each site is giving which is, "code that can run on the client and server." Does this mean that a node.js app is inherently universal javascript because it will have javascript running in the client side and server side. Or does universal javascript have to do with server side rendering then client side rendering?
Share Improve this question asked May 9, 2017 at 6:40 Ethan DavisEthan Davis 1,2792 gold badges14 silver badges21 bronze badges 2- 2 Well… it's a script that can be included and used in the browser as is and also in node, without any changes. It doesn't have any platform-specific things in it, or it can adapt automatically to the differences. – deceze ♦ Commented May 9, 2017 at 6:45
- It would help greatly if you provided references for "articles online about what universal javascript is". But I think this is just too dependent on opinion. – RobG Commented May 9, 2017 at 12:35
3 Answers
Reset to default 14Preface: I cannot find any highly-authoritative (e.g. ECMA, Microsoft, Mozilla or Google) source that provides a strict definition of "universal JavaScript" or "isomorphic JavaScript" - at most I've found a few blog posts (albeit by influential personalities) however I can see why a newcomer might be confused.
It seems there are two definitions going around which are similar, but with crucial differences:
1. To refer to JavaScript which runs anywhere
This definition refers to JavaScript which does not take a dependency on any specific client-side or server-side API, instead they only make use of features present in JavaScript's built-in library (String
, Array
, Date
, function
, Math
etc) or on other libraries that also similarly restrict their dependencies (a transitive relation).
Remember that "JavaScript" does not mean that the DOM API, AJAX, HTML5 <canvas>
(and so on) are available - it just means the JavaScript scripting language is being used - that's it. JavaScript has been available outside of web-browsers for over 20 years now (Windows support JavaScript as a shell-scripting language in cscript.exe
/wscript.exe
and ASP 3.0 supported server-side JScript as an alternative to VBScript - and the .NET Framework has "JScript.NET" too).
So in this case, if you wrote a library that adds some useful string functions, which only references String
, then that script would work without issue in a Node.js server environment or an in-browser environment.
But if your script ever used the window
object (only present in browsers) or express
(a library only for Node) then it loses "universal" status because it cannot "run everywhere".
2. To refer to JavaScript which renders the same HTML whether on the server or on the client
e.g. http://isomorphic.net/
This definition is actually a strict subset of the first definition: as the same script must (by definition) run inside both a server/Node.js context, but also a browser DOM context - and when it runs it generates content (typically HTML) that is then displayed in the user's browser (and by doing this it must take a dependency on both a Node API and the W3C DOM - so then it cannot strictly run "anywhere" because neither are available in a cscript.exe
environment, for example.
Note: There is debate if use of XMLHttpRequest
or fetch
makes a script universal or not - as their presence is not guaranteed (as technically they're part of the DOM, not JavaScript's built-in library).
In this 2015 blog post ( https://medium.com/@ghengeveld/isomorphism-vs-universal-javascript-4b47fb481beb ) the author argues that only the term "isomorphic JavaScript" should be used to refer to rendering code that runs in both browser and server environments, while "universal JavaScript" should refer to truly portable, environment-agnostic, JavaScript (i.e. my first definition).
Nowadays Single Page Applications have become very popular but they have problems, SEO, for example.
So, how does an SPA work? JavaScript loads in the browser and loads data from an API. Most of the rendering is done on the client Side. But search engine bots have a hard time indexing the page because it doesn't have much without JS.
Now, Universal/Isomorphic App comes to the rescue. At the initial page load, the original page renders on the server. After that, the app works like an SPA. It's got better SEO because when a search engine bot asks for a page, the server returns the whole rendered HTML page, with content and meta tags.
Edit
An isomorphic app can be done with JavaScript (Node.js), PHP or some other language, but if that app written with Node.js, then we can call it universal as both the backend and frontend are in JavaScript.
I'll try to explain it with examples, even if other answers seem already accurate.
A basic example
Imagine you develop a SPA that render an Hello World message. This means that your browser loads an HTML file with a <script>
tag (or the reference to a JS file) that actually makes this happen. You can prove that "Hello world" is generated by JavaScript in the client browser, because if you deactivate JavaScript you won't see any message.
Now isolate the code that prints the string "Hello World", it doesn't need much to be adapted and work in the server side. In fact, the server just needs to send an HTML string that "contains" the <h1>Hello World</h1>
inside its body.
So what it makes it universal/isomorphic? The fact that the code can understand in which environment it runs (the browser, the server or possibly an other environment) and it keeps functioning. Remember: code usually only runs in one of the two environments, the thing is that you wrote some common code that can run in both environments (universal).
The behavior of a more complex Universal App
Imagine that you struggle to develop a new Universal website. The code can acknowledge in which environment it is running and work just fine. So you have, let's say, 80% of your code that is shared, it doesn't even need to know the environment, and the rest of your code is there to managing the fact that your app can be used in the client or in the server.
How does this work?
The client first contacts the server that returns some HTML to the client with all the content of the page, elaborated in the server. So the server renders the application. In the mean time the browser downloads the script file where your single page can work in the client. The client is now rendering the same page again. You won't see anything, because if it is properly done, it will just be the same (of course all the animations and real time features have to work client-side, so you will eventually see your animations starting)
When the user clicks an internal link or uses an interactive feature, or eventually fills out and submits a form, the client-side code is in use. The server doesn't get any request, especially assuming that all the interaction are abstracted in an API that is not our isomorphic app.
If the user goes crazy and wants to deactivate JavaScript, how do you assure that, for example, forms still work? Here is a trick you can use:
<form method="post" action="/api/fakeBackendRoute" onSubmit={this.handleSubmit} > [input fields here] </form>
When the client JS is available, the
handleSubmit
is executed and the propagation of the event is prevented. This way the server side code will never fire.
If the client JS is disabled, thenhandleSubmit
will never be executed and you have to care that your/api/fakeBackendRoute
will handle the data exactly how the client would.
Why do people use it?
In my opinion the difficulty of undertaking the development of an Universal App is often underestimated. Good reasons to use it are:
- Be more SEO friendly
Support very old browsers. For example, if you want to support IE8, you could do something like this:
<!--[if gt IE 8]><!--> <script src="yourfile.js"></script> <!--<![endif]-->
Be more accessible for people that don't want to use JavaScript
Other reasons could be:
- Performance, if it matters to your application. You can improve your response time by using, for example, a lot of Node capabilities to stream your HTML string in the first request, and eventually later be more in the client, where things will be likely faster. But you could decide whether it is faster to render on the client or on the server, depending on the content and how you create your assets.
If someone knows other good reasons, just comment below and I will add them.
Some good reference links:
- https://medium.com/airbnb-engineering/isomorphic-javascript-the-future-of-web-apps-10882b7a2ebc
- https://medium.com/front-end-developers/handcrafting-an-isomorphic-redux-application-with-love-40ada4468af4
- https://github.com/xgrommx/awesome-redux