• Stars
    star
    2,089
  • Rank 22,116 (Top 0.5 %)
  • Language
    TypeScript
  • License
    Apache License 2.0
  • Created almost 5 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Stale-while-revalidate data fetching for Vue

swrv

npm build

swrv (pronounced "swerve") is a library using the Vue Composition API for remote data fetching. It is largely a port of swr.

The name “SWR” is derived from stale-while-revalidate, a cache invalidation strategy popularized by HTTP RFC 5861. SWR first returns the data from cache (stale), then sends the fetch request (revalidate), and finally comes with the up-to-date data again.

Features:

  • Transport and protocol agnostic data fetching
  • Fast page navigation
  • Interval polling
  • SSR support (removed as of version 0.10.0 - read more)
  • Vue 3 Support
  • Revalidation on focus
  • Request deduplication
  • TypeScript ready
  • Minimal API
  • Stale-if-error
  • Customizable cache implementation
  • Error Retry

With swrv, components will get a stream of data updates constantly and automatically. Thus, the UI will be always fast and reactive.

Table of Contents

Installation

The version of swrv you install depends on the Vue dependency in your project.

Vue 3

# Install the latest version
yarn add swrv

Vue 2.7

This version removes the dependency of the external @vue/composition-api plugin and adds vue to the peerDependencies, requiring a version that matches the following pattern: >= 2.7.0 < 3

# Install the 0.10.x version for Vue 2.7
yarn add swrv@v2-latest

Vue 2.6 and below

If you're installing for Vue 2.6.x and below, you may want to check out a previous version of the README to view how to initialize swrv utilizing the external @vue/composition-api plugin.

# Install the 0.9.x version for Vue < 2.7
yarn add swrv@legacy

Getting Started

<template>
  <div>
    <div v-if="error">failed to load</div>
    <div v-if="!data">loading...</div>
    <div v-else>hello {{ data.name }}</div>
  </div>
</template>

<script>
import useSWRV from 'swrv'

export default {
  name: 'Profile',

  setup() {
    const { data, error } = useSWRV('/api/user', fetcher)

    return {
      data,
      error,
    }
  },
}
</script>

In this example, the Vue Hook useSWRV accepts a key and a fetcher function. key is a unique identifier of the request, normally the URL of the API. And the fetcher accepts key as its parameter and returns the data asynchronously.

useSWRV also returns 2 values: data and error. When the request (fetcher) is not yet finished, data will be undefined. And when we get a response, it sets data and error based on the result of fetcher and rerenders the component. This is because data and error are Vue Refs, and their values will be set by the fetcher response.

Note that fetcher can be any asynchronous function, so you can use your favorite data-fetching library to handle that part. When omitted, swrv falls back to the browser Fetch API.

Api

const { data, error, isValidating, mutate } = useSWRV(key, fetcher, options)

Parameters

Param Required Description
key yes a unique key string for the request (or a reactive reference / watcher function / null) (advanced usage)
fetcher a Promise returning function to fetch your data. If null, swrv will fetch from cache only and not revalidate. If omitted (i.e. undefined) then the fetch api will be used.
options an object of configuration options

Return Values

  • data: data for the given key resolved by fetcher (or undefined if not loaded)
  • error: error thrown by fetcher (or undefined)
  • isValidating: if there's a request or revalidation loading
  • mutate: function to trigger the validation manually

Config options

See Config Defaults

  • refreshInterval = 0 - polling interval in milliseconds. 0 means this is disabled.
  • dedupingInterval = 2000 - dedupe requests with the same key in this time span
  • ttl = 0 - time to live of response data in cache. 0 mean it stays around forever.
  • shouldRetryOnError = true - retry when fetcher has an error
  • errorRetryInterval = 5000 - error retry interval
  • errorRetryCount: 5 - max error retry count
  • revalidateOnFocus = true - auto revalidate when window gets focused
  • revalidateDebounce = 0 - debounce in milliseconds for revalidation. Useful for when a component is serving from the cache immediately, but then un-mounts soon thereafter (e.g. a user clicking "next" in pagination quickly) to avoid unnecessary fetches.
  • cache - caching instance to store response data in. See src/lib/cache, and Cache below.

Prefetching

Prefetching can be useful for when you anticipate user actions, like hovering over a link. SWRV exposes the mutate function so that results can be stored in the SWRV cache at a predetermined time.

import { mutate } from 'swrv'

function prefetch() {
  mutate(
    '/api/data',
    fetch('/api/data').then((res) => res.json())
  )
  // the second parameter is a Promise
  // SWRV will use the result when it resolves
}

Dependent Fetching

swrv also allows you to fetch data that depends on other data. It ensures the maximum possible parallelism (avoiding waterfalls), as well as serial fetching when a piece of dynamic data is required for the next data fetch to happen.

<template>
  <p v-if="!projects">loading...</p>
  <p v-else>You have {{ projects.length }} projects</p>
</template>

<script>
import { ref } from 'vue'
import useSWRV from 'swrv'

export default {
  name: 'Profile',

  setup() {
    const { data: user } = useSWRV('/api/user', fetch)
    const { data: projects } = useSWRV(() => user.value && '/api/projects?uid=' + user.value.id, fetch)
    // if the return value of the cache key function is falsy, the fetcher
    // will not trigger, but since `user` is inside the cache key function,
    // it is being watched so when it is available, then the projects will
    // be fetched.

    return {
      user,
      projects
    }
  },
}
</script>

Stale-if-error

One of the benefits of a stale content caching strategy is that the cache can be served when requests fail.swrv uses a stale-if-error strategy and will maintain data in the cache even if a useSWRV fetch returns an error.

<template>
  <div v-if="error">failed to load</div>
  <div v-if="data === undefined && !error">loading...</div>
  <p v-if="data">
    hello {{ data.name }} of {{ data.birthplace }}. This content will continue
    to appear even if future requests to {{ endpoint }} fail!
  </p>
</template>

<script>
import { ref } from 'vue'
import useSWRV from 'swrv'

export default {
  name: 'Profile',

  setup() {
    const endpoint = ref('/api/user/Geralt')
    const { data, error } = useSWRV(endpoint.value, fetch)

    return {
      endpoint,
      data,
      error,
    }
  },
}
</script>

State Management

useSwrvState

Sometimes you might want to know the exact state where swrv is during stale-while-revalidate lifecyle. This is helpful when representing the UI as a function of state. Here is one way to detect state using a user-land composable useSwrvState function:

import { ref, watchEffect } from 'vue'

const STATES = {
  VALIDATING: 'VALIDATING',
  PENDING: 'PENDING',
  SUCCESS: 'SUCCESS',
  ERROR: 'ERROR',
  STALE_IF_ERROR: 'STALE_IF_ERROR',
}

export default function(data, error, isValidating) {
  const state = ref('idle')
  watchEffect(() => {
    if (data.value && isValidating.value) {
      state.value = STATES.VALIDATING
      return
    }
    if (data.value && error.value) {
      state.value = STATES.STALE_IF_ERROR
      return
    }
    if (data.value === undefined && !error.value) {
      state.value = STATES.PENDING
      return
    }
    if (data.value && !error.value) {
      state.value = STATES.SUCCESS
      return
    }
    if (data.value === undefined && error) {
      state.value = STATES.ERROR
      return
    }
  })

  return {
    state,
    STATES,
  }
}

And then in your template you can use it like so:

<template>
  <div>
    <div v-if="[STATES.ERROR, STATES.STALE_IF_ERROR].includes(state)">
      {{ error }}
    </div>
    <div v-if="[STATES.PENDING].includes(state)">Loading...</div>
    <div v-if="[STATES.VALIDATING].includes(state)">
      <!-- serve stale content without "loading" -->
    </div>
    <div
      v-if="
        [STATES.SUCCESS, STATES.VALIDATING, STATES.STALE_IF_ERROR].includes(
          state
        )
      "
    >
      {{ data }}
    </div>
  </div>
</template>

<script>
import { computed } from 'vue'
import useSwrvState from '@/composables/useSwrvState'
import useSWRV from 'swrv'

export default {
  name: 'Repo',
  setup(props, { root }) {
    const page = computed(() => root.$route.params.id)
    const { data, error, isValidating } = useSWRV(
      () => `/api/${root.$route.params.id}`,
      fetcher
    )
    const { state, STATES } = useSwrvState(data, error, isValidating)

    return {
      state,
      STATES,
      data,
      error,
      page,
      isValidating,
    }
  },
}
</script>

Vuex

Most of the features of swrv handle the complex logic / ceremony that you'd have to implement yourself inside a vuex store. All swrv instances use the same global cache, so if you are using swrv alongside vuex, you can use global watchers on resolved swrv returned refs. It is encouraged to wrap useSWRV in a custom composable function so that you can do application level side effects if desired (e.g. dispatch a vuex action when data changes to log events or perform some logic).

Vue 3 example:

<script>
import { defineComponent, ref, computed, watch } from 'vue'
import { useStore } from 'vuex'
import useSWRV from 'swrv'
import { getAllTasks } from './api'

export default defineComponent({
  setup() {
    const store = useStore()

    const tasks = computed({
      get: () => store.getters.allTasks,
      set: (tasks) => {
        store.dispatch('setTaskList', tasks)
      },
    })

    const addTasks = (newTasks) => store.dispatch('addTasks', { tasks: newTasks })

    const { data } = useSWRV('tasks', getAllTasks)

    // Using a watcher, you can update the store with any changes coming from swrv
    watch(data, newTasks => {
      store.dispatch('addTasks', { source: 'Todoist', tasks: newTasks })
    })

    return {
      tasks
    }
  },
})
</script>

Cache

By default, a custom cache implementation is used to store fetcher response data cache, in-flight promise cache, and ref cache. Response data cache can be customized via the config.cache property. Built in cache adapters:

localStorage

A common usage case to have a better offline experience is to read from localStorage. Checkout the PWA example for more inspiration.

import useSWRV from 'swrv'
import LocalStorageCache from 'swrv/dist/cache/adapters/localStorage'

function useTodos () {
  const { data, error } = useSWRV('/todos', undefined, {
    cache: new LocalStorageCache('swrv'),
    shouldRetryOnError: false
  })

  return {
    data,
    error
  }
}

Serve from cache only

To only retrieve a swrv cache response without revalidating, you can set the fetcher function to null from the useSWRV call. This can be useful when there is some higher level swrv composable that is always sending data to other instances, so you can assume that composables with a null fetcher will have data available. This isn't very intuitive, so will be looking for ways to improve this api in the future.

// Component A
const { data } = useSWRV('/api/config', fetcher)

// Component B, only retrieve from cache
const { data } = useSWRV('/api/config', null)

Error Handling

Since error is returned as a Vue Ref, you can use watchers to handle any onError callback functionality. Check out the test.

export default {
  setup() {
    const { data, error } = useSWRV(key, fetch)

    function handleError(error) {
      console.error(error && error.message)
    }

    watch(error, handleError)

    return {
      data,
      error,
    }
  },
}

FAQ

How is swrv different from the swr react library

Vue and Reactivity

The swrv library is meant to be used with the Vue Composition API (and eventually Vue 3) so it utilizes Vue's reactivity system to track dependencies and returns vue Ref's as it's return values. This allows you to watch data or build your own computed props. For example, the key function is implemented as Vue watcher, so any changes to the dependencies in this function will trigger a revalidation in swrv.

Features

Features were built as needed for swrv, and while the initial development of swrv was mostly a port of swr, the feature sets are not 1-1, and are subject to diverge as they already have.

Why does swrv make so many requests

The idea behind stale-while-revalidate is that you always get fresh data eventually. You can disable some of the eager fetching such as config.revalidateOnFocus, but it is preferred to serve a fast response from cache while also revalidating so users are always getting the most up to date data.

How can I refetch swrv data to update it

Swrv fetcher functions can be triggered on-demand by using the mutate return value. This is useful when there is some event that needs to trigger a revalidation such a PATCH request that updates the initial GET request response data.

Contributors

Thanks goes to these wonderful people (emoji key):


Darren Jennings

💻 📖

Sébastien Chopin

💻 🤔

Fernando Machuca

🎨

ZEIT

🤔

Adam DeHaven

💻 📖 🚧

This project follows the all-contributors specification. Contributions of any kind welcome!

More Repositories

1

kong

🦍 The Cloud-Native API Gateway and AI Gateway.
Lua
38,724
star
2

insomnia

The open-source, cross-platform API client for GraphQL, REST, WebSockets and gRPC.
JavaScript
30,407
star
3

unirest-java

Unirest in Java: Simplified, lightweight HTTP client library.
Java
2,602
star
4

kubernetes-ingress-controller

🦍 Kong for Kubernetes: The official Ingress Controller for Kubernetes.
Go
2,127
star
5

mockbin

Mock, Test & Track HTTP Requests and Response for Microservices
JavaScript
1,988
star
6

mashape-oauth

OAuth Modules for Node.js - Supporting RSA, HMAC, PLAINTEXT, 2,3-Legged, 1.0a, Echo, XAuth, and 2.0
JavaScript
1,781
star
7

docker-kong

🐒 Docker distribution for Kong
Shell
1,392
star
8

unirest-php

Unirest in PHP: Simplified, lightweight HTTP client library.
PHP
1,282
star
9

httpsnippet

HTTP Request snippet generator for many languages & libraries
TypeScript
1,061
star
10

unirest-nodejs

Unirest in Node.js: Simplified, lightweight HTTP client library.
JavaScript
954
star
11

guardian

Remove the OAuth dance with one request.
JavaScript
640
star
12

deck

decK: Configuration management and drift detection for Kong
Go
437
star
13

unirest-python

Unirest in Python: Simplified, lightweight HTTP client library.
Python
432
star
14

apiembed

Embeddable API code snippets for your website, blog or API documentation
Pug
402
star
15

unirest-ruby

Unirest in Ruby: Simplified, lightweight HTTP client library.
Ruby
365
star
16

unirest-obj-c

Unirest in Objective-C: Simplified, lightweight HTTP client library.
Objective-C
276
star
17

kong-dist-kubernetes

Kubernetes managed Kong cluster
Shell
255
star
18

kong-manager

Admin GUI for Kong Gateway (Official)
TypeScript
242
star
19

kong-plugin

Simple template to get started with custom Kong plugins
Lua
238
star
20

charts

Helm chart for Kong
Mustache
224
star
21

lua-resty-worker-events

Cross Worker Events for Nginx in Pure Lua
Lua
190
star
22

unirest-net

Unirest in .NET: Simplified, lightweight HTTP client library.
C#
190
star
23

docs.konghq.com

🦍 Source code for docs.konghq.com website.
Ruby
186
star
24

kong-oauth2-hello-world

This is a simple node.js + express.js application that shows an authorization page for the OAuth 2.0 plugin on Kong.
JavaScript
173
star
25

kong-pongo

Tooling to run plugin tests with Kong and Kong Enterprise
Lua
154
star
26

lua-resty-dns-client

Lua DNS client, load balancer, and utility library
Lua
152
star
27

kongponents

🦍 Kong Vue Component Library
Vue
134
star
28

go-pdk

Kong Go Plugin Development Kit
Go
126
star
29

kong-vagrant

🐒 Vagrantfile for Kong testing and development
Shell
124
star
30

lua-resty-healthcheck

Healthcheck library for OpenResty to validate upstream service status
Lua
119
star
31

kong-plugin-prometheus

Prometheus plugin for Kong - this plugin has been moved into https://github.com/Kong/kong, please open issues and PRs in that repo
Lua
119
star
32

apiglossary

Open source glossary of API terms, acronyms and industry buzzwords.
95
star
33

go-kong

Go binding for Kong's admin API
Go
87
star
34

go-plugins

A collection of Kong plugins written in Go
Go
86
star
35

ngx_wasm_module

Nginx + WebAssembly
C
80
star
36

kong-terraform-aws

Kong Terraform Module for AWS
HCL
77
star
37

kong-build-tools

Build tools to package and release Kong
Shell
77
star
38

homebrew-kong

🐒 Homebrew tap for Kong
Ruby
69
star
39

kong-dist-cloudformation

🐒 Kong CloudFormation Stack
66
star
40

go-pluginserver

Kong Go Plugin Server
Go
66
star
41

kong-plugin-zipkin

A Kong plugin for propogating zipkin spans and reporting spans to a zipkin server - this plugin has been moved into https://github.com/Kong/kong, please open issues and PRs in that repo
Lua
60
star
42

kong-operator

Kong Operator for Kubernetes and OpenShift
Mustache
58
star
43

lua-multipart

Multipart Parser for Lua
Lua
55
star
44

mashape-php-library

Mashape PHP Server Library - Easily create an API in PHP. You can use it for existing services or brand new cloud components.
PHP
50
star
45

gateway-operator

Kubernetes Operator for Kong Gateways
Go
46
star
46

gojira

Multi-purpose tool to ease development and testing of Kong by using Docker containers
Shell
45
star
47

kong-python-pdk

Write Kong plugins in Python (Experimental)
Python
44
star
48

HARchiver

[Deprecated] Universal Lightweight Proxy for Galileo
OCaml
41
star
49

atc-router

Expression based matching library for Kong
Rust
41
star
50

koko

koko - Control Plane for Kong Gateway [open-source]
Go
41
star
51

unirest-website

Simplified, lightweight HTTP libraries in multiple languages
HTML
39
star
52

go-srp

Secure Remote Password library for Go
Go
38
star
53

tcpbin

TCP Request & Response Service, written in node.js
HTML
37
star
54

kong-plugin-acme

Let's Encrypt and ACMEv2 integration with Kong - this plugin has been moved into https://github.com/Kong/kong, please open issues and PRs in that repo
Lua
36
star
55

kong-portal-templates

Themes, components, and utilities to help you get started with the Kong Dev Portal.
CSS
35
star
56

kong-js-pdk

Kong PDK for Javascript and plugin server
JavaScript
35
star
57

kong-mesh-dist-kubernetes

Start Kong 1.0 as a K8s sidecar
Makefile
33
star
58

kubernetes-testing-framework

Golang Integration Testing Framework For Kubernetes APIs and Controllers.
Go
32
star
59

lua-kong-nginx-module

Nginx C module to allow deeper control of Nginx behaviors by Kong Lua code
Perl
32
star
60

demo-scene

🦍 a collection of demos and examples around Kong tools and technologies
JavaScript
30
star
61

konnect-portal

Konnect OSS Dev Portal
TypeScript
30
star
62

docker-java8

A Dockerfile for starting a container with Java 8 installed
30
star
63

Astronode-Broadcaster

A TCP replication server, or broadcaster, that replicates TCP commands to other TCP servers
Java
29
star
64

insomnia-docs

This repository houses all Insomnia documentation.
JavaScript
29
star
65

opentracing-lua

Opentracing Library for Lua
Lua
28
star
66

lua-resty-events

Inter process Pub/Sub pattern for Nginx worker processes
Raku
28
star
67

boss.js

Automatically load balance asyncronous jobs across multiple processes in a round-robin fashion.
JavaScript
27
star
68

kong-portal-cli

Kong Developer Portal CLI
TypeScript
25
star
69

lua-uuid

Lua library to generate UUIDs leveraging libuuid
Lua
25
star
70

lua-resty-aws

AWS SDK for OpenResty
Lua
24
star
71

lua-resty-lmdb

Safe API for manipulating LMDB databases using OpenResty/Lua.
C
24
star
72

kong-plugin-request-transformer

Kong request transformer plugin - this plugin has been moved into https://github.com/Kong/kong, please open issues and PRs in that repo
Lua
22
star
73

lua-resty-timer

Extended timers for OpenResty
Perl
22
star
74

lua-resty-counter

Lock-free counter for OpenResty
Perl
21
star
75

kong-plugin-session

🍪 Session plugin for Kong - this plugin has been moved into https://github.com/Kong/kong, please open issues and PRs in that repo
Lua
20
star
76

lua-pack

A library for packing and unpacking binary data.
C
20
star
77

go-apiops

Kong's Go based APIOps library
Go
19
star
78

swagger-ui-kong-theme

Plugin theme for Swagger-UI that adds snippets
JavaScript
19
star
79

terraform-provider-konnect

Terraform Provider for Kong Konnect
Go
18
star
80

api-log-format

Specification and examples of the new API logging format ALF
17
star
81

kong-plugin-serverless-functions

Kong Serverless Plugins - this plugin has been moved into https://github.com/Kong/kong, please open issues and PRs in that repo
Lua
17
star
82

apistatus

API status is a simple tool that checks if an API is online. http://apistatus.org
JavaScript
15
star
83

changelog-generator

a changelog generator focused on flexibility and ease of use
TypeScript
14
star
84

openresty-patches

Moved to https://github.com/Kong/kong-build-tools
Perl
14
star
85

kong-plugin-grpc-gateway

Kong Plugin to transcode REST request to gRPC - this plugin has been moved into https://github.com/Kong/kong, please open issues and PRs in that repo
Lua
14
star
86

lua-resty-consul-event

Consul Events HTTP API Wrapper
Perl
14
star
87

srp-js

Fork of node-srp modified to work in the browser
TypeScript
14
star
88

KongAir

An example Kong Konnect application deployed with Kong APIOps
JavaScript
13
star
89

harplayer

Replay HAR logs
JavaScript
13
star
90

kong-plugin-aws-lambda

AWS Lambda plugin - this plugin has been moved into https://github.com/Kong/kong, please open issues and PRs in that repo
Lua
13
star
91

openresty-build-tools

Moved to https://github.com/Kong/kong-build-tools
Shell
13
star
92

priority-updater

Tool to quickly create a plugin with an updated priority
Lua
13
star
93

jenkins-infrastructure

Cloudformation to create and update an ECS cluster that runs jenkins
Shell
12
star
94

httpbin

Python
12
star
95

kong-custom-plugin-workshop

Lua
12
star
96

kong-apisecops-redhat

Self-paced demo of APISecOps with ROSA and Kong Konnect
Jinja
12
star
97

version.lua

Simple version comparison library
Lua
11
star
98

kong-license

Kong Inc internal script to manage your local test license
Shell
11
star
99

kong-plugin-proxy-cache

HTTP Proxy Caching for Kong - this plugin has been moved into https://github.com/Kong/kong, please open issues and PRs in that repo
Lua
11
star
100

openapi2kong

Lib to convert OpenAPI specs into Kong specs
Lua
11
star