When i use storage emulator, I have been struggling to connect download URLs to URLs that can be accessed by 3rd parties - image and video optimisation tools. Firebase Storage production url is https://firebasestorage.googleapis.com/...
(accessible over the web) whereas local environment url is http://localhost:9199/...
(inaccessible).
I tried a bunch of things make the URL accessible. I've resorted to creating another bucket on my production environment and then the auth, function, firestore and hosting is on the local emulator.
This works but i wonder, what are the risks to this?
Is there a better way?
Edit: Adding my json file as per comment.
{
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"functions": [
{
"source": "functions",
"codebase": "default",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log"
],
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint"
]
}
],
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"storage": {
"rules": "storage.rules"
},
"emulators": {
"auth": {
"port": 9099
},
"firestore": {
"port": 8080
},
"hosting": {
"port": 5000
},
"storage": {
"port": 9199
},
"ui": {
"enabled": true,
"port": 4000
},
"singleProjectMode": true,
"functions": {
"port": 5001
}
}
}
I think you are accessing firebase emulator from the node environment and not in the browser environment as hostname will only work if the environment is running in the browser and here location.hostname
will also not work.
If you initialize without checking the condition for ''localhost'' you should get the results. Because if you have used typescript
here you might have got error on hostname like
This comparison appears to be unintentional because the types '() => string' and 'string' have no overlap.
if(hostname === "localhost")
👆
Instead of initializing the firebase emulators from the client like you did, I recommend you to use some env
file and add one variable called NODE_ENV = ''development'' and initialize based on that condition as follows:
if(process.env.NODE_ENV === 'development') {
connectAuthEmulator(auth, "http://localhost:9099");
connectFirestoreEmulator(db, "localhost", 8080);
connectDatabaseEmulator(database, "localhost", 9000);
connectStorageEmulator(storage, "localhost", 9199);
connectFunctionsEmulator(functions, "localhost", 5001);
}
OR just use a variable like const useEmulator: boolean = true;
in your firebase initialization file and check against this value and when you want to connect to production firebase instance just make the value of useEmulator
to false.
Update : Let's double check if you have followed these steps or not, if yes then try to give it a chance again.
npm init -y
and configure typescript project as shown in here.firebase init
and select existing project and provide project_id to the cli then select which features you want to use in this case select Storage: Configure a security rules file for Cloud Storage
and Emulators: Set up local emulators for Firebase products
then hit enter.Would you like to download the emulators now?(Y/n)
as a prompt, type Y then enter. Your emulators will get downloaded.npm install firebase
to add firebase dependency to your project.firebase.ts
file then add your firebase credentials as follows:// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { connectAuthEmulator, getAuth } from "firebase/auth";
import { connectDatabaseEmulator, getDatabase } from "firebase/database";
import { connectFirestoreEmulator, getFirestore } from "firebase/firestore";
import { connectFunctionsEmulator, getFunctions } from "firebase/functions";
import { connectStorageEmulator, getStorage } from "firebase/storage";
const firebaseConfig = { … };
const useEmulator: boolean = true;
// Initialize Firebase Services
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
const database = getDatabase(app);
const storage = getStorage(app);
const functions = getFunctions(app);
if(useEmulator) {
connectAuthEmulator(auth, "http://localhost:9099");
connectFirestoreEmulator(db, "localhost", 8080);
connectDatabaseEmulator(database, "localhost", 9000);
connectStorageEmulator(storage, "localhost", 9199);
connectFunctionsEmulator(functions, "localhost", 5001);
} else console.log("If Block has been Skipped");
export { auth, db, database, storage, functions }
firebase emulators:start
to start the emulator it will spit out ui URL and configured emulator services urls. Go to the ui URL and upload an image to the storage emulator. You will get the url for that image like this : http://127.0.0.1:9199/v0/b/<project_id>.appspot.com/...
Reference : Instrument your app to talk to the emulators