Next.js – A small framework for server-rendered universal JavaScript apps
zeit.co
zeit.co
It's definitely not hard for community members to build these abstractions themselves (`cookies = (req) => req ? req.headers['Cookie'] : document.cookie`), but some of these are going to play into major use cases like authentication, so, as Next matures, it'll start to make sense to provide these especially common abstractions out of the box.
That said, these are next steps; the first release is all about showcasing the fundamental architecture, and it's looking gooood :D
But what if my component looks like this:
import React from 'react'
export class exports React.Component {
static async getInitialProps () {
const res = await fetch('/api/user/123')
const data = await res.json()
return { username: data.profile.username }
}
}I want to get started with vue.js but there is NO mention of how to get data from a database. It is assumed the reader knows exactly what to do.
What you described is basically how I imagined it would work but I've just not been in this world for so long that I haven't been able to find the answer. (How to get data from a database with a system like vue.js.)
Libs like vue & react are essentially ui renderers, they create the html representation of app state, and handle all the DOM event binding and whatnot for you.
You will likely have some kind of client state management to take care of telling your ui to update, but essentially you will push json into that 'store' and that will then be used by your framework of choice to populate the page with content.
How that json gets there is largely upto you, and will be influenced by what you use to manage state, however you will need to handle getting data from the db server-side. Php or rails are popular, with reams of great (and some not so great) resources out there, but realistically you could use whatever you wanted.
Node.js is nice and could be useful if you want to focus on 1 language initially.
Partly I was tripped up because I have used Meteor and they handle everything for you. Before that I was using PHP and making SQL queries to MySQL directly.
In both of those cases I was able to get directly at the database. What you're saying is that I need a middle-tier that acts as the layer above the database but below the client (obviously.)
You mentioned Node.js. I know what that is and I know it's not a database. So it needs to connect to a database and then pass off data to the client. This is the piece of the puzzle I'm missing in my mental visualization.
I've learned that Laravel works well with Vue so I'll start there.
Thanks!
function ensureServerUrl(url) {
// parse and replace with your server url
// in Este you read from a SERVER_URL environment variable
}
function fetch(url, options) {
url = ensureServerUrl(url);
return fetch(url, options);
}In the case the GP describes, the proxying web server has no additional authority on the API server: if the API route requires a cookie from the user, it doesn't matter whether that's passed directly or proxied.
That being said, feel free to correct me if I'm missing something. Also, thank you very much for giving me the name for this problem, it will come in very handy.
How would you do that without breaking the whole universal/isomorphic aspect of this?
Some explanation at [3] although that writeup (and this demo code) needs updating.
[1] https://github.com/firasd/react-server-tutorial/blob/master/...
[2] https://github.com/firasd/react-server-tutorial/blob/master/...
[3] https://medium.com/@firasd/quick-start-tutorial-universal-re...
That entirely defeats the purpose of an isomorphic/universal React application.
Also because of network latency sometimes it's faster to just reload the whole page than to send a few async requests and wait for them to return while the user sits there wondering what's going on.
SSR: (client request) -> (server retrieves empty divs + js, API results used to fill initial page content) -> (fully rendered first page view + js delivered to client) -> (further page interaction calls APIs to mutate client side page)
Hammers and nails equivalent is cgi/perl/php/asp and they still do a fine job. You can use the screw machine to manually punch down screws, but then why not use the hammer and nails instead, as you do not see the advantage of the screw machine.
Not really any different from building say a PHP app that serves an API to a mobile app.
Keep reading past: "## Automatic server rendering and code splitting" & "## Anticipation is the key to performance"
Each sub-component is loaded dynamically which speeds up the initial load time but still allows for the 'flow' of single page apps.
- "For www.zeit.co we've implemented a technique on top of Next.js that brings us the best of both worlds: every single <Link /> tag pre-fetches the component's JSON representation on the background, via a ServiceWorker."
As another comment noted, a typical SPA just delivers a bunch of script, link and empty div tags to be populated after JS loads and runs on the client. With SSR you can at least provide some meaningful content for the user to experience while the rest of the JS loads and improves the existing experience instead of providing the entire experience.
* Simplicity. You don't need a fancy bunch of tools to cross-compile things, or any big frameworks, because a bunch of problems (browser compatibility especially) disappear. No more random people's browsers. You control every variable, and you can far more easily accurately test the end result.
* Shared data between requests. You can easily cache requests to backend services for multiple users, or even cache the entire rendered outputs of pages or parts of pages. Instead of every one of your users hitting a backend service from their browser and waiting for the result, you can hit it once every X, and then every other page load becomes just a cache read. In many simple cases you can have dynamically generated page content that's served up and readable after a single cache read, and update the cache totally async on the server too. Super fast.
* Data transfer, sometimes. If your end page is small but you use a lot of JS to render it, and your users load new pages more often than they reload content inside an already open page, then you might well end up transferring less data with a server-side approach (although this is very case specific).
* Page rendering times. If you use JS frameworks badly browers will really struggle, especially on mobile. Even with React you can really shoot yourself in the foot: https://github.com/reddit/reddit-mobile/issues/247. Obviously you shouldn't use JS frameworks badly, but people do. Static HTML + CSS reliable renders very very fast, everywhere.
* SEO. Google now has a degree of ability to run JavaScript (not unlimited, but fairly good), but nobody else seems to. Google is about 80% of US search traffic, so if any content you render client-side only will get about 20% less search traffic than it would otherwise.
* Accessibility. Some screen reading tools etc aren't great at JavaScript (although this is improving). More generally all sorts of other tools (site scrapers, sentiment analysis bots, whatever) have to put in way more effort to read your content.
* Network resilience - if you serve up only half an HTML page, or a couple of your external resources get dropped, your end user probably gets something sensible-ish. If you drop a JS file you depend on for rendering, it's all over. Offline with service workers is a good argument for progressive enhancement on top of this though: JS can also improve later network resilience drastically.
That's server-side rendering generally - the comparison gets more complicated and you lose some of this (simplicity especially) if you do isomorphic rendering (as here I think), where you render the page on the server and the client too.
Performance-wise, full server-side rendering is a huge step back. For dynamic web apps, next.js is going to drive up hosting costs massively and open you up to DDoS attacks because of server-side cache issues. I suppose it's OK for static websites.
s/common/uncommon
if you have to do additional template fetching via follow-up async requests, sure. but if you serve the js & js-parsed/executed template in the initial request, then the only difference would be a synchronous reflow/paint for js (white page flash) vs streamed/incremental reflow/repaint.
completely disabling scripting [rather that just disabling third-party script injection] is not a pleasant experience, even for the technical crowd. i already reluctantly have to whitelist CDNs which can track me across the internet.
You just described every single non-SPA...
I can pay to render everything for my user, essentially streaming their webpage to them. Or for the potential cost of a slightly slower page load I can offset the cost of all that rendering to their xGHz multi core CPU that's likely sitting idle.
Not to mention the cacheability of the data.
Yes, latency for a single bit of payload to ever hit the client. The rest of the data then needs to be transferred as well. Transferring that amount of data constantly would be terrible with regards to battery life.
> The CPU and the GPU could be several miles apart.
How exactly? Would you send draw commands over the internet?
It is funny how concepts come and go in circles. ASP.NET offered unified client and server development, though mostly in C#. It had the nuget package manager and VS store or something, but it was never amazing and packed like npm. Partial page postbacks and page state in encrypted strings..yikes. Now we have that in redux I suppose. It is all so familiar, yet so much better now.
Forward and backward navigation only works up to one level. Is that a limitation of the framework or an intentional design choice?
To me, tooling is very important since software is more consistent/reliable/productive at simple repetitive tasks like matching parenthesis, braces, quotes... and in my case I take it further like documenting types via documentation tags and verifying that function signatures and return types match. That alone helps me save a lot of time once the code has grown over 1 kSLOC.
I think it should be replaced to just a filename that gets required.
Especially for quickly prototyping an idea.
Getting a React project in place (webpack config, code structure, all the boilerplate, redux,...) swallows quite some time. And I haven't found a bootstrapper yet that I liked.
It took about half a day to get used to it, but I enjoyed not having to make the decisions over and over again and handles the basics as well as advanced use cases.
The only fundamental disagreement I have with it is how the "client" folder is organized by default. I think it's a mistake to organize by the type of file (component, reducers, etc). Instead, the organization should be centered around the real use (pages, resources, etc.) Explained in more detail here, https://medium.com/@alexmngn/how-to-better-organize-your-rea...
I understand that's personal preference, and my preference is born out of seeing more than one react app become a tangled mess because isolation was hard to understand based upon file structure.
Currently using it on a project and it works seamlessly.
Thank you for making this.
Meatier also uses Babel, React and Node.js except that it has been around for almost a year and is already stable. They've already solved all the difficult issues like realtime pagination, authentication, GraphQL, etc...
Meatier, as the name suggests, seems to be fundamentally "meatier" than next.js. It's coming from the same monolithic mindset as Meteor, and despite leading with the intro "... but without the monolithic structure", the general architectural thinking still appears to reflect that.
It makes a lot of decisions for you (express, rethinkdb, graphql, redux, etc. - it's production dependency list is gargantuan). You've phrased this as "they've already solved all the difficult issues", but many may see it as "they've removed a lot of choice and flexibility". It's a matter of perspective: the meatier docs do admit it's "overkill" for certain applications.
Next.js, apart from the inclusion of glamor, seems to pretty much largely leave you to your own architectural and library preferences.
What if you had a 'chatbox' component which updated every time a user wrote a message; would Next.js have to resend the entire HTML for the 'chatbox' component (containing the full message log) every time a message is added to that chatbox? Am I right to assume that only the affected component will be rerendered? Or the entire page has to be re-rendered (and the entire HTML of the page resent over the wire) for every change in data?
It sounds like a nightmare for caching: If data is updated dynamically and you constantly have to rerender components in realtime on the serverside; you can't really cache every permutation of every component's HTML for every data change and for every user... That's insane.
Regarding CPU, it sounds like it's going to eat up server-side performance and increase hosting costs massively! What, like 10 times 100 times? Are there any benchmarks done on performance for a typical single page app built with Next.js?
Then there is the latency issue...
Finally; if we move back to full server rendering and get rid of the need for client-side code; why would we want to stick to JavaScript?
I haven't used it yet so please correct me if I'm misunderstanding something.
Next.js sounds great for building static websites... But so does PHP!
The server only sends rendered components once, then the client handles the re-rendering afterwards.
It's still a javascript client-side SPA, except the initial rendering is done by the server. You don't see a loading screen, google can crawl your page, and users can see an initial page with JS turned off).
I hope that cleared things up a bit.
The logic for rendering loading screen in a component can quickly get tedious and annoying, such a pattern helps having a global loading screen and still allow the component to be responsible of how to fetch its data.
I've been reading a lot about SSR lately. Correct me if I'm wrong, but wasn't one of the points of thick clients to offload processing to the client?
Added bonus if the site works fine without client-side JS at all (which Next.js does)
"Filesystem as the API" in this case looks more like "convention over configuration" (which has worked fine for other frameworks like Rails), it doesn't actually seem to be using the filesystem as the only storage backend.
Next's routing is much more similar to Jekyll's which quite literally is based on your filesystem file-organisation.
This scheme seems to force route parameters into query parameters. Disadvantage: It's not RESTful. Advantage: Your route parameters are now named query parameters. You only handle one dict of parameters...
I'm not sure how I feel about this.
- You can't have beautiful URLs
- you can't regroup small related routes in one file
- you can't remap you urls without changing your project structure
- changing your project structure means changing your urls
- now you have part of your url definition in the file structure and part of it in your code logic
- of course it's harder to do anything using virtual routes: load balancing, aliasas and redirections, generating urls on the fly, etc
As it stands, my text editor defaults to the JS syntax highlighting. I suppose one could make JSX their default JS syntax, but then JSX would incorrectly appear to be correct in non-React files.
It hasn't taken off completely, and personally I like having the ".jsx" extension indicate that file will export a React component instead of plain javascript.
There are lots of arguments online about this: https://github.com/facebook/react/issues/3582#issuecomment-8... https://www.reddit.com/r/reactjs/comments/4kkrwg/ask_js_or_j...
And arguably it doesn't make a lot of sense, because when working with most modern frameworks/libs, JSX is not the only non-standard-js element in the file. Should we call it .es6, .es2015, .es2015+jsx ?
So yeah, sticking with .js is common.
JSX is not.
Preferences > Workspace Settings (to target your React project) >
{
"files.associations": {
"*.js": "javascriptreact"
}
}Why try to outsmart the browser?
> then things like the back button after scrolling through the blog would work.
What do you mean?
> Why try to outsmart the browser?
Not sure how this is outsmarting the browser.
Regarding the back button, you can see the mis-behavior here: 1) Go here: https://zeit.co/blog 2) Scroll all the way down to the bottom 3) Click a link 4) Click back
Expected: Page returns to exactly were you left off Actual: You are scrolled to a random blog post
My overarching question is why any type of SPA is needed for a site like zeit.co?
Breaking the behavior of my back button is one of the worst user experiences I get these days. Usually it makes me so angry that I just leave the site right away.
> Rather than waiting for the HTML to be downloaded when a link is clicked, most of the UI can be displayed while a smaller payload is downloaded.
Browsers can do that on their own since forever, given a carefully crafted HTML page. Of course there are use cases where that is not enough, needing some load-on-scroll mechanism or something like that, but it gets abused all the time for things a browser could handle so much better (with proper HTM of course) - blobs, newspaper articles etc.
Obviously that is not the wanted user experience. Disregarding SPAs as a solution because of an unintended behaviour is kind of throwing the baby out with the bath water.
> Browsers can do that on their own since forever, given a carefully crafted HTML page.
How are you rendering parts of something from a server before receiving anything from the server using only HTML? I'm talking about the following flow:
1. User clicks link
2. Instantly the layout etc. is rendering using JS, with fancy loading elements (maybe ala how FB does their news feed) for the missing items
3. The data is loaded and put into the layout
Whereas for the non-SPA flow the user would have to wait for data to be received before anything is rendered. Of course pre-fetching alleviates this a bit, but it still requires the whole page to re-render.
Performance better on Node? Feedback from the trenches would be appreciated.
Google bots do not view this rubbish favourably.
The Structured Data Testing Tool doesn't complain.
We'd need someone to try it out and get the results of the other Google Search Console tools to know for sure, however.
Minifying HTML, JS, CSS is a common practice
You may have missed it if you hadn't scrolled to the right.
Stylizing is done on the terminal itself, and then anything (like Quicktime) could do a recording.
It's not the gif OR the svg (individually) but somehow both together are causing it. I'm on Win7 with 2 gig ram and scrolling this (see pastebin) up from the bottom causes cpu to jump and memory near 1 gig with hdd looping endlessly, so i have to hard power off just to recover any function.
~