
Show HN: Sapper.js – towards a better web app framework - rich_harris
https://svelte.technology/blog/sapper-towards-the-ideal-web-app-framework
======
Touche
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_progra...](https://en.wikipedia.org/wiki/Rule_of_three_\(computer_programming\))

~~~
rich_harris
In 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
Then 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
The 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
There's a discrepancy if the user doesn't see something when the page first
renders but then does see it once the JS runs.

~~~
abritinthebay
That 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.

------
DougWebb
Sorry, I couldn't resist. Second and third paragraphs, with some minor
editing:

 _HTML_ is close to this ideal. If you haven't encountered it yet, I strongly
recommend going through the tutorials at
[https://www.w3schools.com/html/](https://www.w3schools.com/html/). _HTML_
introduced a brilliant idea: all the pages of your app are files in a your-
project/pages directory, and each of those files is just an _HTML page._

Everything else flows from that breakthrough design decision. Finding the code
responsible for a given page is easy, because you can just look at the
filesystem rather than playing 'guess the component name'. Project structure
bikeshedding is a thing of the past. And the combination of SSR (server-side
rendering) and code-splitting — something the React Router team gave up on,
declaring 'Godspeed those who attempt the server-rendered, code-split apps' —
is trivial.

~~~
rich_harris
If you don't mind reloading the entire page on every single navigation, and
don't have any dynamic data or interactivity, this is indeed a very solid
approach.

~~~
RobertRoberts
But this is where the entire argument of "do first page load server side
because it's faster" doesn't make any sense.

Because then aren't you suggesting that after that, all the other pages can be
slow?

The worst sites I visit now are React.js like sites, instead of the page load
being slow, _everything_ is slow. Ugh. I can't wait until web 3.0 and this
silly balogna with the "make a browser with React and run it inside a browser"
fades out...

(note, Netflix _removed_ their js rendering from their home page cause it was
slow)

~~~
rich_harris
Server-side rendering means you get a quick _first_ load. Client-side
rendering means _subsequent_ navigations are quick, because there's less data
to transfer (maybe a little bit of JSON, maybe nothing at all). Going back to
the server for 100kb of HTML and reloading the entire page, as opposed to
fetching 10kb of JSON and instantly updating it in place, is a very 2002 way
of doing things!

~~~
RobertRoberts
>...because there's less data to transfer...

The problem is that just the theory, reality if often times different.

>Going back to the server for 100kb of HTML and reloading the entire page...

This implies that 1) you don't go "back to the server" to load your bit of
JSON. and 2) the JSON loaded doesn't require any extra templates, images or
more JSON to be loaded. See the problem? It's all assumptions.

Another thing, what about browser caching? I can see how the next page loads
_only_ the html, as all the js, css and images were loaded already. I think
you are falling for the exaggerated speed benefits from making a website with
a JS framework.

To be clear, I am talking about a web page, an HTML document, static content.
Maybe that's where the confusion happens in discussions like this. (I said
"sites", not "webapps" in my original comment)

A history lesson, we did this with Flash years ago (no more page refreshes!),
and everyone ultimately learned to hate it. Just because the flashy crap is
spread over the entire "webapp/site" to every button, mouseover and click
doesn't mean it's useful or better. (I think many devs think they need to
build basic site features with big frameworks just to "stay modern".) Look at
Youtube, it's slower now that they implemented their "webapp" experience, but
the page doesn't "refresh", so that is somehow better... (is youtube really a
webapp? Or a bunch of pages with videos on them?)

~~~
rich_harris
Ultimately, the proof is in the pudding. Which is faster, when you start
navigating around?

* [https://news.ycombinator.com/item?id=16052558](https://news.ycombinator.com/item?id=16052558)

* [https://hn.svelte.technology/item/16052558](https://hn.svelte.technology/item/16052558)

Bear in mind that HN itself has a huge advantage over HN clones, yet — for me
at least, sitting here — the Sapper version is significantly snappier.

~~~
dgreensp
Hi Rich. On my iPhone, I get a 3-second delay between when I “swipe to go
back” and when the page is usable/scrollable on the Sapper HN. When I first
went to the site, via the link above, the top nav links did not seem to work
reliably, and it may have been the same 3-second delay, but I’m only getting
now when swiping to go back — maybe because the page is being reloaded from
the server? It’s still quite a delay, though.

~~~
shoover
Interesting. I get behavior like that with twitter.com on the iPad. It hangs
with a blank white page for a few seconds. I always wondered what kind of
client script shenanigans were going with that. Using the back button embedded
in the web page does not cause the same delay.

~~~
boubiyeah
I get the same behavior on my phone with their new website too. Service worker
infancy bugs?

------
deno
Some bullet points are missing from the “perfect framework” list:

1\. SSR must support streaming

2\. SSR must work in a service worker (so in fact you have 3 targets: server,
client/hydration, client/service worker)

3\. All work that can be offloaded to a WebWorker must be offloaded

4\. Navigating to subsequent pages must support prefetching, including dynamic
data (Next.js doesn’t even tell you how to do it)

5\. Navigating to subsequent pages SHOULD support prerendering (offscreen)
where it makes sense, but…

6\. MUST support FLIP-style transitions[1].

Which does mean prerendering anyway for about 100ms at least so the layout can
stabilize and cached images load into memory.

For long pages you need to split them into chunks/sections and only animate
the part that gets shown (usually above fold).

[1]
[http://www.pocketjavascript.com/blog/2015/11/23/introducing-...](http://www.pocketjavascript.com/blog/2015/11/23/introducing-
pokedex-org)

~~~
rich_harris
This is an excellent list, thank you. To answer some of the points:

Sapper supports partial streaming of server-rendered HTML (typically you'll
get most of the <head> while it's fetching data for your page, unless there's
no dynamic data in which case you get the whole lot instantly).

I'm not convinced there's actually a benefit to 'server' rendering in a
service worker as opposed to serving a shell page. We have an issue for it
though!
([https://github.com/sveltejs/sapper/issues/22](https://github.com/sveltejs/sapper/issues/22))

Sapper supports prefetching (including of dynamic data) of subsequent pages —
just add rel=prefetch to <a> elements (we'll add a programmatic way to do this
in future as well).

As for the rest, some of it is app-specific, some of it is stuff the framework
could help with. We're not at version 1 yet, so bear with us :)

~~~
deno
It should be “free” with the right architecture, and it should be faster,
that’s why I included it for the “perfect” framework list.

However, it’s only a win on first page load on a subsequent visit. So
definitely not a priority for an actual implementation.

BTW one easy way to implement this would be to flip the usual model:

1) Have service worker/server as main renderers

2) On navigation do a fetch to service worker and patch the page

So you’re on /main, do fetch to /page2?from=state and get patching
instructions.

If you could give the service worker readonly access to DOM without copying
this wouldn’t actually be that stupid.

It might be possible some day:

[https://github.com/whatwg/dom/issues/270](https://github.com/whatwg/dom/issues/270)

------
Tankenstein
As always, my main concern with this is traction. Will this be well supported,
with a good community, 4 years down the line? I know React will, just because
of the massive amounts of business depending on it. When building something
real, i have to think about this because i need to be able to hire developers
and actually develop my product instead of rewriting it.

That aside, the idea of svelte is cool, and i'm happy they're continuing to
build on that. Excited to see what comes out of this!

~~~
whome2
Massive amounts of business were also built on Angular 1.x but it is no longer
supported. To be honest, I am tiring of seeing a new javascript framework
everyday. I am pretty sure I saw a post for something called StimulusJs in the
last hour and now this.

~~~
hluska
Sorry, but that isn't correct. Angular 1.x had a release just over a week ago.
1.6.8 was released on December 21, 2017.

[https://code.angularjs.org](https://code.angularjs.org)

~~~
RobertRoberts
I think he is implying that since Angular 2 is out, 1 is guaranteed to be
gone, and no longer supported in the future.

Who would intentionally use an older version of a framework, where the upgrade
path breaks compatibility?

Angular 1.x is in essence, dead. It's just going to take a long time to go
away.

------
skrebbel
I've been following Rich's work on Rollup, Svelte and now Sapper with interest
and great awe. I truly believe he's onto something.

At the same time, if I were designing something like this, I'd use a tool like
Flow or TypeScript in a heartbeat. Doing AOT optimization is so much easier
when you have type guarantees, I'm sure that once you go deep enough you get
into all kinds of little issues that are only issues because JS is both
dynamic and very quirky.

Rich, if you're reading this, did you consider this and if so, why not?

~~~
rich_harris
Thank you.

Svelte itself is written in TypeScript so I'm a believer. I'd like to get
first-class support for TypeScript in components at some point. Adding .ts
support for the non-component parts of a Sapper app should be fairly
straightforward (it's just a webpack config after all) — will add that to the
TODO list.

~~~
stephen
Curious, but since you're a TypeScript believer, and venturing into "build yet
another JS framework", why not make it TypeScript-first or even TypeScript
only?

Granted, you'd loose a large number of JS-only potential users, but seems like
it'd be very differentiating (and unique?) to be TS-first, and
market/specialize within the large niche of TS developers/teams.

Vs. the usual TS-last/TS-kinda-sorta approach that, again AFAICT, all the
other JS frameworks take.

~~~
rich_harris
Learning a new framework is intimidating enough without potentially having to
learn a new language on top of it. I work in the news business, among people
who in many cases learned the bare minimum of JavaScript necessary to
visualise data and tell interactive stories, so that's my natural constituency
— beginner-to-intermediate/casual programmers, most of whom don't even know
what TypeScript is.

There are TS-first frameworks, such as Angular, and they're off-putting to
people who just want to build something.

------
bryanlarsen
"While it's true that citing 'ecosystem' as the main reason to choose a tool
is a sign that you're stuck on a local maximum, apt to be marooned by the
rising waters of progress, it's still a major point in favour of incumbents."

Yet the article makes clear that React is working on implementing some similar
technologies. Is there anything in svelte / sapper that cannot eventually be
implemented in React / next.js too? I'm more than willing to wait a year for
it to show up in React rather than live on the bleeding edge...

~~~
rich_harris
So far, the React team's work is focused on optimising your app code using
Prepack (kind of like Angular's AoT compilation, or similar forms of
preparsing that have existed in other frameworks for a few years) — you still
need React itself.

It's far from clear that it'll ever be possible to compile a React app to
something that doesn't need virtual DOM reconciliation, with all that entails.

------
_greim_
> the framework should do automatic code-splitting at the route level, and
> support dynamic import(...) for more granular manual control

I disagree! Code-splitting is arguably an architectural dead-end for SPAs:

1) It adds a non-trivial layer of complexity to both your application logic
and your tooling. SPAs (and the JS ecosystem in general) are already
complicated enough without this extra layer of indirection, and that
complexity carries a higher cost than most people realize, _especially_ when
it's blindly accepted across the industry as best practice.

2) It's based on the conflation of _apps_ with _collections of hypertext
documents_ , whereas in reality these are different architectures with
different trade-offs. We're under no such delusions for apps in the app store
for example, and thus nobody bats an eye if one takes a full minute to
download.

I guess this isn't what people want to hear, but the web is more than apps,
and we need to stop pushing SPA as the default way to build every new website.
Code-splitting is merely the by-product of choosing the wrong architecture. In
cases where SPA is the right tool for the job, we need to make users aware
that they're downloading an _actual app_. I.e. a one-time install screen
implemented via some kind of service-worker-driven bootstrapper: "Just a
moment while we install your app..."

~~~
lfischer
It’s an interesting idea. From the case studies you’ll find on the web, it
looks like Progressive Web Apps want to play minimal bootstrap time as as card
against native apps, but it’s true that re-use of existing web know-how could
be enough arguments in their, although native app developers are getting
almost as easy to find as web developers these days.

------
cryptica
Isomorphic frameworks are a bad idea. I'm convinced that any attempt at making
a single general-purpose web application framework will fail. I've seen it
happen too many times before.

SocketStream, Derby, and even MeteorJS which had massive funding and marketing
just couldn't do it. NextJS is just the next generation of fools who didn't
research the market... Surely we can at least wait for NextJS to go belly up
before launching yet another project that's going to waste several more
lifetimes of human effort.

There was nothing wrong with the implementation of the MeteorJS project by the
way... The problem was the idea itself. All the marketing and funding it
received only served to delay its inevitable demise.

~~~
lfischer
From what I’ve gathered, both Next.js and Sapper.js are less ambitious than
Meteor and Derby. They require to write your own data access code by hand, by
making HTTP requests or importing whatever server-side JavaScript libraries
you need, while Meteor and Derby tried to provide the same model API on the
server and on the client. Maybe the model API (and the fact that you were
almost forced into storing everything in MongoDB) was the greatest limitation.

~~~
arxpoetica
THIS.

------
auggierose
If the "compiler as framework" idea sounds interesting to you, and you don't
mind a little Scala, this paper might also be of interest to you:
[https://www.google.co.uk/url?sa=t&rct=j&q=&esrc=s&source=web...](https://www.google.co.uk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwiA6PvX2bnYAhULb1AKHaABCYgQFggoMAA&url=http%3A%2F%2Fspiral.ece.cmu.edu%3A8080%2Fpub-
spiral%2Fpubfile%2Fpaper_284.pdf&usg=AOvVaw3yPlVCT73I81zdV7vNmkVJ)

~~~
zimablue
"compiler as framework"

This really does sound like we're slowly reinventing lisp

------
tobr
Curious: why use Webpack rather than your own and IMHO much superior bundler,
Rollup?

I’m excited to try this more but I have mixed feelings about Svelte. The
concept is brilliant but I feel like there’s too much API and some weird
gotchas. I hope there’ll be an effort to simplify it if possible.

~~~
rich_harris
It uses code-splitting, dynamic imports and hot module reloading, which are
all well supported in webpack. We definitely plan to support Rollup as well,
once it has those features — it should be possible to shrink down JS payloads
by a reasonable amount. (Maybe Parcel too, eventually.)

I think the 'too much API' feelings might be more unfamiliarity than anything.
The API surface area is _much_ smaller than anything like Angular, Vue etc,
and although it's a fundamentally different approach to React I'd argue Svelte
has a much shallower learning curve there as well. We're very open to feedback
and suggestions though!

~~~
tobr
Maybe it's just the documentation that is lacking, but when I've played with
Svelte, the API and template syntax feels like a hodgepodge of special cases.

For example, what exactly does a tag starting with colon mean? Is it just
arbitrary syntax for things that don't fit in? What does a colon in an
attribute mean? (i.e., why on:click rather than onclick or onClick or even
something simpler like :onClick?) Why is there both {{#if
condition}}<p>Content</p>{{/if}} and {{{condition && '<p>Content</p>'}}}? I
feel like all these different concepts break the "it's just HTML" promise,
when it seems like it could be simplified a lot.

Yes, JSX has similar gotchas, but at least it has references and
specifications.

And what's up with the crazy semantics of computed properties?

Sorry if this sounds negative, but these have been genuine problems for me in
getting a hang of Svelte.

~~~
rich_harris
Colons indicate that something is a _directive_ rather than an attribute — so
`on:click` is the `on` directive with the `click` event, and `bind:thing` is
the `bind` directive with the `thing` data property. The one place we violate
that slightly is with `:foo`, which is shorthand for `foo={{foo}}` (since
people dislike the ceremony of passing props down between components, and this
makes it easier).

{{#if condition}}...{{/if}} tells Svelte something about the structure of your
app. {{{condition && '<p>Content</p>'}}} doesn't, and you can't add
interactivity to the <p> if it's just a string. Moreover, if `condition` is
`undefined`, then that's the string that will get rendered to the DOM.
Generally, {{{triples}}} should be used for blobs of HTML you get from data
sources, such as a blog post.

If you can overcome your distaste for the computed property dependency
injection, you'll hopefully find it's an extremely easy and compact syntax for
declaring arbitrarily complex graphs of properties. The advantage of doing it
this way is that Svelte can generate, at compile time, very efficient code for
updating computed properties without any wasteful runtime dependency tracking.
I realise it's slightly controversial (because it's a Svelte idiom, rather
than something in JS itself), but for those who have embraced them, computed
properties are one of the best features of Svelte!

~~~
tobr
The problem with Svelte's computed properties is that it's not just an idiom,
but a completely new language that happens to look like JS. It does things JS
can't, and breaks very basic things like functional composition.

Why not simply use the "correct" ES6 syntax to do the same thing? It's almost
identical:

    
    
      computed: {
        hours: ({time}) => time.getHours(),
        minutes: ({time}) => time.getMinutes(),
        seconds: ({time}) => time.getSeconds()
      }
    

This way, the compiler could simply optimise idiomatic cases where it's easy
to see which data is depended on, without breaking the language.

~~~
rich_harris
Interesting idea! I've raised an issue, thanks —
[https://github.com/sveltejs/svelte/issues/1069](https://github.com/sveltejs/svelte/issues/1069)

------
dmitriid
What I don't get in all these frameworks is the desire to invent new and
incompatible template languages with increasingly inane syntaxes. Oh. And, of
course, with stringly-typed programming and magic binding rules.

Just look at Svelte's templates: [https://svelte.technology/guide#template-
syntax](https://svelte.technology/guide#template-syntax)

Not only it's some custom implementation, it also breaks all assumptions about
_javascript_ code

    
    
       const counter = new Counter({
          data: {
            count: 99
          }
       });
    
       ...then {{count}}, or counter.get('count')
    

Why is it `counter.get('count')`? WTF?

Or just the section on computed properties[1]: oh, it's no longer even
Javascript. It's some magic Javascript-like scripting language that gets
injected with properties based on what you write.

Much like in Vue data, properties, and methods are magically hoisted up to the
object breaking everything you learned about Javascript:

    
    
      export default {
        methods: {
          say: function ( message ) {
            alert( message ); // again, please don't do this
          }
        }
      };
    
      // and then
    
      import MyComponent from './MyComponent.html';
    
      var component = new MyComponent({
        target: document.querySelector( 'main' )
      });
    
      component.say( '' );
    

Why the hell is `.say` a top-level method now?

And so on and so forth.

[1] [https://svelte.technology/guide#computed-
properties](https://svelte.technology/guide#computed-properties)

~~~
purple-again
I’m not an expert can I can chime in and say that .get and .set are common in
Ember data objects as well. No idea if it’s an ES6 thing or Ember thing
though.

~~~
dbbk
Those are Ember-specific, because ES getters and setters weren't widely
available at the time of introduction. They just dropped < IE 11 though so
they'll start to go away.

------
dfabulich
I think the major missing principle on this list is "streaming." (This is
missing in Next, too.)

The server should send down parts of the page as soon as their data becomes
available. Typically, pages have a "header" section that requires no data at
all, and the server should render it instantly and stream it to the client.
Then there's typically some fast-loading "above-the-fold" data; the server
should render and stream that as soon as it's ready. Beyond that, there's
other below-the-fold components, which may load/render more slowly. The server
should render those as they come in.

Then, the magic technique is to progressively attach event listeners to
components as they stream in, so you don't have to wait for the whole page to
load to be able to interact with above-the-fold components.

~~~
rich_harris
Sapper supports partial streaming if you have data that needs to be loaded
asynchronously (i.e. you'll get most of the <head> immediately, then other
stuff later), but it doesn't currently do what you suggest (such as loading a
<header> while <main> is pending). That's something that we intend to tackle
in future, though _hydrating_ pages with async data dependencies is a hard
problem.

------
AiDirex
How the fuck something that is in early development advertises as military
grade!

~~~
aspiringuzer
Getting new technologies to gain traction is not easy - regardless of their
technical merit. I do admire the framework designer's P.T. Barnum like
showmanship. He's got it down to a science.

------
antris
Now add to this the ability to write native apps on the iPhone and Android and
I'm sold.

------
kiernanmcgowan
Question:

> 1\. It should do server-side rendering, for fast initial loads and no
> caveats around SEO

Is server-side rendering still an issue for SEO? Don't major search engines
evaluate pages now so that SPAs can be indexed?

~~~
LeonM
I can confirm that Google can crawl SPA's like any other page. But do note
that they crawl using Chrome 41 (!) so make sure you have sufficient polyfills
in place.

This also applies for AdWords, it drove me mad when Google kept insisting my
site was not reachable, even though it was.

Only after installing a client-side exception tracking tool (like raygun or
errorception) I found out the page was not rendering on the 'old' browser
Goolge uses internally.

------
Ros2
Hey Rich, your hackernews clone doesn't perform all that well globally

[https://testmysite.io/5a4c2cdf819876444fa127b5/hn.svelte.tec...](https://testmysite.io/5a4c2cdf819876444fa127b5/hn.svelte.technology)

I really like Svelte! But I don't even serve my content from Express
middleware anymore due to the above problem.

I just feel like you're under-estimating a developer's resourcefulness to make
the content that actually _is_ static a static page, and also over-estimating
the number of new, traditional client/server web apps (at least by people who
are probably in your target audience).

Static performance is hard to beat _especially_ globally and there's a clear
performance degradation once you get away from the epicenter. Believe it or
not Svelte.technology's landing page actually performs noticeably more poorly
coast to coast in the US (>2x worse to load in California than NY--150ms vs
500ms).

I'm not saying give up or anything, just saying it might be a good idea to
talk to more JAMStack people :)

~~~
rich_harris
This is more of an ops thing than a framework thing. If you're making a purely
static app, JAMStack is great. Sapper is solving a different problem.

Having said that, we will eventually add the ability to 'export' a purely
static site that can be deployed to services like Netlify. Next.js has this,
but they didn't launch with it either. Bear with us!

------
jitlerr
Is there any way to use Sapper.js with React, Vue or anything framework? I
find the premise behind Sapper interesting, but I just don't see the appeal of
Svelte, where they are basically reinventing HTML syntax.

~~~
rich_harris
Svelte _is_ the premise behind Sapper. If you want to use React, use Next; if
you want to use Vue, use Nuxt; if you want that 7kb Hello World (instead of
Next's 204kb or Nuxt's 175kb) then you have to adopt a more efficient
approach.

We're not reinventing HTML, we're _using_ HTML. And CSS. ('Reinventing HTML'
is a far more fitting description of JSX, and then there's CSS-in-JS...)

Doing so is what allows us to statically analyse your app and compile it to a)
a tiny client-side JS payload, and b) an incredibly efficient server-side
renderer.

------
jchook
If you can "customise every aspect of the system" why does he spend a whole
paragraph complaining about people who like JSX? Shouldn't the answer be, "and
you can use JSX if you want"?

------
ashelmire
"This framework is 95% ideal, let's build another framework for my personal
5%."

This attitude is why we have a hundred different relevant frameworks right
now. How about instead of a building a new framework, you contribute to an
existing one? You even say that Next is close to what you want... why not help
to make it better?

Relevant song about this issue:
[https://www.youtube.com/watch?v=Wm2h0cbvsw8](https://www.youtube.com/watch?v=Wm2h0cbvsw8)

~~~
jazoom
Because then we'd all still be using an improved Angular, or even something
earlier. If that's what you want then you're welcome to make that happen for
yourself.

------
christophilus
Sounds interesting. He mentions that his gzipped size for the RealWorld
project is about 40KB. There was a good comparison done with this project[0]
in which one of the frameworks (AppRun) weighed in at 19KB. 19KB is pretty
crazy. Has anyone here used AppRun?

[0] [https://medium.freecodecamp.org/a-real-world-comparison-
of-f...](https://medium.freecodecamp.org/a-real-world-comparison-of-front-end-
frameworks-with-benchmarks-e1cb62fd526c)

------
antihero
Why on earth would I give a shit about SEO for a web application? The SEO is
for the brochure site that leads people toward the webapp, not the webapp
itself...

------
breatheoften
“Compiler as framework” seems like a really terrible unifying vision — a far
more interesting framing I think would be “type system as framework”. It’s the
difference between “this app is assembled by cobbling together a bunch of
random domain specific syntaxes” and “this app was assembled by combining
together resources with different well-defined, well-enforced constraints.”

~~~
ricardobeat
I’m having trouble visualising what you’re hinting at. How do DSLs relate to
static typing? Are you referring to writing all code in the same language (as
in JSX + JSS)?

------
aspiringuzer
I've used many web frameworks over the years and I really wanted to like this
Sapper technology, but for the life of me I just don't understand what problem
it's trying to solve. Can someone give me a comparison of what comparable
technologies it is replacing?

~~~
arxpoetica
There isn't really anything comparable. Really. It doesn't include the
framework in the end build. It's only in the original source. So it's a
compiler, not really a framework, that compiles to code that's performant to
specific tasks.

------
Rauchg
One of the authors of Next.js here. I want to clarify that all the points
against Next.js are virtues! They probably just arise from Rich not being so
familiar with it (or not having looked at the examples/ directory extensively:
[https://github.com/zeit/next.js/tree/canary/examples](https://github.com/zeit/next.js/tree/canary/examples))

1\. I think this point is trying to say that we don't have special "mask
files" inside `pages/`, which is an idea worth exploring. Right now, Next.js
instead gives you full flexibility on how you want to match the routes on your
server (as it should be). For example, `your-domain.com/xyz` can even first
perform a database query before deciding what page to render it with (if any).

2\. What the author points out as a weakness here is that you can handle
server things directly in your server code (`server.js` using micro or express
for example). That sounds like the right thing to do to me, and if you don't
want that, you still can do something like:

    
    
      // pages/my-server-page-only.js
      export default ({ req, res }) => res.end('hi')
    

3\. "To use the client-side router, links can't be standard <a> tags." This is
by design. Magically overloading `<a>` to add client-specific behavior sounds
like the days of jQuery or TurboLinks. If you want client-side behavior, wrap
`<a>` in the higher-order `<Link>` component. There also very important
properties of the `<Link>` like `<Link prefetch>` that are simply not part of
the `<a>` standard definition.

Also noteworthy: the entire ZEIT Documentation is written in Markdown with
React components. It's open source:
[https://github.com/zeit/docs](https://github.com/zeit/docs)

On size: the Next.js and React teams are both working towards really
interesting solutions to ship only the code that's necessary, without
resorting to templating as the main strategy. Our team actually spends more
time on the 'compiler' parts of Next.js than the 'framework API' parts. (the
API has barely changed since the initial 0.1 release in fact).

Additionally, since Next.js uses React as peer dependencies, you'll also get
to do `yarn add next react react-dom-lite` [https://github.com/jquense/react-
dom-lite](https://github.com/jquense/react-dom-lite) in the future.

Overall, I think Sapper is an excellent framework for Svelte users. I'm
looking forward to seeing more Next.js-like frameworks.

For Vue users: check out [https://nuxtjs.org/](https://nuxtjs.org/)!

~~~
rich_harris
Thanks Guillermo. I hope the respect and appreciation I have for the Next team
came across in the post.

My criticisms aren't based on misunderstandings, however. Route masking
provides flexibility but it really _does_ undermine the ability to navigate a
complex app structure — Nuxt.js evidently reached the same conclusion, because
they too have dynamic route parameters encoded in filenames.

The my-server-page-only.js results in a 'Cannot read property 'end' of
undefined' error for me, because it seems Next can't distinguish between
universal and server-only routes. If you have any examples of this working,
please do share them!

The Markdown ZEIT documentation is cool, but doesn't really address the
problem I was getting at with <Link>, which is that your content is likely to
come from a database. (Incidentally, Sapper does provide support for <a
rel=prefetch>, which works exactly the same as <Link prefetch>.)

> On size: the Next.js and React teams are both working towards really
> interesting solutions to ship only the code that's necessary, without
> resorting to templating as the main strategy.

I'm excited to see where that takes us. My conviction remains that templates
will always provide more and deeper optimisation possibilities than JSX, but
this is a competition in which ultimately we're all winners.

~~~
tribby
> Nuxt.js evidently reached the same conclusion, because they too have dynamic
> route parameters encoded in filenames.

nuxt.js applications don't need to rely on filenames for routing. there's a
handy nuxt module for this -- [https://github.com/nuxt-community/router-
module](https://github.com/nuxt-community/router-module)

------
young_greedo
ITT: a complete misunderstanding of how a universal JS web app works.

~~~
thomasfromcdnjs
Agreed. As a JS app developer I now feel more confident about my job security.

------
techaddict009
Why dont you guys use laravel when you need better SEO and server side
rendering? It is fast, easy to learn, easy to deploy, etc.

------
nwmcsween
Could webpack be replaced with something else? IMO webpack is a giant mess.

~~~
arxpoetica
Have you had a look at Rollup.js (incidentally by the author of Sapper).

------
chaostheory
Is there a reason why most Javascript web frameworks, like this one, tend to
ignore relational databases?

hmm, I don't even see a mention of how to integrate any datastore with Sapper
or did I miss something?

~~~
dbbk
> Is there a reason why most Javascript web frameworks, like this one, tend to
> ignore relational databases?

Yes, because these are frontend frameworks and that is a backend concern.

~~~
chaostheory
I could be wrong, but this doesn't look like a front end framework.

------
QGmLe
An ideal web app framework would not be in JavaScript...

~~~
wcarron
Do you have any other frameworks in mind? Ones that easily and concisely hook
into the DOM APIs provided by browsers? One that hot reloads in dev? Or maybe
just accomplishes even a handful of the 11 targets listed at the beginning of
the article?

Because I don't know of any. Except maybe the new Rust framework, Yew. Which
seems very interesting.

~~~
innocentoldguy
Perhaps you're right, there may not be one. However, I think the point the OP
is trying to make is that JavaScript is a shitty language and it would be
better to invest some effort in replacing it with something better than to
continuously try to "fix" all its inherent shitty-ness over and over again to
little avail. Sure, JavaScript isn't as shitty today as it was 10 years ago,
but it still isn't a well-thought-out, well-designed, or consistent language.

For examples of JavaScript's shitty-ness, I'd point to its various function
declaration styles and their disparate effects on the code you write, its
wishy-washy scoping, namespacing, the number type's precision problem, NaN
being a number type, the ambiguity of _this_ , just to name a few.

~~~
QGmLe
yes. well put

------
pwaai
How many of you actually built a React/Redux stack SPA that actually came
anywhere near what Sapper offers?

The file size problem is underrated. Not everybody walks around with 5G like
in South Korea. Not everybody has the latest and greatest Samsung or Apple
phone.

It's a big problem when you advertise PWA as quick and fast but then in tiny
letters mention its using the best case on best network and best phone. If you
design without worst case in mind, you've discriminated people based on
whether they can afford the best or not.

The vast majority of users don't. It's only recently that Android phones have
gotten cheap that its seeing widespread usage. These people are not going to
wait around for the React/Redux stack to load AND still wait on more data
coming through their 2g/3g connection. Oh, and there's slow rendering on older
Android phones and now you have a laggy Javascript app experience that
Lighthouse tells you everything is okay.

Let's not be so quick to judge. It's not as if Sapper has deviated from the
trend that even React team is acknowledging. This is a fresh approach to a
quickly monopolizing space, from an organization that has other agendas in
seeing their tech stack flourish.

I'm gonna definitely be watching Sapper.js in 2018 and if they deliver on most
of the 11 criterias, I know my customers and their customers will be happy.

~~~
mlsarecmg
You can boil down react to virtually nothing. preact-compat turns it into 4kb.
Redux + router don't add _that_ much. The loading impact, if you watch out,
code split, isn't the dire problem.

As for laggy experience, Fiber is the only feasible attempt at the moment to
actually tackle it. Microbenchmarks will not help and neither Svelte nor
anything else will make a webapp fast on a slow phone as baseline diffing has
never been the problem in the first place. The problem is and has been the dom
and the single threaded handling of it.

Fiber will allow apps to schedule. Imagine an app with 100.015 rows that
Svelte renders in, say, 500ms, let it be 10ms faster than React 15's 510ms. It
would still eat into your frame budget and cause heavy jank _like all web apps
do_. Fiber just wouldn't render the 100.000 rows that don't fit your phones
screen finishing the whole op under a single ms. It culls and prioritizes
similar to how virtual lists operate in general, but you get that as a _first
class primitive_ being able to defer any render call of lesser importance
without causing visual distortion or code complexity.

Not to mention that with React you could actually produce a real native app,
while redux would allow you to share most of your code. With something like
react-native-web you could even write a universal app being able to render
both in the web and natively.

~~~
leeoniya
> Imagine an app with 100.015 rows

i can imagine an app like this. and such an app would have been designed with
0 thought given to the actual usability by humans. the _proper_ solution is to
provide sorting, grouping, filtering and pagination. your UIs should be small
enough to remain fast without insane optimization tricks. mobile and even
desktop browsers are plenty slow at rendering/reflowing 100k DOM nodes; the
fastest way to render this is simply not to.

it's not as if suddenly you don't have to worry about the shitty UX and
performance of your app's architecture "because fiber".

~~~
mlsarecmg
The list is an example, the cheapest one to make it understandable. Let it be
2000, or 100, filtered and pre-processed. It would still take longer than the
15 the user actually sees. The point isn't the list, but the primitive.

I don't even know where the scepticism comes from, culling and priotization is
normal on the desktop. You've been offloading UI related tasks that could
interrupt animations or interactions in C# forever - it is a great tool to
have and getting it for the web is a major step. Microbenchmarks that measure
baseline deletes/adds/changes will simply not result in apps that feel native.
Thinking framework xyz will just feel acceptable to mobile users because
Krausest says it takes 1ms less adding 100.000 rows, that is just silly.

~~~
GordonS
I would think that some combination of sorting, grouping, filtering and
pagination would still make for a more user-friendly experience.

~~~
mlsarecmg
I don't think there's anything more user unfriendly and annoying than
pagination. Pull/click/scroll to load have been made to help it. But that
aside, the list isn't important. It could be dialog items, complex tree-views,
plugins, graphs, visuals in general, etc.

