How do you pass data to react components from express or koa without renderToString? - express

I'm unable to use React's server side rendering due to my use of client side libraries such as reqwest. I would like to pass some data to my react components, however. Is there a way to do this?

The easiest way to do this is by having api-client.js and api.js. In your browserify/webpack config you set up a client side version. For browserify put this in your package.json (feel free to edit and add webpack).
"browser": {
"./path/to/api.js": "path/to/api-client.js"
}
The second option is better in my opinion, but more difficult to implement. You create an abstract representation of your API that works like this:
var comments = require('./api').get('comments');
comments.getById('7').then(function(comment){ ... });
comments.create({...}).then(...);
On the server api.js simply calls the correct functions, which all return promises. On the client it returns a promise, makes an ajax request to the server, which calls these functions, and sends back the response, and the api client resolves/rejects its promise.
This allows the api to automatically work, and allows you to do additional things like track unfulfilled promises, and pre-populate state on the client, etc. (see react-async for example).

Related

Running method on every call using express-graphql

I'm using express-graqphl and was wondering if there is any concept of running a function before each graphql endpoint is executed? I'd like to have this for things like validating JWTs and other things. I realize we could use express for this, e.g.
app.use('/graphql`, doChecks);
but I'd like for the graphql handler to throw an error so it'll be inside the errors: [] list in the results giving the client a consistent experience with the api. Is there any direct support for this in the package?
The context function is executed before every request. If you're using Apollo v4+ then here are the docs
The context function is most often used to manage auth, including reading and validation of security tokens.

Using Vue Composition API with Pinia

I have a Vue 3 project and I'm working with Composition API. I'm communicating with my backend using Urql which is a graphql library which allows me to wrap API requests as composables.
I'm new to Pinia, but after a bit of time working with Vue 2 + Vuex I can tell that one of the most common scenarios of writing actions was making API requests and updating the state (asynchronously) with the response. I'm trying to adopt the same technique in my current tech stack and facing some issues.
My problem is that I can't just use the old fashioned fetch/axios/got libraries to execute requests whenever I want, I should first register the composable somewhere. I've seen that one option is to call the composable's use* function in the store's state section, but it seems weird to me to have such thing in there as it has nothing to do with the state. I've tried executing the use* method directly in an action, but it seems to fail.
I wonder if I'm missing some best-practice way to work with Urql and Pinia, as things are getting more and more complex even though my usecase is pretty common and simple. Should I use Urql's Client directly? Any other good solution to make gql requests from within my store actions?
export const useUsersStore = defineStore('app', {
actions: {
setUser() {
const response = (await useUsers()).data // this wont work
},
}
);

Workbox/Vue: Create a custom variation on an existing caching strategy handler

Background:
I'm building an SPA (Single Page Application) PWA (Progressive Web App) using Vue.js. I've a remote PostgreSQL database, serving the tables over HTTP with PostgREST. I've a working Workbox Service Worker and IndexedDB, which hold a local copy of the database tables. I've also registered some routes in my service-worker.js; everything is fine this far....
I'm letting Workbox cache GET calls that return tables from the REST service. For example:
https://www.example.com/api/customers will return a json object of the customers.
workbox.routing.registerRoute('https://www.example.com/api/customers', workbox.strategies.staleWhileRevalidate())
At this point, I need Workbox to do the stale-while-revalidate pattern, but to:
Not use a cache, but instead return the local version of this table, which I have stored in IndexedDB. (the cache part)
Make the REST call, and update the local version, if it has changed. (the network part)
I'm almost certain that there is no configurable option for this in this workbox strategy. So I would write the code for this, which should be fairly simple. The retrieval of the cache is simply to return the contents of the requested table from IndexedDB. For the update part, I'm thinking to add a data revision number to compare against. And thus decide if I need to update the local database.
Anyway, we're now zooming in on the actual question:
Question:
Is this actually a good way to use Workbox Routes/Caching, or am I now misusing the technology because I use IndexedDB as the cache?
and
How can I make my own version of the StaleWhileRevalidate strategy? I would be happy to understand how to simply make a copy of the existing Workbox version and be able to import it and use it in my Vue.js Service Worker. From there I can make my own necessary code changes.
To make this question a bit easier to answer, these are the underlying subquestions:
First of all, the StaleWhileRevalidate.ts (see link below) is a .ts (TypeScript?) file. Can (should) I simply import this as a module? I propably can. but then I get errors:
When I to import my custom CustomStaleWhileRevalidate.ts in my main.js, I get errors on all of the current import statements because (of course) the workbox-core/_private/ directory doesn't exist.
How to approach this?
This is the current implementation on Github:
https://github.com/GoogleChrome/workbox/blob/master/packages/workbox-strategies/src/StaleWhileRevalidate.ts
I don't think using the built-in StaleWhileRevalidate strategy is the right approach here. It might be possible to do what you're describing using StaleWhileRevalidate along with a number of custom plugin callbacks to override the default behavior... but honestly, you'd end up changing so much via plugins that starting from scratch would make more sense.
What I'd recommend that you do instead is to write a custom handlerCallback function that implements exactly the logic you want, and returns a Response.
// Your full logic goes here.
async function myCustomHandler({event, request}) {
event.waitUntil((() => {
const idbStuff = ...;
const networkResponse = await fetch(...);
// Some IDB operation go here.
return finalResponse;
})());
}
workbox.routing.registerRoute(
'https://www.example.com/api/customers',
myCustomHandler
);
You could do this without Workbox as well, but if you're using Workbox to handle some of your unrelated caching needs, it's probably easiest to also register this logic via a Workbox route.

Securing API keys in Nuxtjs

I've researched and found three different possibilities to solving my case: I'd like to make an async API call (using dotenv variables to store the credentials) and commit the returned data to Vuex on app init --keeping the creds secure.
Currently I'm attempting using serverMiddleware, but I'm having trouble accessing the context. Is this possible? Currently just getting a "store is not defined" error.
Also, after researching, I keep seeing that it's not a good idea to use regular middleware, as running any code on the client-side exposes the env variable... But I'm confused. Doesn't if (!process.client) { ... } take care of this? Or am I missing the bigger picture.
Additionally, if it does turn out to be okay to use middleware to secure the credentials, would using the separate-env-module be wise to make doubly sure that nothing gets leaked client-side?
Thanks, I'm looking forward to understanding this more thoroughly.
You can use serverMiddleware.
You can do it like this:
client -> call serverMiddleware -> servermiddleware calls API.
that way API key is not in client but remains on the server.
Example:
remote api is: https://maps.google.com/api/something
your api: https://awesome.herokuapp.com
since your own api has access to environment variables and you don't want the api key to be included in the generated client-side build, you create a serverMiddleware that will proxy the request for you.
So that in the end, your client will just make a call to https://awesome.herokuapp.com/api/maps, but that endpoint will just call https://maps.google.com/api/something?apikey=123456 and return the response back to you

Relay modern caching example

I would like to enable caching in my react native application. I am using GraphQL with Relay modern. I found out that caching is not enabled by default in relay modern, but they have exposed RelayQueryResponseCache from relay-runtime, which we can add to the fetchQuery function in our API. I read discussion here and here about it, but have not seen any example to get started. Can someone help me out on this?
EDIT:
Ok I came up with a solution. I think it misses few things but so far it serves our needs.
I have noticed that passing anything into QueryRenderer into cacheConfig results passing that value into fetchQuery function inside my environment.
So I have created a Component which loads the data by some relation and resolves it into the correct json structure requested by the query. Then I return this into the state. Then I extended my Component which contains QueryRenderer with the created 'cache loader'. Now when componentWillMount() is called I ask for the cached data. During this I have set this.state.loading = true so I am able to handle loading state. Reading from DB is async.
I am using this class in other components as well. Every one handles its cache data. I just pass it to QueryRenderer.
However I was thinking that this makes some extra logic need to add for each Component which is supported by this caching. Probably passing the cache resolver as cacheConfig and resolve the cached data immediately inside the environment would be much more cleaner.