5 ms·
You don’t need bundlers or build systems. ES modules work in all modern browsers without any build tooling, imports and all. HTTP/2 mitigates the TCP overhead.
by eurasiantiger 4y ago
You don’t need bundlers or build systems. ES modules work in all modern browsers without any build tooling, imports and all.
HTTP/2 mitigates the TCP overhead.
You can have an unbundled, unminified web app load quicker than the average bundled and minified React app.
Best of all, you can’t use NPM modules so your codebase can stay ultra-clean!
- josephg 4y agoSure, but I can’t run the same code in nodejs for server side rendering. And wasn’t server push for HTTP/2 removed by web browsers? If the browser needs to do a round-trip to the server to fetch every individual javascript file (and it doesn’t even know which files it needs up front) then the result will be way slower than a bundler. I would expect performance to get worse, not better using this approach.
- cityzen 4y agoI don’t get the need to use js for SSR? Why not PHP/Go/Python/Ruby… ?
- danielheath 4y agoIf you use react to create the DOM, you can do SSR in nodejs to re-use the same code. Not clear to me that the added complexity is worth it personally.
- zelphirkalt 4y agoAlso this re-use tricks people into tightly coupling frontend view logic with backend logic, making a mess of everything.
- eurasiantiger 4y agoNo it doesn’t. SSR is typically just a way to pre-render the client app into (critical) static assets that can be delivered to the browser quickly, so it can display at least some content before the client app loads, runs and ”hydrates” the server-generated HTML back into the exactly same interactive app (e.g. a React app) that was used to generate the SSR assets.
- zelphirkalt 4y agoI know what SSR is ... been using it for a decade or so, before it became hip again in form of JS frameworks. That does not change, that in practice people will write their web components all in one file and render a template, which contains <MyFancyNamedTag>{js logic here that should not be written here}</MyFancyNamedTag>. The mere ability to have arbitrary js logic in there and the fact, that rendering MyFancyNamedTag actually renders a component, which itself can contain arbitrary js logic, instead of outputting a real tag named MyFancyNamedTag, leads to people coupling everything tightly together. Traditional server side template rendering encourages people to make up their data beforehand and then render the template. Maybe you don't do it that way. Maybe you are smarter than the average frontend/js-is all-I-know-because-I-heard-its-all-I-will-ever-need developer. Not saying you specifically make these mistakes it. Edit: With regards to being able to contain arbitrary js code in braces in the call to render a component, this actually inches close to the mess many people make when using PHP. There is was: open php "tag", php logic, output HTML, treating it as a string, inside HTML open PHP again, output some JS, JS logic contains code for manipulating HTML ...
- eurasiantiger 4y agoWell, the way I see it (and the canonical way React sees it), a render function f producing a view V from some data D is defined as V = f(D) … which is an oversimplification, since UI commonly has local state, which definitely doesn’t need to be elevated all the way to the master data. Any interactive UI thus certainly uses several sources of truth. Let’s add some to the previous. Let our previous data D now be D_master since it is our master business data (which we may not change in any way, shape, or form). Then, add state of app routing D_router, user auth state D_auth, and local widget state D_widget. V = f(D_master, D_router, D_auth, D_widget) We might have all kinds of access checks regarding the three first ones, but here we are only interested in what this means for rendering a view. To use all our data, let’s imagine a form where a dropdown select widget is placed inside a tabbed container. The user needs to have a particular user role in their auth data to see this widget. There are many similar widgets in this form, all with fine-grained controls. - The options for the list come from D_master. - The state of the tabbed container lives in the URL so that it isn’t lost on refresh, so it is accessed through D_router. - The user role comes from D_auth. - And finally, whether the dropdown is open or not is stored in the component’s local state, D_widget. This is not a far-fetched example, such things are common in more complicated applications. In any case, it does make intuitive sense to me to allow logic in the render function, as long as that logic operates directly on the render function parameters and not on some on-the-fly transformed intermediate. Rules of refactoring also apply. Without logic in the render function, the coupling between frontend and backend would get insane, as every component fetching data would require custom on-the-fly denormalisation for that data in the backend. In our example, we would be pre-generating data for the entire form for a particular user, probably even for unused features. It would be like generating snippets of HTML in response to AJAX requests, but without the prerendering to HTML.
- josephg 4y ago> Not clear to me that the added complexity is worth it personally. It used to be pretty easy to set this up. Modern bundlers, jsx, es modules, typescript, webassembly and modern web frameworks which need their own compilers have all made this much more complex. I’m not sure the complexity is worth it any more.
- ttty 4y agoSo you rather write your app twice: once in react and once in go? And keep it in sync, including css and styles and dom… ? For real?
- chrismorgan 4y agoYou should almost always use a bundler. ES modules work, yes, but using them naively subjects you to a waterfall (each module file may trigger the loading of others, though you could circumvent this with a sufficiently advanced server that recursively traversed modules in order to collect the whole set and send rel=preload links for each with the initial response), slow loading everywhere and exceedingly slow loading in higher latency, and the downloading and execution of much unnecessary code. For many completely realistic designs that would have been a hundred kilobytes in a one or two files, you’ll end up with it spread over several hundred files, reaching ten or twenty levels deep, so that it downloads and executes multiple megabytes of code, a lot of which is not even used, so that for someone on the other side of the world, what would with proper bundling have taken less than two seconds to load (including initial TLS handshake) will instead take ten or twenty seconds if everything goes smoothly. And I’m not exaggerating in the slightest here. The situation would certainly be worse in HTTP/1 because of the lack of pipelining and the six connections limit, but HTTP/2 does not make not-bundling in any way reasonable.
- eurasiantiger 4y agoDon’t use external dependencies (:D), don’t write code you don’t use, encapsulate imports in custom elements (this is a joke). Without any runtime boilerplate like module bundling, corejs polyfills and the usual frontend/css-in-js frameworks, all code that gets downloaded is your code, so make it count. 640 kilobytes should be enough for everyone.
- chrismorgan 4y agoFor runtime boilerplate: yeah, don’t use webpack, it does indeed add silly boilerplate (and structures things in a way that almost requires source map tooling to understand!); use Rollup instead, which pretty much writes just what you would have written if you had put everything in one file, with no overhead whatsoever. (If you happen not to be familiar with it, take a look at the examples in https://www.rollupjs.org/repl/ https://www.rollupjs.org/repl/.) Also ditch core-js as it’s almost certainly unnecessary if ES modules are your baseline. But even if you’re not using external dependencies, I maintain: by not bundling, you’re slowing things down, and it’s generally the people on the other side of the world from your servers and the disadvantaged with less-powerful computers and more expensive data that will suffer for your whim.