Skip to content

Commit b92f8bc

Browse files
committed
fix: compatibility with Vue 2
Fix #1280
1 parent 6458b3b commit b92f8bc

File tree

3 files changed

+52
-18
lines changed

3 files changed

+52
-18
lines changed

docs/guide/getting-started.md

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,14 @@ import App from './App.vue'
7979
import { firebaseApp } from './firebase'
8080

8181
const app = createApp(App)
82-
app
83-
.use(VueFire, {
84-
// imported above but could also just be created here
85-
firebaseApp,
86-
modules: [
87-
// we will see other modules later on
88-
VueFireAuth(),
89-
],
90-
})
82+
app.use(VueFire, {
83+
// imported above but could also just be created here
84+
firebaseApp,
85+
modules: [
86+
// we will see other modules later on
87+
VueFireAuth(),
88+
],
89+
})
9190

9291
app.mount('#app')
9392
```
@@ -102,12 +101,26 @@ const db = useFirestore()
102101
</script>
103102
104103
<template>
105-
<div>
106-
...
107-
</div>
104+
<div>...</div>
108105
</template>
109106
```
110107

108+
#### Vue 2
109+
110+
VueFire only supports Vue 2.7 and it also requires you to use `createApp()` from `vue-demi` to keep the API the same in both versions, Vue 2 and Vue 3. Here is the same example as above but simplified for Vue 2:
111+
112+
```ts{1}
113+
import { createApp } from 'vue-demi'
114+
import { VueFire } from 'vuefire'
115+
import App from './App.vue'
116+
// the file we created above with `database`, `firestore` and other exports
117+
import { firebaseApp } from './firebase'
118+
119+
const app = createApp(App)
120+
app.use(VueFire, { firebaseApp })
121+
app.mount('#app')
122+
```
123+
111124
### Composition API
112125

113126
VueFire exposes a few [composables](https://vuejs.org/guide/reusability/composables.html#composables) to create reactive variables from Firebase references.
@@ -129,7 +142,7 @@ const todos = useDatabaseList(dbRef(db, 'todos'))
129142
<template>
130143
<ul>
131144
<li v-for="todo in todos" :key="todo.id">
132-
<span>{{ todo.text }}</span>
145+
<span>{{ todo.text }}</span>
133146
</li>
134147
</ul>
135148
</template>
@@ -146,7 +159,7 @@ const todos = useCollection(collection(db, 'todos'))
146159
<template>
147160
<ul>
148161
<li v-for="todo in todos" :key="todo.id">
149-
<span>{{ todo.text }}</span>
162+
<span>{{ todo.text }}</span>
150163
</li>
151164
</ul>
152165
</template>

src/index.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,14 @@ export interface VueFireOptions {
125125
* Array of VueFire modules that should be added to the application. e.g. `[VueFireAuth, VueFireDatabase]`. Remember
126126
* to import them from `vuefire`.
127127
*/
128-
modules?: Array<(firebaseApp: FirebaseApp, app: App) => void>
128+
modules?: VueFireModule[]
129+
}
130+
131+
/**
132+
* A VueFire module that can be passed to the VueFire Vue plugin in the `modules` option.
133+
*/
134+
export interface VueFireModule {
135+
(firebaseApp: FirebaseApp, app: App): void
129136
}
130137

131138
/**
@@ -138,6 +145,9 @@ export function VueFire(
138145
app.provide(_FirebaseAppInjectionKey, firebaseApp)
139146

140147
for (const firebaseModule of modules) {
141-
app.use(firebaseModule.bind(null, firebaseApp))
148+
firebaseModule(firebaseApp, app)
149+
// NOTE: we cannot use the following because it doesn't work on Vue 2
150+
// the version above works since we are just using app.provide and vue-demi adds it
151+
// app.use(firebaseModule.bind(null, firebaseApp))
142152
}
143153
}

src/shared.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type {
66
Query as FirestoreQuery,
77
} from 'firebase/firestore'
88
import { StorageReference } from 'firebase/storage'
9-
import { getCurrentInstance, inject, ssrContextKey } from 'vue-demi'
9+
import { getCurrentInstance, inject, isVue2 } from 'vue-demi'
1010
import type { Ref, ShallowRef } from 'vue-demi'
1111

1212
export const noop = () => {}
@@ -267,13 +267,24 @@ export interface _ResolveRejectFn {
267267
(value: unknown): void
268268
}
269269

270+
// NOTE: copied from vue core, avoids importing it since it only exists in Vue 3
271+
const ssrContextKey = Symbol.for('v-scx')
272+
270273
/**
271274
* Check if we are in an SSR environment within a composable. Used to force `options.once` to `true`.
272275
*
273276
* @internal
274277
*/
275278
export function useIsSSR(): boolean {
276-
return !!(getCurrentInstance() && inject(ssrContextKey, null))
279+
const instance = getCurrentInstance()
280+
if (isVue2) {
281+
return (
282+
!!instance &&
283+
// @ts-expect-error: Vue 2 only API
284+
instance.proxy.$isServer
285+
)
286+
}
287+
return !!inject(ssrContextKey, 0)
277288
}
278289

279290
/**

0 commit comments

Comments
 (0)