[Nuxt3] Firebase 데스크에서 실행합니까 서버에서 실행합니까
프론트 데스크에서부터 집행을 시작하다
왜냐하면db를 정의하기 전에 FirebaseApp 기반의 비동기 처리를 초기화하지 않았기 때문에db는undefined
<script setup lang="ts">
// これはうまくいく
const users = ref<User[]>([])
async getUsersTest(){
	users.value = await useFirestore().getUsers()
}
// ページ読み込みの時にユーザー一覧を表示させようとして以下のように書くとエラーが出る
const users = await useFirestore().getUsers()
console.log(users)
 
</script>
<template>
<button @click="getUsersTest()">ユーザー取得</button>
</template>
  expected first argument to collectin() to be a CollectionReference・・・
  프런트에서 하는 방법.
클릭하여 보기
plugins/firebase.client.ts
import { defineNuxtPlugin, useState } from '#app'
import { FirebaseApp, initializeApp } from 'firebase/app'
import { Firestore, getFirestore } from 'firebase/firestore'
import { Auth, initializeAuth } from 'firebase/auth'
// Initialize Firebase
const firebaseConfig = {
    apiKey: "",
    authDomain: "",
    databaseURL: "",
    projectId: "",
    storageBucket: "",
    messagingSenderId: "",
    appId: "",
    measurementId: ""
};
const firebaseApp:FirebaseApp = initializeApp(firebaseConfig)
export const db:Firestore = getFirestore(firebaseApp)
export const auth:Auth = initializeAuth(firebaseApp)
export default defineNuxtPlugin((nuxtApp) => {
    useState('firebaseApp', () => firebaseApp)
    useState('auth', () => auth)
    useState('db', () => db)
})
composables
1. useFirestore.ts
compoosable의 함수는 모두Promise를 되돌려줍니다. 예를 들어 쓰기에 성공한 경우'success'의res를 되돌려주고 실패한 경우'failure'의res를 되돌려줍니다.
import {
    Firestore,
    collection,
    query,
    where,
    getDocs,
    doc,
    getDoc
} from 'firebase/firestore';
type User = {
    id:String,
    name:String
}
type Users = Array<User>
export const useFirestore = () => {
    const db:Firestore = useState('db').value;
		// 全ユーザーを取得
    async function getUsers(){
        return new Promise(async(resolve, reject)=>{
            const q = query(
                collection(db, 'users'),
            );
            const querySnapshot = await getDocs(q);
            const users:Users = querySnapshot.docs.map((doc) => {
                const data = doc.data()
                const user:User = {
                    id:doc.id,
                    name:data.name
                }
                return user
            });
            resolve(users)
        })
    };
    async function getUserById(id:string){
        return new Promise(async(resolve, reject)=>{
            const docRef = doc(db, 'users', id);
            const docSnap = await getDoc(docRef);
            if (docSnap.exists()) {
                const data = docSnap.data()
                const user:User={
                    id:docSnap.id,
                    name:data.name
                }
                resolve(user)
              } else {
                reject(null)
              }
        })
    }
    async function getHashiraUsers(){
        return new Promise(async(resolve, reject)=>{
            const q = query(
                collection(db, 'users'),
                where('hashira','==',true)
            );
            const querySnapshot = await getDocs(q);
            const users:Users = querySnapshot.docs.map((doc) => {
                const data = doc.data()
                const user:User = {
                    id:doc.id,
                    name:data.name
                }
                return user
            });
            resolve(users)
        })
    }
    return {
        getUsers,getUserById,getHashiraUsers
    };
};
2. useAuth.ts
import {
    Auth,
    createUserWithEmailAndPassword,
    signInWithEmailAndPassword,
    onAuthStateChanged,
    signOut
} from 'firebase/auth'
export const useAuth = () => {
    const currentUser = ref<T>(null)    
    const auth:Auth = useState('auth').value
    async function signUp(email:string, password:string){
        return new Promise((resolve)=>{
            createUserWithEmailAndPassword(auth, email, password)
            .then((userCredential) => {
                // サインアップできたらログインする
                const currentUser = userCredential.user;
                resolve("success")
            })
            .catch((error) => {
                const errorCode = error.code;
                const errorMessage = error.message;
                resolve(errorCode)
            });            
        })
    }
    async function passwordSignIn(email:string,password:string){
        return new Promise((resolve)=>{
            signInWithEmailAndPassword(auth, email, password)
                .then((userCredential) => {
                    // ログインできた時
                    currentUser.value = userCredential.user
                    resolve('success')
                })
                .catch((error) => {
                    // ログインできていない時
                    resolve(error)
                })
        })
    };
    function getUserData(){
        console.log(`getUserDataが呼び出された`)
        onMounted(() => {
            onAuthStateChanged(auth, (currentUser) => {
                if (currentUser) {
                    console.log(`currentUserあり`)
                    currentUser.value = currentUser
                }else{
                    console.log(`currentUserなし`)
                    user.value = null
                }
            })
        })
    }
    async function signout() { 
        return new Promise((resolve)=>{
            signOut(auth)
                .then(()=>{
                    currentUser.value = null
                    resolve("success")
                })
                .catch((error)=>{
                    resolve(error)
                })
        })
    }
    return {
      signUp, passwordSignIn, signout, currentUser, getUserData
    };
};
app
app.vue
<script setup lang="ts">
const {signUp, passwordSignIn, signout, currentUser, getUserData} = useAuth();
const router = useRouter()
const email = ref<String>('[email protected]')
const password = ref<String>('password')
const message = ref<String>('ログインしていません')
const items = [
    {
        title:'ダッシュボード',
        to:'/',
        icon:''
    },{
        title:'authのテスト',
        to:'/authtest',
        icon:''        
    },{
        title:'storeのテスト',
        to:'/dbtest',
        icon:''
    }
]
async function createAccount(){
    const res:String = await signUp(email.value,password.value)
    if(res=="success"){
        // ダッシュボードに遷移するなど
    }else if(res=="email-already-in-use"){
        message.value = '既にアカウントを作成されているメールアドレスです'
    }
}
async function login(){
    const res:string = await passwordSignIn(email.value,password.value)
    console.log(`ログイン結果, ${res}`)
    if(res==="success"){
        // ダッシュボードに遷移するなど
        console.log(`ログインしました`)
    }else if(/^.+wrong-password.+$/.test(res)){
        message.value = `パスワードが間違っています`
    }else if(/^.+user-not-found.+$/.test(res)){
        message.value = `メールアドレスが間違っています`
    }else{
        message.value = `エラーが発生しました`
    }
}
async function logout(){
    const res:string = await signout()
    console.log(`ログアウト結果, ${res}`)
    if(res=="success"){
        router.push('/')
        message.value = 'ログアウトしました'
    }else{
        message.value = 'ログアウトに失敗しました。もう一度やり直してください'
    }
}
</script>
<template>
    <div style="outline:1px solid;height:50px;display:flex;justify-content: space-between;">
        <h1 style="margin:0 10px;">Nuxt3</h1>
        <div v-if="currentUser">{{currentUser.uid}}</div>
        <button v-if="currentUser" @click="logout">ログアウト</button>
    </div>
    <div v-if="currentUser" style="display:flex">
        <div style="outline:1px solid;width:150px;height:90vh">
            <ul style="list-style-type: none;padding:10px">
                <li v-for="item of items" :key="item.title">
                    <NuxtLink :to="item.to">{{item.title}}</NuxtLink>
                </li>                
            </ul>
        </div>
        <div style="padding:10px">
            <NuxtPage/>            
        </div>
    </div>
    <div v-else style="margin:0 auto;width:30vw">
        {{message}}
        <div>
            <input type="text" id="email" v-model="email" placeholder="メールアドレス">            
        </div>
        <div>
            <input type="text" id="password" v-model="password" placeholder="パスワード">            
        </div>
        <button @click="createAccount">サインアップ</button>
        <button @click="login">ログイン</button>
    </div>
</template>
pages
authtest.vue
<script setup lang="ts">
const {signUp, passwordSignIn, signout, user} = useAuth();
const email = ref<String>('[email protected]')
const password = ref<String>('password')
const message = ref<String>('')
async function createAccount(){
    const res:String = await signUp(email.value,password.value)
    if(res=="success"){
        // ダッシュボードに遷移するなど
    }else if(res=="email-already-in-use"){
        message.value = '既にアカウントを作成されているメールアドレスです'
    }
}
async function login(){
    const res:string = await passwordSignIn(email.value,password.value)
    console.log(`ログイン結果, ${res}`)
    if(res==="success"){
        // ダッシュボードに遷移するなど
        console.log(`ログインしました`)
    }else if(/^.+wrong-password.+$/.test(res)){
        message.value = `パスワードが間違っています`
    }else if(/^.+user-not-found.+$/.test(res)){
        message.value = `メールアドレスが間違っています`
    }else{
        message.value = `エラーが発生しました`
    }
}
async function logout(){
    const res:string = await signout()
    console.log(`ログアウト結果, `)
    if(res=="success"){
        // ログインページに遷移するなど
    }else{
        message.value = 'ログアウトに失敗しました。もう一度やり直してください'
    }
}
</script>
<template>
    <input
        type="text"
        id="email"
        v-model="email"
        placeholder="メールアドレス"
    >
    <input
        type="text"
        id="password"
        v-model="password"
        placeholder="パスワード"
    >
    <button @click="createAccount">サインアップ</button>
    <button @click="login">ログイン</button>
    <button @click="logout">ログアウト</button>
    <div>メッセージ</div>
    <div>{{message}}</div>
    <div>ログインユーザー情報</div>
    <div>{{user}}</div>
</template>
dbtest.vue
<script setup lang="ts">
type User = {
    id:String,
    name:String
}
type Users = Array<User>
const users = ref<Users>()
const user = ref<User>()
const { getUsers, getUserById, getHashiraUsers } = useFirestore();
async function test1(){
    users.value = await getUsers()
}
async function test2() {
    user.value = await getUserById('tanjiro')
}
async function test3(){
    users.value = await getHashiraUsers()
}
async function test4(){
    users.value = []
    user.value=null
}
</script>
<template>
    <div>
        <button @click="test1">全ユーザーを取得</button>
        <button @click="test2">炭治郎を取得</button>
        <button @click="test3">柱を取得</button>
        <button @click="test4">クリア</button>
        <div style="height:200px;outline:solid 1px">
            ここにusersを表示
            <ul>
                <li v-for="user of users" :key="user.id">{{user.name}}</li>
            </ul>
        </div>
        <div style="height:300px;outline:solid 1px">
            ここにuserを表示
            <div>{{user}}</div>
        </div>
    </div>
</template>
참고 자료
nuxt3+firebasev9를 시도해 보세요.
How to integrate Firebase v9 with Nuxt3? · Discussion #2404 · nuxt/framework
서버에서 실행
Reference
이 문제에 관하여([Nuxt3] Firebase 데스크에서 실행합니까 서버에서 실행합니까), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/yuta_enginner/articles/f2eb0d4f36dfc7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)