5 ms·
I think this premise is wrong: > 2. As a corollary, your app's codebase should be universal — write once for server and client This is a mistake a lot of deve
by Touche 9y ago
I think this premise is wrong:
> 2. As a corollary, your app's codebase should be universal — write once for server and client
This is a mistake a lot of developers make. The server and client are not the same. As far as rendering HTML goes, the client does a superset of what the server does.
This means either the framework has to be without leaks; meaning you never need raw DOM access at all, OR it means once you do need lower-level access (for doing animations, for example) you are in trouble. You now have a problem where you have some code that needs to only run in the client. So you have to special case that code to check if running on the server. And you need a strategy for what to do in the server (do you just omit this part, or do you try to do something more basic or what?)
In my experience you run into more pain trying to plug the leaks in these "universal" apps than you would if you just had separate server and client templates. Remember that the rule of 3 is the rule of 3, not the rule of 2.
https://en.wikipedia.org/wiki/Rule_of_three_(computer_programming) https://en.wikipedia.org/wiki/Rule_of_three_(computer_progra...
- rich_harris 9y agoIn practice, this isn't an issue. Component lifecycle hooks and methods (which is where anything involving raw DOM access or animation takes place) never run on the server — the SSR renderer just generates some HTML for a given initial state. Once you grok that, it's easy. Certainly much easier than maintaining two codebases in parallel!
- Touche 9y agoThen you have a server/client difference if the lifecycle hooks change the dom (like a jQuery plugin or something). So you have to figure out what to do on the server.
- rich_harris 9y agoThe server is only involved when you first hit the page. After that, the client takes care of all the rendering. There is no discrepancy!
- Touche 9y agoThere's a discrepancy if the user doesn't see something when the page first renders but then does see it once the JS runs.
- inventingwithmo 9y agoBut this doesn't happen?
- scottmf 9y agoHonestly these are solved issues. It’s 2018.
- abritinthebay 9y agoThat would be poor coding or application design. There’s no reason for that to happen with SSR. At all. There’s especially no reason for it with modern frameworks like React/Vue/etc - it’s not been a technical problem for years.
- ralmidani 9y agoWith Ember and React at least, it's the same if you use 100% client-rendered elements; the component/template renders to the page, then a lifecycle hook is triggered, and then your custom code/plugin runs.
- natecavanaugh 9y agoThe client handles the dynamic aspect of time, whether that's event handlers that may be invoked later or animations which may run at some point and for some length of time. The server only needs to handle it's default, but as other commenters mentioned, lifecycle hooks help manage when some logic gets run. I think it does take some time to think universally, but it's not all confusion and hair pulling. In fact, it kinda reminds me of writing testable code. You need to separate some concerns, but ultimately, it's a set of conventions that help you get there. I can tell you, there are plenty of times when even a rule of two isn't worth the maintenance effort that's caused by rendering HTML in two different places.
- Can_Not 9y agoIf it doesn't make sense to render on server (last child tag for Google maps? YouTube? Calendar datetimepicker?) Then wrap it in a simple <no-ssr> tag that has existed for a long time in all major frameworks supporting SSR. Interesting problem, but when it ever rarely actually shows up, it has an obvious, practical, and proven solution.
- deleted 9y ago[deleted]
- tnolet 9y agoIs it stranfe that I actually prefer two codebases? I find the hard split (or just client/server architecture) to provide clarity, focus and peace of mind.
- mike-cardwell 9y agoIn Universal React based apps, some of the lifecycle methods only run on the client side, e.g componentDidMount. So you just perform client-side-only functions there. There's also react-no-ssr - https://www.npmjs.com/package/react-no-ssr https://www.npmjs.com/package/react-no-ssr. It is an issue, but one that is really easy to handle.
- dbbk 9y agoThe same applies to Ember apps as well. Honestly, this is not an issue.
- dfabulich 9y agoYou really want multiple layers of "server" code, one of which is a tweaked version of what's on the client, and one of which is purely server-side. For example, you can't trust client-side code for security/authentication purposes. You almost certainly don't want client code to connect directly to your database and run arbitrary queries/look-ups. So some kind of server-side-only wrapper around your DB, at least, is required. But the reason you'd run "client" code on the server is to have a layer of universal HTML-rendering code. The server needs to do it for fast initial page loads (and SEO), and the client needs to do it for fast, offline page loads. At the same time, there's a bunch of code that will run on the client side only, e.g. click handlers, animations, etc. There's essentially nothing for that code to do on the server, but I think it's still basically correct to call it "universal" when you mean "client code that can also run on the server" which is what Sapper provides.
- tootie 9y agoThis has a name and it's the BFF pattern (backend for frontend). It's main reason for existence is just to do SSR. It might also do some level of service orchestration where it pulls API responses from multiple microservices and munges them into a single page model to reduce round trips from the client.
- tboyd47 9y agoCan't agree more. It's El Dorado for web developers. You might be able to write all your app code in Javascript, but the inputs and outputs are so different that you never really avoid "if(isServer()) {...} else {...}". You can't contain that in a single file, either. It surfaces in the most unexpected places and gradually erodes the illusion of "universal," until you're never sure in which order or what environment your code is executed. You'll have pieces of code written and rewritten again and again and executed several times just to make sure it gets called in the exact moment, with the exact arguments you need, at least once. I spent many years in search of "universal" JS, and worked with many people who were convinced they had found El Dorado, yet always ended up in situations like I described, so maybe I'm jaded.
- abritinthebay 9y agoApparently I’m working in El Dorado then...
- deleted 9y ago[deleted]
- dbbk 9y agoThis is not the reality though... with React and Ember (presumably also Vue) there is one place where client-side only stuff happens, and it's in component lifecycle hooks. It's perfectly clean and makes sense.
- tboyd47 9y agoIt was and is a reality for many people and was my very frustrating reality for quite a while. The concept of "client-side only" code that does anything more significant than animations (such as, say, modals) breaks down if you want deep linking, and deep linking requires full data reloading on every action, because how can you be sure the data is all there if you don't load it, and once you're reloading your entire state tree on every action you're already slower (not just in data transfer but in code execution) than the "traditional" client-server pattern, and if you have a UX team and any timeline pressure at all, you've already written yourself into several corners for UI bells and whistles, which unfortunately affect the server side as well now, not to mention being at least a major version out of date on several NPM libraries, and just another rewrite away from clean architecture, and so on...
- lcfcjs2 9y agoI completely agree. These 2 layers must be separated, by the HTTP protocol.
- OJFord 9y ago> the rule of 3 is the rule of 3, not the rule of 2. But, to quote from your link: > and may or may not if there are two copies.
- alkonaut 9y agoI’m not sure I’d share a lot of code between server and client even if I could, but sharing the odd domain type, some utilities etc might be handy. The universalness I want is that I want one language, package manager, toolchain, IDE etc for all the code I’m working on. Worst case would be to have the two platforms being slightly different. Say two IDE’s with slightly different shortcuts, two curly brace languages with slightly different syntax, two different build systems you need to integrate in the CI etc.
- dbbk 9y agoWhy's that? Why would you want your server response and your client-side app to be different?
- alkonaut 9y agoWhy is what? Why I would not share code? Server response, do you mean in the context of a server that does server side rendering? I was thinking in the context of a normal app: api backend and (possibly multiple) front end rendering apps
- dbbk 9y agoAh, apologies. I meant server response as in the server-rendered version of your client-side app, not your backend server.
- austincheney 9y ago> This is a mistake a lot of developers make. The server and client are not the same. This is the basic value premise of frameworks. Write less code with uniform conventions and make it easy by hiding the complexity. Unfortunately, the premise is faulty. You can only lie to yourself for so long that your ignorance of how things really work is fine because of (name your favorite abstraction). This is a very direct example of tech debt. By ignoring how things really work the application will gradually get bigger and slower until it is an incompetent mess like paying off credit cards with other credit cards. The reason for this snowball effect is largely due to a lack of confidence that feeds upon convenience as opposed to examination of why technical problems exist in the first place.
- nh2 9y ago> The reason for this snowball effect is largely due to a lack of confidence that feeds upon convenience as opposed to examination of why technical problems exist in the first place. I find this a great answer. Much time is spent these days on taping over problems at the high level on the top of broken stacks, instead of fixing the underlying issues. Building on broken foundations will only get you so far and yield diminishing returns, even if it initially looks easy and convenient to just build on top.