fab-spec / fab

💎 FAB project specification & monorepo
https://fab.dev
MIT License
579 stars 37 forks source link

Accessing the KV from the server (edge) side in likes of Next.js #296

Closed awthwathje closed 3 years ago

awthwathje commented 3 years ago

Hello! FAB looks absolutely fabulous at this point, but the one thing that will make it even more fabulous is the ability to bind the KV namespace, so we can write and read stuff to Cloudflare's KV data store right from the server, I mean, edge side!

So the typical use case when using server-side rendering frameworks like Next.js is to pre-render the HTML right after the client requested it for a first time. So (potentially slow) client won't waste time and network resources to populate the HTML with the actual custom data (think user's dashboard).

In the Next.js universe, there is a getServerSideProps() lifecycle method, which could be used to execute all the server-side stuff when it is needed, like calling APIs to obtain some data, modifying requests and so on. Sounds like a perfect fit for a Jamstack site powered by a distributed data store like Cloudflare Workers KV.

There is a caveat though: you can create a separate worker to fetch the data for you and you can call this worker from getServerSideProps() on the edge-side, but if both Next.js worker and this data fetching worker are in the same zone (on the same domain), the communication will fail with a 522 error code. This is not a bug, but rather a security feature by Cloudflare (they admitted to revisit it though, but no time indication is given).

With that being said, if worker-to-worker communication is not possible now, it would be great to have means to access the KV data store right from the Next.js getServerSideProps() (and likes, in other frameworks), utilizing a similar binding mechanism employed in Cloudflare Workers and Serverless Framework!

geelen commented 3 years ago

Hey, thanks for writing this up! I just added the support for custom bindings in the CF deployer here: https://github.com/fab-spec/fab/pull/295. And just published @fab/deployer-cf-workers v1.0.0-rc.8.p1 with it.

This adds the ability to add any custom bindings to the FAB CF script, which you can use for KV just fine. Documented here: https://fab.dev/guides/deploying#with-custom-bindings

Cloudflare docs on bindings: https://developers.cloudflare.com/workers/platform/scripts#resource-bindings

So, with a config like:

{
  //...
  deploy: {
    //...
    'cf-workers': {
      account_id: '@CF_WORKERS_ACCOUNT_ID',
      api_token: '@CF_WORKERS_API_TOKEN',
      workers_dev: true,
      script_name: 'your-app-name',
      custom_bindings: [
        {
          type: 'kv_namespace',
          name: 'DATA_STORE',
          namespace_id: '...', // get from Cloudflare dashboard
        },
      ],
    },
    //...
  },
}

you should be able to do getServerSideProps like:

export async function getServerSideProps() {
  const value = JSON.parse(await DATA_STORE.get('some-key'))
  return {
    props: {
      value
    }
  }
}

Good luck! 🤙

awthwathje commented 3 years ago

Kudos! You rock!