如何告诉 Vue 应用程序使用 Firebase 模拟器?
How to tell a Vue app to use Firebase emulator?
我有一个利用 Firebase Cloud Functions 的 Vue 应用程序,我对其进行了如下配置。
src/plugins/firebase.js
import firebase from '@firebase/app'
import '@firebase/firestore'
import '@firebase/auth'
import '@firebase/functions'
const firebaseConfig = {
apiKey: 'my-api-key',
authDomain: 'my-project.firebaseapp.com',
databaseURL: 'https://my-project.firebaseio.com',
projectId: 'my-project',
storageBucket: 'my-project.appspot.com',
messagingSenderId: '12345678910',
appId: '123456789101112',
measurementId: 'ASDFJKL'
}
firebase.initializeApp(firebaseConfig)
export default firebase
src/main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// Other imports goes here
import firebase from './plugins/firebase'
Vue.config.productionTip = false
new Vue({
router,
store,
// Other includes goes here...
firebase,
render: h => h(App)
}).$mount('#app')
我想使用 Firebase 模拟器进行测试,但我不知道要更改什么才能实现此目的。
好的,所以这将是一个很长的答案,但我希望尽可能完整地回答您的问题。该过程分两个阶段进行:使模拟器(包括热重载)与 Vue 一起工作,然后使 Vue 与 Firebase 的模拟版本一起工作。
第 1 步:使 Firebase 模拟器与 Vue 一起工作
第一步,您需要编辑 package.json
以设置 Vue 执行 watch/build 循环而不是热重载循环,如下所示。唯一不起作用的(AFAIK)是 Vue DevTools 扩展。 (请注意,我使用的 run-s
和 run-p
命令来自 npm-run-all
包,因为我在 Windows 和 cmd.exe
上不喜欢单个与号 &
)。此外,要在脚本中使用 firebase
命令,您需要安装 firebase-tools
包作为开发依赖项。
"scripts": {
"build": "vue-cli-service build",
"build:dev": "vue-cli-service build --mode development",
"build:watch": "vue-cli-service build --mode development --watch --no-clean",
"lint": "vue-cli-service lint",
"serve": "run-s build:dev watch",
"serve:firebase": "firebase serve",
"watch": "run-p build:watch serve:firebase"
}
安装所需的开发依赖项
npm i --save-dev firebase-tools npm-run-all
这么多。让我详细说明每个命令的作用:
watch
:这个命令就是使一切正常运行的shell命令。它依次运行 build
和 serve
命令。稍后详细介绍
serve
:此命令开始实际的 watch/build 循环。它启动 Firebase 模拟器并启动 vue-cli-service
以观察变化。
serve:firebase
:此命令启动 Firebase 模拟器...仅此而已。
build
:此命令执行生产构建...此处未真正使用,但为了完整性而保留。
build:dev
:这个命令有点重要。如果您注意到,在最初的 watch
脚本中,我们首先调用了 build:dev
脚本。这是因为如果您启动 Firebase 模拟器并且您的“public”目录(注意:这是 Firebase 的 public 目录,而不是 Vue 的)被删除,那么 Firebase 实际上会崩溃。因此,为了解决这个问题,我们在 开始 build/watch 循环之前完成构建 。
build:watch
:这就是热重载魔法发生的地方。我们告诉 vue-cli-service
构建应用程序,但也要注意变化而不是清理构建目录。观察变化开始了前面提到的 watch/build 循环。我们告诉它不要清理构建目录,因为 Firebase 不关心它所服务的目录中的文件是否发生变化,但如果目录被删除它就会崩溃。
此方法的唯一缺点是 Vue DevTools 不起作用。
第 2 步:让 Vue 与 Firebase 模拟器一起工作
事实证明,由于 Firebase Documentation,这个问题实际上有一个非常简单的解决方案。您需要做的是从 Firebase 保留的 URL 请求一个特殊文件。在我的示例中,我使用 Axios,但无论如何,您可以随意使用任何库来发出您想要的请求。
import axios from 'axios';
import firebase from '@firebase/app';
import '@firebase/auth';
import '@firebase/firestore';
import '@firebase/functions';
axios.get('/__/firebase/init.json').then(async response => {
firebase.initializeApp(await response.data);
});
export default firebase;
此外,要向 Vue 实例添加一个 属性,最好这样做,以避免垃圾收集或命名冲突的任何问题。然后,在任何 Vue 组件中,您可以只使用 this.$firebase
.
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import firebase from './plugins/firebase';
Vue.config.productionTip = false;
Vue.prototype.$firebase = firebase;
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');
理想情况下,会有一些方法可以区分应用程序是否在模拟器中 运行,但实际上它能解决的唯一问题是使用 Vue DevTools 扩展的能力,我不要真正将(双关语)视为一项要求。但是,在完成所有这些之后,您应该在模拟器中启动 运行,并进行实时重新加载;而且,最重要的是,一旦准备就绪,您无需对应用程序进行任何更改即可部署它。
奖励:部署
因此,这是另一个脚本部分,它与上面的所有内容相同,但还包括一个单命令部署,以确保您将生产构建从 Vue 部署到 Firebase。
"scripts": {
"build": "vue-cli-service build",
"build:dev": "vue-cli-service build --mode development",
"build:watch": "vue-cli-service build --mode development --watch --no-clean",
"deploy": "run-s build deploy:firebase",
"deploy:firebase": "firebase deploy",
"lint": "vue-cli-service lint",
"serve": "run-s build:dev watch",
"serve:firebase": "firebase serve",
"watch": "run-p build:watch serve:firebase"
}
2021 年 1 月 14 日更新以反映对 Firebase SDK 的更改。
关于连接到 Firestore 模拟器的官方文档在这里:https://firebase.google.com/docs/emulator-suite/connect_firestore
关于连接到 Functions 模拟器的官方文档在这里:https://firebase.google.com/docs/emulator-suite/connect_functions
在实践中,设置将如下所示:
import * as Firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import 'firebase/functions';
import 'firebase/storage';
const firebaseConfig = { <Per Firebase Console> };
!Firebase.apps.length ? Firebase.initializeApp(firebaseConfig) : '';
if(window.location.hostname === 'localhost') {
Firestore.firestore().useEmulator('localhost', 8080);
Firestore.functions().useEmulator('localhost', 5001);
/* OLD implementation */
// Firebase.firestore().settings({ host: 'localhost:8080', ssl: false });
// Firebase.functions().useFunctionsEmulator('http://localhost:5001');
}
export const GoogleAuthProvider = new Firebase.auth.GoogleAuthProvider();
export const FirebaseAuth = Firebase.auth();
export const Firestore = Firebase.firestore();
export const FirebaseFunctions = Firebase.functions();
export const FirebaseStorage = Firebase.storage();
export default Firebase;
这可以导入到 Vuex 商店,或像这样的任何其他页面:
import { Firestore, FirebaseFunctions } from '@/services/firebase.js';
然后在命令提示符/终端中 运行:
firebase emulators:start
这也适用于 Nuxt。
于 2021 年 11 月更新了 Firebase Web 版本 9:
使用与 starleaf1 相同的配置设置,将 firebase.js 更改为以下内容:
import { initializeApp } from "firebase/app";
import { getAuth, connectAuthEmulator } from "firebase/auth";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
initializeApp({
apiKey: "xxx",
authDomain: "xxx",
projectId: "xxx",
storageBucket: "xxx",
messagingSenderId: "xxx",
appId: "xxx"
});
const db = getFirestore();
const auth = getAuth();
// If on localhost, use all firebase services locally
if (location.hostname === 'localhost') {
connectFirestoreEmulator(db, 'localhost', 8080);
connectAuthEmulator(auth, "http://localhost:9099");
// add more services as described in the docs: https://firebase.google.com/docs/emulator-suite/connect_firestore
}
export { db, auth };
就是这样 :-) 我花了 10 多个小时才弄明白。
我有一个利用 Firebase Cloud Functions 的 Vue 应用程序,我对其进行了如下配置。
src/plugins/firebase.js
import firebase from '@firebase/app'
import '@firebase/firestore'
import '@firebase/auth'
import '@firebase/functions'
const firebaseConfig = {
apiKey: 'my-api-key',
authDomain: 'my-project.firebaseapp.com',
databaseURL: 'https://my-project.firebaseio.com',
projectId: 'my-project',
storageBucket: 'my-project.appspot.com',
messagingSenderId: '12345678910',
appId: '123456789101112',
measurementId: 'ASDFJKL'
}
firebase.initializeApp(firebaseConfig)
export default firebase
src/main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// Other imports goes here
import firebase from './plugins/firebase'
Vue.config.productionTip = false
new Vue({
router,
store,
// Other includes goes here...
firebase,
render: h => h(App)
}).$mount('#app')
我想使用 Firebase 模拟器进行测试,但我不知道要更改什么才能实现此目的。
好的,所以这将是一个很长的答案,但我希望尽可能完整地回答您的问题。该过程分两个阶段进行:使模拟器(包括热重载)与 Vue 一起工作,然后使 Vue 与 Firebase 的模拟版本一起工作。
第 1 步:使 Firebase 模拟器与 Vue 一起工作
第一步,您需要编辑 package.json
以设置 Vue 执行 watch/build 循环而不是热重载循环,如下所示。唯一不起作用的(AFAIK)是 Vue DevTools 扩展。 (请注意,我使用的 run-s
和 run-p
命令来自 npm-run-all
包,因为我在 Windows 和 cmd.exe
上不喜欢单个与号 &
)。此外,要在脚本中使用 firebase
命令,您需要安装 firebase-tools
包作为开发依赖项。
"scripts": {
"build": "vue-cli-service build",
"build:dev": "vue-cli-service build --mode development",
"build:watch": "vue-cli-service build --mode development --watch --no-clean",
"lint": "vue-cli-service lint",
"serve": "run-s build:dev watch",
"serve:firebase": "firebase serve",
"watch": "run-p build:watch serve:firebase"
}
安装所需的开发依赖项
npm i --save-dev firebase-tools npm-run-all
这么多。让我详细说明每个命令的作用:
watch
:这个命令就是使一切正常运行的shell命令。它依次运行build
和serve
命令。稍后详细介绍serve
:此命令开始实际的 watch/build 循环。它启动 Firebase 模拟器并启动vue-cli-service
以观察变化。serve:firebase
:此命令启动 Firebase 模拟器...仅此而已。
build
:此命令执行生产构建...此处未真正使用,但为了完整性而保留。
build:dev
:这个命令有点重要。如果您注意到,在最初的watch
脚本中,我们首先调用了build:dev
脚本。这是因为如果您启动 Firebase 模拟器并且您的“public”目录(注意:这是 Firebase 的 public 目录,而不是 Vue 的)被删除,那么 Firebase 实际上会崩溃。因此,为了解决这个问题,我们在 开始 build/watch 循环之前完成构建 。build:watch
:这就是热重载魔法发生的地方。我们告诉vue-cli-service
构建应用程序,但也要注意变化而不是清理构建目录。观察变化开始了前面提到的 watch/build 循环。我们告诉它不要清理构建目录,因为 Firebase 不关心它所服务的目录中的文件是否发生变化,但如果目录被删除它就会崩溃。
此方法的唯一缺点是 Vue DevTools 不起作用。
第 2 步:让 Vue 与 Firebase 模拟器一起工作
事实证明,由于 Firebase Documentation,这个问题实际上有一个非常简单的解决方案。您需要做的是从 Firebase 保留的 URL 请求一个特殊文件。在我的示例中,我使用 Axios,但无论如何,您可以随意使用任何库来发出您想要的请求。
import axios from 'axios';
import firebase from '@firebase/app';
import '@firebase/auth';
import '@firebase/firestore';
import '@firebase/functions';
axios.get('/__/firebase/init.json').then(async response => {
firebase.initializeApp(await response.data);
});
export default firebase;
此外,要向 Vue 实例添加一个 属性,最好这样做,以避免垃圾收集或命名冲突的任何问题。然后,在任何 Vue 组件中,您可以只使用 this.$firebase
.
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import firebase from './plugins/firebase';
Vue.config.productionTip = false;
Vue.prototype.$firebase = firebase;
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');
理想情况下,会有一些方法可以区分应用程序是否在模拟器中 运行,但实际上它能解决的唯一问题是使用 Vue DevTools 扩展的能力,我不要真正将(双关语)视为一项要求。但是,在完成所有这些之后,您应该在模拟器中启动 运行,并进行实时重新加载;而且,最重要的是,一旦准备就绪,您无需对应用程序进行任何更改即可部署它。
奖励:部署
因此,这是另一个脚本部分,它与上面的所有内容相同,但还包括一个单命令部署,以确保您将生产构建从 Vue 部署到 Firebase。
"scripts": {
"build": "vue-cli-service build",
"build:dev": "vue-cli-service build --mode development",
"build:watch": "vue-cli-service build --mode development --watch --no-clean",
"deploy": "run-s build deploy:firebase",
"deploy:firebase": "firebase deploy",
"lint": "vue-cli-service lint",
"serve": "run-s build:dev watch",
"serve:firebase": "firebase serve",
"watch": "run-p build:watch serve:firebase"
}
2021 年 1 月 14 日更新以反映对 Firebase SDK 的更改。
关于连接到 Firestore 模拟器的官方文档在这里:https://firebase.google.com/docs/emulator-suite/connect_firestore
关于连接到 Functions 模拟器的官方文档在这里:https://firebase.google.com/docs/emulator-suite/connect_functions
在实践中,设置将如下所示:
import * as Firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import 'firebase/functions';
import 'firebase/storage';
const firebaseConfig = { <Per Firebase Console> };
!Firebase.apps.length ? Firebase.initializeApp(firebaseConfig) : '';
if(window.location.hostname === 'localhost') {
Firestore.firestore().useEmulator('localhost', 8080);
Firestore.functions().useEmulator('localhost', 5001);
/* OLD implementation */
// Firebase.firestore().settings({ host: 'localhost:8080', ssl: false });
// Firebase.functions().useFunctionsEmulator('http://localhost:5001');
}
export const GoogleAuthProvider = new Firebase.auth.GoogleAuthProvider();
export const FirebaseAuth = Firebase.auth();
export const Firestore = Firebase.firestore();
export const FirebaseFunctions = Firebase.functions();
export const FirebaseStorage = Firebase.storage();
export default Firebase;
这可以导入到 Vuex 商店,或像这样的任何其他页面:
import { Firestore, FirebaseFunctions } from '@/services/firebase.js';
然后在命令提示符/终端中 运行:
firebase emulators:start
这也适用于 Nuxt。
于 2021 年 11 月更新了 Firebase Web 版本 9: 使用与 starleaf1 相同的配置设置,将 firebase.js 更改为以下内容:
import { initializeApp } from "firebase/app";
import { getAuth, connectAuthEmulator } from "firebase/auth";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
initializeApp({
apiKey: "xxx",
authDomain: "xxx",
projectId: "xxx",
storageBucket: "xxx",
messagingSenderId: "xxx",
appId: "xxx"
});
const db = getFirestore();
const auth = getAuth();
// If on localhost, use all firebase services locally
if (location.hostname === 'localhost') {
connectFirestoreEmulator(db, 'localhost', 8080);
connectAuthEmulator(auth, "http://localhost:9099");
// add more services as described in the docs: https://firebase.google.com/docs/emulator-suite/connect_firestore
}
export { db, auth };
就是这样 :-) 我花了 10 多个小时才弄明白。