
Isomorphic JavaScript, let’s make it easier - piercey4
https://medium.com/@pierceydylan/isomorphic-javascript-it-just-has-to-work-b9da5b0c8035
======
madeofpalk
This looks like a really interesting model, less hacky than the current
approach of 'lets take client-side react-router and somehow make it work on
the server' approach.

What isn't answered here however is how it transfers this 'config' and the
rest of the state and make it work in the browser. Does rill come with its own
client-side router (that works nicely with React?) How does it serialise the
state and send it down for the client resume?

Ultimately, the reason 'universal javascript' is hard is because everything's
'modular' so you can get more controller over each component and customise
exactly how it works. While rill might be 90% for 90% of use cases, I can see
something like this falling down once you start to build anything non-trivial.

~~~
piercey4
What I use to handle state transfer from the server to the client is
@rill/session along side @rill/loader. Check them out and feel free to ask me
any questions (here or in the gitter!)

------
nigel182
This looks pretty damn good. I'm a little wary though because it makes me
remember unfondly the leaky abstractions and blurred line between client and
server in ASP.NET webforms. Granted, there is no generated client code here
(not counting what webpack compiles from JSX) but I'm suspicious of things
that claim to bridge the client/server gap.

~~~
piercey4
As I have mentioned to others here and is mentioned in the Rill README the
goal of Rill is provide a bare minimum of abstractions over the browser to
encourage code sharing and code reuse with isomorphic JavaScript. Even with
this goal Rill is great because you can use it "server only" or "client only"
or shared, it's up to you, it gets out of the way. The huge benefit is that
when you want to be able to share code it's extremely easy and when you don't
just use "if (process.browser)" type stuff to clean up the edge cases.

Ultimately I found that when writing isomorphic SPA's the amount of code you
"CAN" share is much more than what is unsharable, personally I am often able
to share 90% or more of the front end code and just have to throw in a few "if
(!process.browser)"'s to hide some mission critical stuff from the client.

With many isomorphic examples you will find you end up jumping through hoops
to share code. Rill makes this part easy but that doesn't mean that absolutely
everything can or should be shared.

------
chvid
How is authentication/authorization handled in this example?

The code hits a web api that sends out a batch of emails. Doing this from
client side has an obvious set of problems, whereas had it been on server side
one can assume a stricter use and thus have a simple security model.

~~~
piercey4
The way that I typically setup my apps is to have two parts of the server.
Typically something like:

``` if (!process.browser) app.use(require('./api')) ```

Where the api is your typical REST based api with JWT auth tokens. Then the
shared client side part of the api communicates with the secure part through
"fetch" which works isomorphically (in the browser it is an ajax request, in
the server it is a local http request to itself) you should checkout
@rill/fetcher for what I currently use. In Rill there is no issue with having
"client only" or "server only" routes, the main benefit is that the api is the
same no matter where you are working. Take for example "@rill/progress" which
is a progress bar that only does work in the browser, or "@rill/compress"
which only does anything on the server or "@rill/logger" which works on both
(although with completely different implementations). The goal is certainly to
encourage code sharing where possible but to also not get in the way. You can
use Rill as a standalone server only app if you want, or even just as an in
browser framework, it doesn't really matter.

As for my example with emails it is certainly not real world and I don't
recommend having public access to an email api but the point was merely to
demonstrate that all of the code could be abstracted to work in either place
(even without rill).

------
gtf21
This looks like a very appealing framework, but reminds me of the horrors of
using Google Web Toolkit or Meteor. There are different concerns when writing
on the client (less controlled) and the server (more controlled) - chvid
mentions the security model being different, and this is very true.

The use-case which I think this does seem to solve very well is between
dynamic and static rendering of web apps (especially when using react). The
ability to bundle up routing and rendering and have it handled by the client
if possible and the server if not is a great idea. Apart from this, I am not
convinced that this framework solves any major problems, but does introduce _a
lot_ more magic (which is why I disliked meteor).

~~~
piercey4
I agree with you 100%. You can take this hammer and use it like a axe. But
that's not the goal.

My personal setup has been to still separate my api (although still written in
Rill) from all of this) which runs as an independent server. Then I have an
isomorphic Rill instance communicate with that API. This way I still keep the
important things separate.

------
jaequery
in the case that isomorphic javascript takes over the web for whatever reason,
it will be just a matter of time people will be wanting the client/server
distinction all over again. it's a sure cycle. but regardless, what OP did
looks like excellent work, love the simplicity.

------
tluyben2
Is this really a problem? We don't have too many issues using currently (and
older) technologies to make this work well enough for production systems. The
focus on the frontend of things is nice though and we know how to make API's
(fast), however, is someone fixing any of this for the data? So I want to make
a React JS and after that React Native app, I want it to work (mostly) online
and offline; it needs to have solid SEO for some pages and no SEO is needed at
all for others (behind login). I want to store / sync data in our store and I
need to call a bunch of API's and present and/or store locally and/or server
the results. There are technologies enough; Parse server, Hoodie, Couch/Pouch,
Meteor, Realm, REST API's, Websockets etc however they all only solve a
(small) part; is anyone working on or is there something that would allow me
to simply annotate connections specifying their behaviour (sync
server->client, client<->server, client->server, what the sync behaviour is,
how long data is valid, caching behaviour, how to resolve conflicts etc etc
over different backends => our problem with picking any 'nosql' backend is
that we really don't want to; we can just add a UUID in the REST api or give
the synching code some 'hash' function of what 'unique' is etc) without having
to do all that manually?

We can handle it fine manually but we notice we are basically doing everything
all over again in a next project and putting that in libs now to be open
sourced (maybe someone can use it), however that is for C# and I'm now
wondering if there is something like it for JS already ; we cannot be the only
ones having these deja vu's with every project?

------
sktrdie
If you like working with declarative code, checkout RxJS and specifically
Cycle.js. It's totally isomorphic and lets you think of apps as streams of
data.

------
douche
Because having to use a buggy, badly designed, unsafe language just on the
front-end wasn't enough.

------
mshenfield
If I had to sum this up, I would say rill is an isomorphic/universal
javascript server. Are there examples of other libraries implementing a
similar idea?

~~~
piercey4
I mention my inspiration here: [https://github.com/rill-
js/rill/issues/12](https://github.com/rill-js/rill/issues/12).

There are some other interesting frameworks that have come up while I was
developing Rill such as
[https://github.com/catberry/catberry](https://github.com/catberry/catberry)
but I think (like many have said in this thread) that there is a fine balance
to be had with isomorphic JavaScript. For example I really dislike meteor
because I feel like I have little control. I like Rill because it is a
perfectly capable backend framework, a perfectly capable front end framework
and it all meshes together pretty well.

------
hyuuu
would love to know how Rill hydrates the data needed to render a page, if the
page is dynamically generated.

~~~
piercey4
Great question. I personally use @rill/session along side @rill/loader.
Basically on the initial page load @rill/session asks the server for the
current session then for the rest of the users session the browser manages the
data.

------
biocomputation
"Isomorphic" Javascript? If there exists an isomorphism between the code on
the client and the code on the server, then someone should be able to write a
proof.

Otherwise, using the same language on the client and the server does not
constitute an isomorphism.

Kthxbai!

~~~
mikemikemike
The JS community switched from the term "isomorphic" to "universal" around a
year ago. Seems not everyone is on the same page yet.

~~~
piercey4
I use both but personally prefer Isomorphic because in most cases the code
isn't actually universal, it has to be translated (shimmed, transpired, etc)
between environments.

If there is one thing you can do to annoy programmers though is to use the
wrong terminology :p.

~~~
clhodapp
It really is a very wrong use of "isomorphic", though:

First, "isomorphic" is a word that denotes a symmetric, relative relation
between two separate things; Two things can be isomorphic _to each other_ but
one thing cannot be called "isomorphic" without specifying what other thing it
is isomorphic to. That simply doesn't make sense.

Second, isomorphism is about those two things having the same conceptual
structure, _despite being different things_. In math, this means that you can
define a lossless two-way conversion between the things (you can start with an
A, turn it into a B, and go back to an A, and you'll get the same A). In
biology, the field the author took his definition from, isomorphic means that
the things have a _different ancestry but the same structure_. This is
_literally the opposite_ of taking code and shimming or compiling it to allow
it to run in multiple environments, as it would be taking a single _common_
ancestor codebase and lossily changing its structure to allow it to run in
multiple environments.

edit: Just realized you are the author. Now I feel silly for referring to you
in the third person. In any case, I do want to say that despite any squabbling
over terminology, you seem to be doing great work in putting out rill.
Developing a full-blown application framework like this mostly on your own is
no mean feat. My squabbling stands, though.

~~~
abritinthebay
> It really is a very wrong use of "isomorphic", though

It's really not.

> Two things can be isomorphic to each other but one thing cannot called
> "isomorphic" without specifying what other thing it is isomorphic to.

Good thing we're talking about the relationship of client and server code then
so we're not doing that then isn't it?

> isomorphism is about those two things having the same conceptual structure,
> despite being different things.

Yup, still perfectly on topic here with Client vs Server...

> In math...

Ah well, there's your problem. It's nothing to do with the mathematical
definition of the term.

~~~
madeofpalk
_Technically_, it would be more accurate to say that your client is isomorphic
to your server. In that regard, the term 'isomorphic javascript' doesn't
really make sense as there's nothing to compare it to.

However, everyone knows what you're talking about when you say 'isomorphic
javascript', so the pedantry doesn't really matter.

~~~
abritinthebay
Well indeed, and "isomorphic javascript" is really just dropping the _heavily_
implied "application" at the end.

At it’s core Isomorphic JavaScript describes the relationship between the
application that runs on the server and the one it serves to the client to
run.

It's perfectly correct - because it's not describing the _code_ it's
describing the application(s) and the approach they take.

