Mixing fully rendered and partially rendered pages with AngularJS - javascript

In my web app I keep part of the pages fully rendered on the server side (to make them easily indexed by google) and some of the pages should be rendered partially with AngularJS. Rendering full pages is straightforward, however, I'm confused when I want to mix it with partially rendered pages.
The problem I see is how to make it possible to navigate from a fully rendered page to partially rendered? Let's say that I have a fully rendered page at the following url: fakedomain.com/products/all Now, I want to allow users to edit their profiles and this would be a partially rendered page (available at fakedomain.com/#/user/profile).
How should I do all the routing and rendering?
I mean, when user clicks the option to edit his/her profile should I render index.html where I have ui-view declared? If yes, how do I make sure that correct partial is used?
btw. I'm using NodeJS on the server side and I'm pretty new to the client side stuff.

You can use AngularJS html5 mode https://docs.angularjs.org/guide/$location which takes away the hashbang. Then you need to route all requests to your app to the index.html (which loads angularjs).
You need to add exceptions for your static pages routes on your nodeJS app or your webserver, so that the requests for the static pages get handled correctly.
That should work allright and keep it an integrated experience for your users.

Related

Forcing refresh of cached JS in SPA (reactJS) that changes between requests using react router

I have come to the conclusion that my SPA using reactJS coupled with react router (react-router-dom 5, a client side routing service) CAN ONLY get a newly deployed javascript file IF IT is through a refresh. There is no other way. Am I wrong?
Scenario:
User is on the homepage
A new JS bundle gets deployed. (I am using webpack and using the following format: app.[hash].js as per webpacks's caching documentation. This is then referenced by index.html e.g. <script src="app.dc1abe70ccbf1b703e01.js">)
User now clicks on another link (new route) BUT the old JS still shows (even though there is new code available)
Only when a user does a refresh of the page, does the new code show. (Http status 200 and then 304 on each subsequent refresh until JS changes again which will result in another 200 and so on)
Now, I have gone though several threads, but I am still not clear on how to implement a simple solution to get a freshly deployed JS file WITHOUT a refresh from the back end for an SPA (ReactJS) using react router that replaces a cached version of the JS file between requests.
My understanding
When you use react router, a route is loaded within the SPA when clicked (client side) without requesting any html or js from the back end because there is no need to. i.e. the loading is instant because it's meant to be an SPA. This makes sense because as I said, when the app is loaded the first time, app.[hash].js is downloaded and subsequently referenced.
I have seen many other threads offering various solutions like:
forcing the server to issue a new JS file: script.js?v=1 This however is a hack and you will end up with multiple versions of js files in your browser as per this. Besides, I am using routes (essentially, links managed through react router). I think script.js?v=1 is for individual links. I am also using webpacks format for my js references: app.[hash].js
Others have asked the same question regarding caching and SPA's but never received replies like here and here
Conclusion and goal
According to this comment: This is expected behaviour and until user will not refreshes his page, new changes will not be loaded – Zohaib Ijaz Apr 13 at 14:02 from this thread
MOSTLY everything I have researched does not speak specifically to ReactJS PLUS react-router-dom. They mention versioning js files with a ?ver=xyz but that is for individual links I believe, NOT a router with routes. Some others mention using app.[hash].js but then stop short to explaining what to do next.
EVERYTHING I have researched leads me to believe that in order to see new JS changes the next time a react router link is clicked, my ReactJS SPA with react-router can only see these new changes if it is refreshed. And if so, then there is NO SOLUTION but to hope the customer will refresh the page (because this IS the practical solution)?
p.s I am using express server

How does angularjs not refresh on page change?

I've been learning about angularjs and have been very confused about how angular manages to change pages without refreshing and yet have a completely different view.
Are they actually changing the page URL or just hiding all the elements of on page and showing the other?
This video by CodeSchool explains it quite well.
AngularJS is just a tool that allows you to build single-page web applications with relative ease. What you are looking for is actually the definition of Single-Page Application:
Single-Page Applications (SPAs) are Web apps that load a single HTML page and dynamically update that page as the user interacts with the app. SPAs use AJAX and HTML5 to create fluid and responsive Web apps, without constant page reloads. However, this means much of the work happens on the client side, in JavaScript.
Also, from http://www.johnpapa.net/:
A SPA is fully (or close) loaded on the initial page load, it’s key
resources are preloaded, and progressively downloads features as
required.
And, more specific to your particular question:
When a user clicks on a menu item, the SPA sees that url and
translates it to a View that should be displayed. If the view has not
been seen before, the application may make an HTTP request to retrieve
the HTML template for the view. Then it will compose the view, fill in
the template, and display the view in the appropriate location within
the shell. If the view has already been viewed once, the browser may
have cached it and the router will be smart enough not to make the
request. This is one way a SPA can reduce round-tripping to and from a
server, and thus improve performance.
Keep in mind that this behavior is attained with the use of JavaScript, and does NOT require any specific library or framework (such as AngularJS), although you will probably want to learn how to use one to facilitate the process.
I also recommend you check these resources:
http://johnpapa.net/building-single-page-apps-with-knockout-jquery-and-web-api-ndash-the-story-begins/
http://www.johnpapa.net/pageinspa/
If your url's are mapped with the $routeProvider, you can reload a controller invoking $route.reload().

How to force reload if anything changes in JS while user is browsing in between partials

In my angular app, there is:
index.html: which holds all statics like js and css and a ng-view tag, which loads all the partials.
partials: which are loaded in ng-view as and when user reaches out.
So I am in/have confusion/doubt/issue, regarding a scenario, what if I change something in my controllers and compile will it get served again in the immediate new partials request to my server out of the box? if no what changes or configuration changes do I make to match it with the expectation.
Otherwise there is always a chance of broken experience, where partial is updated but js is old till user himself refreshes it.
PS: I am new to web-development and still learning these details.
If you update a partial and push that update into production, whenever your app now requests that partial (through user interaction via the app or a page reload) it will be the updated version. However if you update your angular app file, that change will not be displayed to the user until they refresh the page, because that resource has already been loaded by the browser and the browser has no way of knowing that the file has been changed and needs to be reloaded.
The reason the partials will appear updated is because your Angular app is sending http requests to get each one. The app cannot send a request to get a new version of itself (nor should it).

How to get page.js to work in a single page AND multipage on the same site?

am using page.js for routing in a Grails application using '/' to point /HomeController/index to serve up a single page web application. I just installed Grails Spring Security Core plugin, and I am using the Grails scaffolding to create the User Admin/Permissions views with the goal of serving them in the traditional multi-page way to avoid having to do a lot of UI work on admin pages. The bulk of the application will be served using single page architecture, with just the admin pages being served multi-page.
In their documentation, page.js says, "By default when a route is not matched, page.js will invoke page.stop() to unbind itself, and proceed with redirecting to the location requested. This means you may use page.js with a multi-page application without explicitly binding to certain links." But, I cannot get it to work...
I am using page.js like so:
page('/', SCM.Dashboard.home);
page('/hx', SCM.HX.summary);
page('/hx/vendor', SCM.HX.vendors);
page('/hx/customer', SCM.HX.customers);
page('/customer/list', SCM.Customer.list);
page('/maintenance/activity', SCM.Maintenance.activity);
page();
When I click a link to '/user', based on their documentation, I expect it to forward directly to 'http://domain.com/user'. It adds the correct path to browser location bar (http://domain.com/user), but the browser never forwards to the page. In order to see the page, I have to click the link, and after the location bar has changed, if I refresh the browser window, the correct page appears - obviously unacceptable. Yet, I cannot find in their documentation how to implement this correctly. I have experimented with various settings for hours with no luck. If I comment out the page.js code above, the multi-page admin pages work fine, and I am able to navigate from page to page no problem. Has anyone solved this problem?
I just upgraded from version 1.4.0 to version 1.5.0 and it links between the Single page (Main app) and Multi-page (Admin functionality) portions of the application seamlessly with no configuration needed!! Excellent feature addition!

Twitter Cards using Backbone's HTML5 History

I'm working on a web app which uses Backbone's HTML5 History option. In order to avoid having to code everything on the client and on the server, I'm using this method to route every request to index.html
I was wondering if there is a way to get Twitter Cards to work with this setup, as currently it can't read the page as everything is loaded in dynamically with Javascript.
I was thinking about using User Agents to detect whether it's the TwitterBot, and if it is, serving a static version of the page with the required meta-tags. Would this work?
Thanks.
Yes.
At one job we did this for all the SEO/search/facebook stuff etc.
We would sniff the user-agent, and if it was one of the following sniffers
Facebook Open Graph
Google
Bing
Twitter
Yandex
(a few others I can't remember)
we would redirect to a special page that was written to dump all the relevant data about the page for SEO purposes into a nicely formatted (but completely unstyled) page.
This allowed us to retain our google index position and proper facebook sharing even though our site was a total single-page app in backbone.
Yes, serving a specific page for Twitterbot with the right meta data markup will work.
You can test your results while developing using the card's preview tool.
https://dev.twitter.com/docs/cards/preview (with your static URL or just the tags).

Categories

Resources