3

I have a nuxt app uploaded to Firebase (served as cloud function). I have also a callable function that I'm trying to call from the app. The problem is that it tries to call localhost url instead of the production one.

My Firebase setup in nuxt.config.js looks like this:

module.exports = {
    env: {
        functionsURL: process.env.NUXT_ENV_FUNCTIONS === 'local' ? "http://localhost:5001/turniejomat/us-central1" : 'https://us-central1-turniejomat.cloudfunctions.net', // I would expect this to be applied
    },
    modules: [
        [
            '@nuxtjs/firebase',
            {
                config: {
                    // app config
                },
                services: {
                    functions: {
                        location: 'us-central1',
                        emulatorPort: 5001,
                    }
                }
            }
        ]
    ],
}

The firebase.nuxt.org documentation mentions only emulator configuration, but not production.

I'm calling the function like this:

const signUp = await this.$fire.functions.httpsCallable("signup")(configObject)

How do I make the function to use proper url in production?

EDIT:

This is package.json setting:

"scripts": {
        "dev": "SET \"NUXT_ENV_FUNCTIONS=local\" & nuxt",
        "build": "SET \"NUXT_ENV_FUNCTIONS=fire\" & nuxt build",
 } 

EDIT 2:

Apparently the env.functionsURL is applied properly, as the app code uses this variable directly for other purposes and it works correctly! It is the callable functions only that for some reason don't receive the relevant production url to be called. At the same time the only places in the code where 5001 port appears are:

  1. nuxt.config.js / env setting
  2. nuxt.config.js / modules / services / functions / emulatorPort setting
  3. service.functions.js module in nuxt/firebase folder which is added automatically (by firebase.nuxtjs I guess?).

The module looks like this:

export default async function (session) {
  await import('firebase/functions')
  const functionsService = session.functions('us-central1')
  functionsService.useFunctionsEmulator('http://localhost:5001')
  return functionsService
}

So maybe for some reason the callable function thinks it should still use emulator settings? How could I prevent it?

The only place where the module is called is the nuxt/firebase/index.js, like this:

 if (process.server) {
    servicePromises = [
      authService(session, firebase, ctx, inject),
    firestoreService(session, firebase, ctx, inject),
    functionsService(session, firebase, ctx, inject),
    ]
  }

  if (process.client) {
    servicePromises = [
      authService(session, firebase, ctx, inject),
      firestoreService(session, firebase, ctx, inject),
      functionsService(session, firebase, ctx, inject),
    ]
  }

Which seems that indeed regardless of the environment the same settings are indeed applied by the Firebase's native code. I could modify the functionsService code, but it does not seem like an optimal solution as Firebase might overwrite it at some point, like during build or update. Or it could have been that these 'native' files were generated only at the beginning and did not update despite potential changes made in the config (which was incorrect, but now is correct).

How could I enforce changes to these Firebase's files distinguishing prod and dev environments and make them safely persist? Probably nuxt.config.js / modules / services / functions / should be configured differently, but how?

Eggon
  • 2,032
  • 2
  • 19
  • 38
  • Can't you do the actual setup into a Nuxt plugin and interpolate the URL there somehow? – kissu Oct 12 '21 at 16:48
  • This is my first app in Nuxt and first using Firebase. I don't know how would I transform nuxt settings into a plugin and how would that help me with the problem. I don't see a plugin-config mentioned in the docs. I expected that either I have some error in the setup or some value is missing. I am using Firebase's SDK to call the function, so I expect it must get the url from somewhere and I would expect that to be `env.functionsURL` setting. But it does not work. So either it's not the right place or Firebase thinks that prod is 'local'. However, the build script sets this variable to "fire". – Eggon Oct 13 '21 at 13:59
  • Why make a conditional here? Add your variable directly here. Then, locally in your `.env` you can set localhost, while on production you could set the real URL. – kissu Oct 13 '21 at 14:04
  • Ok, I did some further tests and hard set the the `env.functionsURL` in `nuxt.config.js` to production value only. Still the localhost was applied for the SDK callable function (I don't know from where as it aws the ONLY place in my project where I had the localhost specified). HOWEVER, in the app code itself I do use the `env.functionsURL` and it is set properly, because some other code uses it ant it works! Is it possible that for the callable funct it is necessary to use some CLI command like firebase functions:config:set myCallableFunction.runtime_api_url="https://function/url"? – Eggon Oct 13 '21 at 17:53

3 Answers3

1

So the solution turned out to be to set up functions.emulatorPort setting in nuxt.config.js conditionally - only for the dev environment and undefined for production:

functions: {
    location: 'us-central1',
    emulatorPort: process.env.NUXT_ENV_FUNCTIONS === 'local' ? 5001 : undefined,                    
}
Eggon
  • 2,032
  • 2
  • 19
  • 38
0

Use the publicRuntimeConfig in nuxt.config.js, in order to configure the environment:

export default {
  publicRuntimeConfig: {
    baseURL: process.env.BASE_URL || 'https://us-central1-turniejomat.cloudfunctions.net'
  }
}

Subsequently the dev script would be:

"dev": "SET \"BASE_URL=http://localhost:5001/turniejomat/us-central1\" & nuxt"

Always substitute production with development values, not the other way around.

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • Not sure how you can use `baseURL` since it's configuration is directly done in `nuxt.config.js`' `module` key and not a plugin. – kissu Oct 13 '21 at 14:41
  • What do you mean? It doesn't matter how you call the variable and `$config` is know application-wide. – Martin Zeitler Oct 13 '21 at 16:55
  • `publicRuntimeConfig` variables cannot be directly used in `nuxt.config.js` keys. Those are aimed towards places with Nuxt context. – kissu Oct 13 '21 at 16:56
  • This is directly copied from the documentation, just click the link above. You could as well use `.env` – Martin Zeitler Oct 13 '21 at 17:02
  • It doesn't say anything regarding my previous comment. But yeah, using `process.env` is a viable solution. – kissu Oct 13 '21 at 17:18
  • @MartinZeitler Unfortunatelly it didn't work. Trying configurations I even hard set the `env.functionsURL` in `nuxt.config.js` to production value only. Still the `localhost` was applied for the SDK callable function. HOWEVER, in the app code itself I do use the `env.functionsURL` and it is set properly! Is it possible that for the callable funct it is necessary to use some CLI command like `firebase functions:config:set myCallableFunction.runtime_api_url="https://function/url"`? I have set such config for the app function, but I dont want to break something running this for callable funct. – Eggon Oct 13 '21 at 17:50
  • @kissu I have updated the question with relevant info. Maybe it will help formulate an answer? – Eggon Oct 21 '21 at 14:13
  • @MartinZeitler I have updated the question with relevant info. Maybe it will help formulate an answer? – Eggon Oct 21 '21 at 14:13
0

You might want to review the documentation again. I checked the previous steps and it seems like you are not initializing firebase and that you can also specify whether you want to work in the development or the production mode. You can find this in the Guide, the configuration is at the beginning. (guide/options/config) details for your nuxt.config.js file.

config

REQUIRED

Your firebase config snippet and other Firebase specific parameters. You can retrieve this information from your Firebase project's overview page:

https://console.firebase.google.com/project/<your-project-id>/overview

nuxt.config.js:

config: {
  // REQUIRED: Official config for firebase.initializeApp(config):
  apiKey: '<apiKey>',
  authDomain: '<authDomain>',
  projectId: '<projectId>',
  storageBucket: '<storageBucket>',
  messagingSenderId: '<messagingSenderId>',
  appId: '<appId>',
  measurementId: '<measurementId>'
}

Can be defined per NODE_ENV environment if put in child-objects config.production and config.development, meaning that e.g. config.production gets loaded when NODE_ENV === 'production'.

You can also specify multiple custom environments as mentioned in the customEnv option below.

And the guide/options/services part instructs you on how to initialize firebase.

services

REQUIRED

By default, NO Firebase products are initialized. To initialize a specific service, set its services flag to true or create a child object and name the key after the service.

Available services:

nuxt.config.js:

services: {
  auth: true,
  firestore: true,
  functions: true,
  storage: true,
  database: true,
  messaging: true,
  performance: true,
  analytics: true,
  remoteConfig: true
} 

Each service has advanced options that you can configure. See the service options section for more details.

EDIT If this is not working, I would like to know if you configured your firebase project in development mode, in that case the issue might be there. To change it to development mode or to troubleshoot that part you might need to create a new project from scratch and import/export your old project like they suggested in this question.

Alex
  • 778
  • 1
  • 15
  • I have the `config` and `services` defined in the module section of `nuxt.config.js` which is shown in my snippet. I have seen the documentation, but it lacks information that I need. The [firebase.nuxtjs docs](https://firebase.nuxtjs.org/service-options/functions) show only the settings that I do have already (setting up emulator host and port), which work incorrectly (they seem to apply emulator settings also in production). I have updated my question with additional information which maybe will help formulate a solution? – Eggon Oct 21 '21 at 14:28
  • Does the edit helped? – Alex Oct 28 '21 at 15:20
  • 1
    Not really. I found a solution myself - I wrote an anwer already. The `emulatorPort` needed to be defined conditionally. But as you were in the right ballpark and the bounty will expire I will grant you the bounty so it doesnt go to waste :), but I will not accept the answer. Please consider upvoting my question. :) – Eggon Oct 29 '21 at 14:21