Skip to content

Commit

Permalink
docs: ssr instantsearch
Browse files Browse the repository at this point in the history
  • Loading branch information
Baroshem committed Jan 15, 2024
1 parent 2f8906b commit 9460dc1
Showing 1 changed file with 102 additions and 1 deletion.
103 changes: 102 additions & 1 deletion docs/content/2.advanced/1.vue-instantsearch.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ Finally, let's use it in our page.vue template section with vue-instantsearch co

## Using vue-instantsearch with SSR

Server-side rendering requires a few extra steps. First, extract `instantsearch` instance from the mixin and provide it to all `vue-instantsearch` components:
Server-side rendering requires a few extra steps and can be implemented by using two approaches.

### With `render` function

To use the approach with `render` function, first we need to extract `instantsearch` instance from the mixin and provide it to all `vue-instantsearch` components:

```ts
import { createServerRootMixin } from 'vue-instantsearch/vue3/es'
Expand Down Expand Up @@ -123,3 +127,100 @@ const { data: algoliaState } = await useAsyncData('algolia-state', async () => {
You can also check out the following Stackblitz link with the usage of above approach in SSR:

https://stackblitz.com/github/plexus77/nuxt-3-algolia-ssr?file=nuxt.config.ts

### Without `render` function

As explained by Rigo [here](https://github.com/nuxt-modules/algolia/issues/187) there is a way of having SSR Instantsearch without a need for using a render function:

```vue
<template>
<div>
<AisInstantSearchSsr>
<AisConfigure :hits-per-page.camel="4" v-if="$route.params.indexName === 'instant_search'"
:facet-filters.camel="`brand:${$route.params.brand}`" />
<AisRefinementList :attribute="$route.params.indexName === 'airbnb' ? 'room_type' : 'categories'
">
</AisRefinementList>
<AisInfiniteHits show-previous>
<template #loadPrevious="{ isFirstPage, refinePrevious }">
<button :disabled="isFirstPage" @click="refinePrevious">
Load less
</button>
</template>
<template v-slot="{ items, refineNext, isLastPage }">
<div class="cont">
<div v-for="item in items" :key="item.objectID" class="item">
{{ item.name }}
<img :src="item.image ?? item.thumbnail_url" />
{{ item }}
</div>
</div>
<button :disabled="isLastPage" @click="refineNext">Load more</button>
</template>
</AisInfiniteHits>
</AisInstantSearchSsr>
</div>
</template>
<script>
import { renderToString } from "vue/server-renderer";
import {
AisInstantSearchSsr,
AisRefinementList,
AisInfiniteHits,
AisIndex,
AisConfigure,
// @ts-ignore
} from "vue-instantsearch/vue3/es/index.js";
export default defineNuxtComponent({
components: {
AisInstantSearchSsr,
AisRefinementList,
AisInfiniteHits,
AisIndex,
AisConfigure,
},
inject: ["$_ais_ssrInstantSearchInstance"],
async serverPrefetch() {
const s = await this["$_ais_ssrInstantSearchInstance"].findResultsState({
component: this,
renderToString,
});
this.$nuxt.ssrContext.payload.data.algoliaState = s;
},
props: {
indexName: {
type: String,
required: false,
default: null,
},
},
mounted() {

This comment has been minimized.

Copy link
@Rigo-m

Rigo-m Jan 15, 2024

Contributor

forgot to remove the mounted method, this was only for testing purposes

console.log(this.$_ais_ssrInstantSearchInstance);
setTimeout(() => { }, 5000);
},
async beforeMount() {
if (this.$nuxt.payload.data.algoliaState) {
this.$_ais_ssrInstantSearchInstance.hydrate(
this.$nuxt.payload.data.algoliaState,
);
} else {
// somehow, it needs to be disposed and refreshed when i change route with client side navigation
this.instantsearch.dispose();
this.$nextTick(() => {
this.$nextTick(() => {
this.instantsearch.helper.setIndex(this.indexName).search();
});
});
}
// avoid double hydration
delete this.$nuxt.payload.data.algoliaState;
},
});
</script>
```

Check out following link for more details

https://github.com/Rigo-m/nuxt-ssr-algolia-example/blob/main/components/InstantSearchProvider.vue

0 comments on commit 9460dc1

Please sign in to comment.