Do you know if it's possible to re-execute Gatsby page queries (normal queries) manually?
Note, This should happen in dev mode while gatsby develop runs.
Background info: I'm trying to set up a draft environment with Gatsby and a Headless CMS (Craft CMS in my case). I want gatsby develop to run on, say, heroku. The CMS requests a Gatsby page, passing a specific draft-token as an URL param, and then the page queries should be re-executed, using the token to re-fetch the draft content from the CMS rather than the published content.
I'm hooking into the token-request via a middleware defined in gatsby-config.js. This is all based on https://gist.github.com/monachilada/af7e92a86e0d27ba47a8597ac4e4b105
I tried
createSchemaCustomization({ refresh: true }).then(() => {
sourceNodes()
})
but this completely re-creates all pages. I really only want the page queries to be extracted/executed.
Probably you are looking for this. Basically, you need to set an environment variable (ENABLE_GATSBY_REFRESH_ENDPOINT) which opens and exposes a /__refresh webhook that is able to receive POST requests to refresh the sourced content. This exposed webhook can be triggered whenever remote data changes, which means you can update your data without re-launching the development server.
You can also trigger it manually using: curl -X POST http://localhost:8000/__refresh
If you need a detailed explanation of how to set .env variables in Gatsby just tell me and I will provide a detailed explanation. But you just need to create a .env file with your variables (ENABLE_GATSBY_REFRESH_ENDPOINT=true) and place this snippet in your gatsby-config.js:
require("dotenv").config({
path: `.env.${activeEnv}`,
})
Of course, it will only work under the development environment but in this case, it fits your requirements.
Rebuild for all is needed f.e. when you have indexing pages.
It looks like you need some logic to conditionally call createPage (with all data refetched) or even conditionally fetch data for selected pages only.
If amount (of pages) is relatively not so big I would fetch for all data to get page update times. Then in loop conditionally (time within a few minutes - no needs to pass parameter) call createPage.
If develop doesn't call 'createPage' on /__refresh ... dive deeper into gatsby code and find logic and way to modify redux touched nodes.
... or search for other optimization techniques you can use for this scenario (queried data cached into json files?).
Related
I'm very very new to node.js, but there's actually only one simple thing that I am trying to achieve by learning the language.
I'd like to create a webpage, where by the code in a specific "div" can be hotswapped on the fly to users currently looking at that page. (ie. the div contains some text, but then an image replaces it.)
Ideally, the swap would be executed manually by the the webpage's admin through the click of a button, or some code fired off on the server or something. Regular viewers to the webpage would not be able to do this - they only see the live changes on the page.
real-life example:
live internet broadcast is off-air, therefore the "div" contains "off-air" text.
live hotswap of code happens when broadcast goes on-air, and the viewers of the webpage now see the html5 broadcast player in the "div" instead.
What's the simplest way to go about doing this for a node.js newbie?
Many thanks :)
Take a look at Socket.IO http://socket.io/#how-to-use
when the server decides to broadcast a change use:
io.sockets.emit('update-msg', { data: 'this is the data'});
on the client first connect socket.io and then wait for the "update-msg" event and update your dom:
var socket = io.connect('http://localhost');
socket.on('update-msg', function (msg) {
console.log(msg);
$('#mydiv').html(msg.data)
});
I created a system/methodology to live update (hot reload) front-end code using RequireJS and Node.js. I made sure it worked with both React and Backbone. You can read about it here:
https://medium.com/#the1mills/hot-reloading-with-react-requirejs-7b2aa6cb06e1
the basic steps involved in doing this yourself:
gulp.js watchers listen for filesystem changes
socket.io server in gulpfile sends a message to all browser clients
with the path of the file that changed
client deletes cache representing that file/module, and re-requires
it (using AJAX to pull it from the server filesystem)
front-end app is configured / designed to re-evaluate all references
to the modules that it wishes to hot-reload, in this case, only JS
views, templates and CSS are available to hot reload - the router,
controllers, datastores (Backbone Collections and Models) are not
configured yet. I do suspect all files could be hot reloaded with
the only exception being data stores.
I am developing react based web application using NEXT.js,. As specified in NEXT.js, documentation to fetch the data before page loads, i am putting required action dispatch code in getInitialProps of the specific page. but some data fetching calls(action dispatch) like fetching authenticated user's data will be common to all the pages, so is there any way to dispatch such actions from single place before page load.
Thanks!
update, now you can use getServerSideProps and nextjs provides an easy way to get user cookie : How to use cookie inside `getServerSideProps` method in Next.js?
--------- old answer ---------
simple answer: use cookie, code refer https://github.com/nextjs-boilerplate/next.js-boilerplate https://github.com/nextjs-boilerplate/next-fetch
-- details --
I had the same question when I first adopt next.js, as it worked in react, people prefer use a token to tag authed user and fetch always run in front-end. But as next.js made ssr a build in feature, I tried and find auth by cookie is possible, and I start https://github.com/nextjs-boilerplate/next.js-boilerplate and split out a fetch based on cookie https://github.com/nextjs-boilerplate/next-fetch
-- how it works --
1.client side fetch: use fetch option option.credentials = 'include' and option.headers.Cookie=document.cookie will patch cookie into your request. Bnd when fetch back result, this become wired, you cannot access cookie header, so you have to use another header and additional logic needed in backend logic like res.header('custom-set-cookie', res.getHeader('set-cookie'))
2.server side fetch: first you need the express request object, and get cookie like req.headers.cookie, then pack it into fetch request option. when fetch back, get cookie like r.headers._headers[cookieHeaderName] and pack into response res.header('set-cookie', setCookie)
then after you pack this transfer up, you can simply call a json api and cookie will automatically transfered. And if you don't need to change cookie through header (you can through js), you can ommit the extra handle like res.header('custom-set-cookie', res.getHeader('set-cookie')) in api
you can try my ssr login here http://nextjs.i18ntech.com/login
I use service worker with sw-toolbox library. My PWA caches everything except API queries (images, css, js, html). But what if some files will be changed someday. Or what if service-worker.js will be changed.
How application should know about changes in files?
My service-worker.js:
'use strict';
importScripts('./build/sw-toolbox.js');
self.toolbox.options.cache = {
name: 'ionic-cache'
};
// pre-cache our key assets
self.toolbox.precache(
[
'./build/main.js',
'./build/main.css',
'./build/polyfills.js',
'index.html',
'manifest.json'
]
);
// dynamically cache any other local assets
self.toolbox.router.any('/*', self.toolbox.cacheFirst);
// for any other requests go to the network, cache,
// and then only use that cached resource if your user goes offline
self.toolbox.router.default = self.toolbox.networkFirst;
I don't know what is the usual method to update cache in PWA. Maybe PWA should send AJAX request in background and check UI version?
AFAIK the sw_toolbox does not have a strategy for cache with network update. This is really what you want I think.
You want to modify the cache-network race strategy - > https://jakearchibald.com/2014/offline-cookbook/#cache-network-race
Instead of just letting the loser fade away, once the network responds you will want to update the client. This is a little more advanced that I have time or time to explain here.
I would post a message to the client to let it know there is an update. You may want to alert the user to the update or just force the update.
I don't consider this to be an edge case, but a very common, but advanced scenario. I hope to publish a more detailed solution soon.
There is nice solution written here where he states (in a nutshell) to either not use cache-first strategy or update a UX pattern of displaying a "Reload for the latest updates."
I dealt with services workers without using any library and the solution I ended up coming up with involved a bit of server side code and some client side. The strategy in a nutshell
Firstly the variables you will need and where:
On the server side have a "service worker version" variable (Put this in a database or config file if you are using something like php that will update immediately on the server side without requiring a redeploy. Let's call it serverSWVersion
On one of the javascript files you cache (I have a javascript file dedicated to this) have a global variable that will also be the "service worker version". Let's call it clientSWVersion
Now how to use the two:
Whenever a person lands on the page make an ajax call to your server to get the serverSWVersion value. Compare this with the clientSWVersion value.
If the values are different that means your web app version is not
the latest.
If this is the case then unregister the service worker and refresh the page so that the service worker will be re registered and the new files will be cached.
What to actually do when new file is available
Update the serviceSWVersion and clientSWVersion variables and upload to server where applicable.
When a person visits again then the service worker should be re registered and all the cached files will be retrieved.
I have provided a php server side based code that I used while I was implementing this strategy. It should show you the principles. Just drop the "Exercise" folder in a htdocs of a php server and it should work without you having to do anything else. I hope you find it useful... And remember you could just use a database instead of a config file to store the server side service worker variable if you are using some other server instead of php:
Zip file with code:
ServiceWorkerExercise.zip
When a service worker is altered, the browser will install it, but the new version will not be activated until the browser tab or PWA app window is closed and re-opened.
So, if you change the cache name, the new cache will not serve any files until the browser re-opens, nor will the old cache be deleted until that time.
You can detect service worker changes in your page javascript using registration.onupdatefound and ask the user to close and re-open the window - something like this:
// register the service worker
navigator.serviceWorker.register('sw.js').then(function(registration)
{
registration.onupdatefound = function()
{
console.log("ServiceWorker update found.");
alert("A new version is available - please close this browser tab or app window and re-open to update ... ");
}
}, function(err)
{
console.log('ServiceWorker registration failed: ', err);
});
change self.toolbox.router.any('/', self.toolbox.cacheFirst); to self.toolbox.router.any('/', self.toolbox.fastest);
I'm using loopback generator to generate models and rest APIs service. Now I wanted to modify a rest api such that everytime the api is called, some spcific logging/actions are taken.
I've come to know that by using remote hooks(beforeRemote, afterRemote), we can specify actions to be taken for different remote method calls. But what I don't know is that where to place the code of remote hooks. In which file this code will go when the project has been created using 'yo loopback'.
You would add code to the files under /common/models.
If you are using a Person model. You would add the following code in /common/models/person.js:
If you want to protect the REST API from a non logged in user or anonymous user you should use ACL. Have a look here:
Define access control from the intermediate tutorial
Authentication, authorization, and permissions
The REST API will respond with codes if someone unauthorized tries to get access (depending on what you define), for example 401. Then in the app if you receive that code, you should redirect to the login.
Now, every time you create a new model with slc loopback:model, it will generate 2 files in the common/models folder. One is a .js and the ohter a .json. You have to add the code in the .js file for the remote hooks.
Have a look to this link that explains how to add remote methods.
I'm very very new to node.js, but there's actually only one simple thing that I am trying to achieve by learning the language.
I'd like to create a webpage, where by the code in a specific "div" can be hotswapped on the fly to users currently looking at that page. (ie. the div contains some text, but then an image replaces it.)
Ideally, the swap would be executed manually by the the webpage's admin through the click of a button, or some code fired off on the server or something. Regular viewers to the webpage would not be able to do this - they only see the live changes on the page.
real-life example:
live internet broadcast is off-air, therefore the "div" contains "off-air" text.
live hotswap of code happens when broadcast goes on-air, and the viewers of the webpage now see the html5 broadcast player in the "div" instead.
What's the simplest way to go about doing this for a node.js newbie?
Many thanks :)
Take a look at Socket.IO http://socket.io/#how-to-use
when the server decides to broadcast a change use:
io.sockets.emit('update-msg', { data: 'this is the data'});
on the client first connect socket.io and then wait for the "update-msg" event and update your dom:
var socket = io.connect('http://localhost');
socket.on('update-msg', function (msg) {
console.log(msg);
$('#mydiv').html(msg.data)
});
I created a system/methodology to live update (hot reload) front-end code using RequireJS and Node.js. I made sure it worked with both React and Backbone. You can read about it here:
https://medium.com/#the1mills/hot-reloading-with-react-requirejs-7b2aa6cb06e1
the basic steps involved in doing this yourself:
gulp.js watchers listen for filesystem changes
socket.io server in gulpfile sends a message to all browser clients
with the path of the file that changed
client deletes cache representing that file/module, and re-requires
it (using AJAX to pull it from the server filesystem)
front-end app is configured / designed to re-evaluate all references
to the modules that it wishes to hot-reload, in this case, only JS
views, templates and CSS are available to hot reload - the router,
controllers, datastores (Backbone Collections and Models) are not
configured yet. I do suspect all files could be hot reloaded with
the only exception being data stores.