react-router: Why the preference for browserHistory over hashHistory? - react-router

I'm relatively new to React; apologies if this is a really naive question.
What are the technical advantages to browserHistory that make it preferable over hashHistory? For example, is there a major performance/efficiency boost from it using the History API?
The docs state that browserHistory is recommended, even though this comes at the cost of the additional server config and needing to hard-code or configure your base URL for different servers via basename.
hashHistory "just works", however, regardless of the base URL from which the files are served. No server config needed. Bundle your app, host it from any URL/path on a server, good to go.
It might be good if the docs went a bit further in explaining why it browserHistory is recommended even though it involves more complexity.

In some cases hashHistory is fine - except when you start dealing with server-side logic that needs to know a full URL of the original request.
Browsers do not send the #hash part of URL in any of HTTP requests.
Therefore server-side (i.e. NodeJS) would not know what #hash was in the URL when user requested a page.
A good example is user trying to load a page that requires a login (via oAuth etc.). Before user is taken to a separate website for authentication, you app's server-side would tell the authentication vendor what URL redirect user to after a successful login (usually it is to the original URL requested as most websites do this). If you were to use hashHistory - server-side would know only the bits before # symbol and would redirect user to the main page of your app and not a sub-page that user wanted to load.
I hope that makes sense.

One reason browserHistory is preferred over hashHistory is that it is better for deployment and production. hashHistory "works" by adding a unique key at the end of the url and creates a "history" for this by using these keys to keep track of your current session.
browserHistory looks much cleaner without the #, but in order to get this set up, you need to configure your server such that it can handle the URLs you intend to provide it.
Hope that helps!

What are the technical advantages to browserHistory that make it preferable over hashHistory?
It allows you to have a server side fallback which:
Allows the first page visited to initialize with HTML (rather than having to fetch all the data with Ajax) which gives better performance
Means the site keeps working even when JS fails (this is also better for search engines).
This comes at the cost of having to write the server side code to build pages in the same way that the client side code does. Without that, using the history API is objectively worse … but the URLs are, very subjectively, nicer so lots of people do it without the server side half anyway.

Related

How can I adapt my gulp static asset revisioning to work with ServiceWorkers?

Context: I have a production application (here if you want to look) that is currently using static asset revisioning using the gulp-rev-all package which is like gulp-rev except that it also handles dependencies when generating content hashes. It generates a new set of files that have static names (eg goals.js becomes goals.6a5aa614.js) and that reference each other using those static names. Then I serve those files up with the Fastly CDN on production, so my NodeJS server isn't being actively used for static assets. This has been working great.
Now I'm in the process of making the site work offline with service-workers. Since I'd done a lot of work on the syncing logic last year, the dynamic part of the site has been pretty easy to overhaul. But I'm a bit at a loss for what to do with my static assets.
I figured I'd use workbox, and that seems to work okay. But the workbox precache uses queries for busting the cache rather than changing filenames, and it seems dumb to do both. But if I stop using the versioned names, then how do I bust the cache on browsers that don't support service worker?
(I have another related question, which is does it make sense to keep using Fastly given that Fastly's responses will be opaque to the SW and therefore not necessarily a good option for precaching? Although without Fastly the app would become a lot slower for anyone who isn't using service workers, which sounds antithetical to the PWA approach. Should I add an nginx cache or something? (I have little idea what this is but I've heard it mentioned a few times))
It seems to me like there's got to be an elegant solution for this, but my understanding of gulp is sufficiently limited that it's hard for me to know what is possible, and my understanding of ServiceWorkers & caching is sufficiently limited that it's hard for me to know exactly what I want.
I'm therefore having trouble getting any traction on this question:
How can I adapt my gulp static asset revisioning to work with ServiceWorkers?
One thing that would be helpful is just a link to examples of how other production applications handle this.
Service worker works best on top of good regular caching strategy. You should continue to revision your static file names then cache them in the service worker. Avoid libraries that alter the URL via a query string, you don't need that feature as you're already revisioning the URL.
If your assets are served from another origin (I guess this is what you mean when you're talking about Fastly), then allow them to be requested via CORS (via Access-Control-Allow-Origin: *), that means they won't be opaque.
You should keep the file-revisioned assets. For a complete example using gulp and precaching take a look here.
You basically want to use a cache-first, then network pattern. You can match for requests to /goals.*.js/ => and then, depending on your application, you could decide to use the cached goals.js even if the [hash] doesn't match, and then download the new goals.[hash].js in the background.
Or, if the hash doesn't match, you may want to go with a network first, fallback to fuzy-matching cache of goals.js.
As for Nginx. It is often suggested to use a reverse proxy for the static asset serving. Node.js is not great for this task. Here is a good working example. If you go with this setup your flow for the static assets would look like this:
CDN => <= Nginx => Node.js Origin.
If you use AWS. Then a typical setup with Cloudfront CDN would involve setting your Nginx reverse proxy node.js EC2 box as the origin. Then you'd setup a behavior for "/" route and your "/assets" route.
The "/" behavior would likely have a short TTL, while the "/assets/" behavior (route in Cloudfront) would have your long-term (max-age=3153600) caching strategy.
In this scenario almost all static assets will be served from the CDN (Cloudfront). It will only have to go back to your origin when you deploy new code with a new set of file-revisioned assets.
You then use the service worker to make all repeat visits extremely quick, potentially even using an outdated asset (matching name, different hash) on initial repeat visit, by going cache first, then network. Thus all repeat users with the service worker will have a fast as possible initial page load.
Those without it will still get all the benefits of file revisioned, long-term browser cached assets with CDN edge serving.

Sending functions rather than data

Nowadays, we always think like "send your data to a server, it computes it for you, then send you back the response".
But imagine something else : i want my client to compute the data itself.
The question is : is there something like a universal protocol to send actions rather than data through http ? So that the server can send the action to the client, whatever system it uses. If it does not exist, what are the technical difficulties you can face creating this kind of system ?
I'm talking about "static" actions, like mathematical functions for example.
You're unfortunately going to run into a problem pretty quick because, technically speaking, a universal language is impossible. Systems are going to have different architecture, different languages available, and different storage means. I believe what you intend (correct me if I'm wrong) is a "widespread" protocol. One way or another, you're going to have to drill down based on your personal use-case.
For a widespread example, you could keep a set of JavaScript files with functions server-side, and refer a web client to the one they need to run it by loading a javascript file during some event. Pass the location of the file and the function name, load it using the link above, then call the JavaScript function by name to run it. I could see this being an admitedly somewhat roundabout solution. This also may work in Java due to its built in JavaScript engine, although I haven't tested it.
Beyond that, I am unaware of anything particularly widespread. Most applications limit what they accept as instructions quite strictly to prevent security breaches (Imagine a SQL Injection that can run free on a client's machine). In fact, JavaScript limits itself quite severely, perhaps most notably in regards to local file reading.
Hopefully this helps with your ideas. Let me know in a comment if you have any questions/issues about what I've said.

Sending continuous data over HTTP with Go

I am currently working on a web service in Go that essentially takes a request and sends back JSON, rather typical. However, this particular JSON takes 10+ seconds to actually complete and return. Because I am also making a website that depends on the JSON, and the JSON contents are subject to change, I implemented a route that quickly generates and returns (potentially updated or new) names as placeholders that would get replaced later by real values that correspond to the names. The whole idea behind that is the website would connect to the service, get back JSON almost immediately to populate a table, then wait until the actual data to fill in came back from the service.
This is where I encounter an issue, potentially because I am newish to Go and don't understand its vast libraries completely. The previous method that I used to send JSON back through the HTTP requests was ResponseWriter.Write(theJSON). However, Write() terminates the response, so the website would have to continually ping the service which could now and will be disastrous in the future
So, I am seeking some industry knowledge into my issue. Can HTTP connections be continuous like that, where data is sent piecewise through the same http request? Is that even a computationally or security smart feature, or are there better ways to do what I am proposing? Finally, does Go even support a feature like that, and how would I asynchronously handle it for performance optimization?
For the record, my website is using React.js.
i would use https websockets to achieve this effect rather than a long persisting tcp.con or even in addition to this. see the golang.org/x/net/websocket package from the go developers or the excellent http://www.gorillatoolkit.org/pkg/websocket from gorilla web toolkit for use details. You might use padding and smaller subunits to allow interruption and restart of submission // or a kind of diff protocol to rewrite previously submitted JSON. i found websocket pretty stable even with small connection breakdowns.
Go does have a keep alive ability net.TCPConn's SetKeepAlive
kaConn, _ := tcpkeepalive.EnableKeepAlive(conn)
kaConn.SetKeepAliveIdle(30*time.Second)
kaConn.SetKeepAliveCount(4)
kaConn.SetKeepAliveInterval(5*time.Second)
Code from felixqe
You can use restapi as webservice and can sent data as a json.SO you can continously sent data over a communication channel.

Is it possible to do client-side page/DOM caching with localStorage?

I'm reading up on Local Storage in HTML5, and I'm starting to view it sort of like a client-side version of how I use memcached. That got me thinking -- I currently do page-level caching in memcache.
Is that possible with localStorage? That is, can an assembled page store itself (or, more importantly, maybe parts of itself) in localStorage such that the client doesn't have to work its DOM so hard next time the user shows up to a page?
It seems to me that since things are only stored as strings this may not work unless there is some string to object transformation available.
Have a look at Christian's 2010 24ways post under the heading Caching a full interface (near the end). He basically does:
localStorage.setItem('state',f.innerHTML);
Followed by:
if('state' in localStorage){
f.innerHTML = localStorage.getItem('state');
}
Where f is the element he wants to cache.
The problem with this is that you don't know what's in the cache until you've loaded your page, meaning that you'd need to perform another HTTP request to get the data that you do need which leads to even more overhead. I would definitely stick with the server-side caching of resources.
You could do it, but something like this would basically involve a single, master index page of Javascript that either loaded cached local files or performed Ajax requests to load content from the server.

Google App Engine - Caching generated HTML

I have written a Google App Engine application that programatically generates a bunch of HTML code that is really the same output for each user who logs into my system, and I know that this is going to be in-efficient when the code goes into production. So, I am trying to figure out the best way to cache the generated pages.
The most probable option is to generate the pages and write them into the database, and then check the time of the database put operation for a given page against the time that the code was last updated. Then, if the code is newer than the last put to the database (for a particular HTML request), new HTML will be generated and served, and cached to the database. If the code is older than the last put to the database, then I will just get the HTML direct from the database and serve it (therefore avoiding all the CPU wastage of generating the HTML). I am not only looking to minimize load times, but to minimize CPU usage.
However, one issue that I am having is that I can't figure out how to programatically check when the version of code uploaded to the app engine was updated.
I am open to any suggestions on this approach, or other approaches for caching generated html.
Note that while memcache could help in this situation, I believe that it is not the final solution since I really only need to re-generate html when the code is updated (as opposed to every time the memcache expires).
In order of speed:
memcache
cached HTML in data store
full page generation
Your caching solution should take this into account. Essentially, I would probably recommend using memcache anyways. It will be faster than accessing the data store in most cases and when you're generating a large block of HTML, one of the main benefits of caching is that you potentially didn't have to incur the I/O penalty of accessing the data store. If you cache using the data store, you still have the I/O penalty. The difference between regenerating everything and pulling from cached html in the data store is likely to be fairly small unless you have a very complex page. It's probably better to get a bunch of very fast cache hits off memcache and do a full regenerate every once in a while than to make a call out to the data store every time. There's nothing stopping you from invalidating the cached HTML in memcache when you update, and if your traffic is high enough to warrant it, you can always do a multi-level caching system.
However, my main concern is that this is premature optimization. If you don't have the traffic yet, keep caching to a minimum. App Engine provides a set of really convenient performance analysis tools, and you should be using those to identify bottlenecks after you've got at least a few QPS of traffic.
Anytime you're doing performance optimization, measure first! A lot of performance "optimizations" turn out to either be slower than the original, exactly the same, or they have negative user experience characteristics (like stale data). Don't optimize until you're certain you have to.
A while ago I wrote a series of blog posts about writing a blogging system on App Engine. You may find the post on static generation of HTML pages of particular interest.
This is not a complete solution, but might offer some interesting option for caching.
Google Appengine Frontend Caching allows you a way of caching without using memcache.
Just serve a static version of your site
It's actually a lot easier than you think.
If you already have a file that contains all of the urls for your site (ex urls.py), half the work is already done.
Here's the structure:
+-/website
+--/static
+---/html
+--/app/urls.py
+--/app/routes.py
+-/deploy.py
/html is where the static files will be served from. urls.py contains a list of all the urls for your site. routes.py (if you moved the routes out of main.py) will need to be modified so you can see the dynamically generated version locally but serve the static version in production. deploy.py is your one-stop static site generator.
How you layout your urls module depends. I personally use it as a one-stop-shop to fetch all the metadata for a page but YMMV.
Example:
main = [
{ 'uri':'about-us', 'url':'/', 'template':'about-us.html', 'title':'About Us' }
]
With all of the urls for the site in a structured format it makes crawling your own site easy as pie.
The route configuration is a little more complicated. I won't go into detail because there are just too many different ways this could be accomplished. The important piece is the code required to detect whether you're running on a development or production server.
Here it is:
# Detect whether this the 'Development' server
DEV = os.environ['SERVER_SOFTWARE'].startswith('Dev')
I prefer to put this in main.py and expose it globally because I use it to turn on/off other things like logging but, once again, YMMV.
Last, you need the crawler/compiler:
import os
import sys
import urllib2
from app.urls import main
port = '8080'
local_folder = os.getcwd() + os.sep + 'static' + os.sep + 'html' + os.sep
print 'Outputting to: ' + local_folder
print '\nCompiling:'
for page in main:
http = urllib2.urlopen('http://localhost:' + port + page['url'])
file_name = page['template']
path = local_folder + file_name
local_file = open(path, 'w')
local_file.write(http.read())
local_file.close()
print ' - ' + file_name + ' compiled successfully...'
This is really rudimentary stuff. I was actually stunned with how easy it was when I created it. This is literally the equivalent of opening your site page-by-page in the browser, saving as html, and copying that file into the /static/html folder.
The best part is, the /html folder works like any other static folder so it will automatically be cached and the cache expiration will be the same as all the rest of your static files.
Note: This handles a site where the pages are all served from the root folder level. If you need deeper nesting of folders it'll need a slight modification to handle that.
Old thread, but i'll comment anyways as technology has progressed a little...
Another idea that may or may not be approproate for you is to generate the HTML and store it on Google Cloud Storage.
Then access the HTML via a CDN link that the cloud storage provides for you.
No need to check memcache or wait for datastore to wake up on new requests.
Ive started storing all my JavaScript, CSS, and other static content (images, downloads etc) like this for my appengine apps and its working well for me.