MrBigboka
MrBigboka

Reputation: 449

Failed to resolve module specifier "firebase/app"

it's my firstime using Firebase and I think that I've followed all step to connect my project to firebase. I tried to run my project with a small js console.log(firebase) When I went to my console I received this error message Failed to resolve module specifier "firebase/app"

I want to mention that I've create a node_module folder and I did npm i firebase.

html file:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>TP1</title>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
        <script type="module" src="/index.js"> </script>
    </head>
    <body>

index.js:

import { initializeApp } from "firebase/app";
//import { getDatabase } from "firebase/database";

const firebaseConfig = {
  //(my config...)
};


const app = initializeApp(firebaseConfig);
//const database = getDatabase(firebaseConfig);

console.log(firebase)

Upvotes: 10

Views: 18732

Answers (5)

Kelvin Cayman
Kelvin Cayman

Reputation: 187

What you have defined in the imports of your index.js are npm paths. The browser wouldn't understand what these means unless they are bundled by webpack/rollup.

Therefore what you need to do is to convert the import paths to browser module paths as explained in this article.

So your index.js will look like this:

import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js";
import { getFirestore } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js";

const firebaseConfig = {
  //(my config...)
};


const app = initializeApp(firebaseConfig);
// To initialize database you need to pass app as a parameter of getFirestore
const database = getFirestore(app);

console.log(database)

To use the npm paths you need to use webpack/rollup as explained by other answers here.

I hope this helps.

Upvotes: 1

Intraterrestrial
Intraterrestrial

Reputation: 46

You have to use a bundler as said in other answers, so what you have to do is follow these module bundling steps.

After you get to the step where you run npm run build it will probably throw error. If the error says something like no index.html found then what you have to do is in "public" folder or whatever name you gave it when installing and seting up firebase, and move all to folder dist created in your root folder, and what i did is move src from "public" folder to root folder where you have all those config files like "webpack.config.js" and also in that file you have to change to something like this:

const path = require('path');

module.exports = {
  // The entry point file described above
  entry: './src/index.js',
  // The location of the build folder described above
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  watch: true, 
  // Optional and for development only. This provides the ability to
  // map the built code back to the original source format when debugging.
  devtool: 'eval-source-map',
};

and then in firebase.json you have to set it up to something like this:

{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

after that you can run npm run build

if for some reason you couldnt get it to work you can watch this tutorial and follow it:

https://www.youtube.com/watch?v=vK2NoOoqyRo

Upvotes: 1

ccalvert
ccalvert

Reputation: 4466

The Firebase team designed their code to work with a bundler. In particular, note these sentences from the docs:

Module bundlers read import paths in your code and combine (bundle) your application-specific code with your imported library code.

From version 9 and higher, the Firebase JavaScript SDK is optimized to work with the optimization features of module bundlers to reduce the amount of Firebase code included in your final build.

I followed the easy-to-understand webpack example shown in the docs. My only change was in webpack.config.js, were I put bundle.js in the public directory rather than dist:

 output: {
    path: path.resolve(__dirname, 'public'), // change here
    filename: 'bundle.js'
 },

I do this because Firebase tends to put their web app code in a directory called public.

In public/index.html, near the bottom of the body tag, I use this code to load bundle.js:

 <script src="bundle.js"></script>

I put it there because that file might take the longest to load, so I make everything else in index.html visible and then begin the potentially longer bundle.js load process.

After doing this the following code from my index.js file began to work:

import { initializeApp } from 'firebase/app';

Upvotes: 1

RobGH999
RobGH999

Reputation: 206

To run Firestore without Webpack or Rollup, skip the npm installs and replace the import lines with Firestore's browser module references. It's explained here:

https://firebase.google.com/docs/web/setup?sdk_version=v9&authuser=0 (in Step 2).

The video is helpful as well, and it explains Firebase's new (in V9) modular/functional vs. the deprecated object.method model.

Here's how my JS module for the Firestore connection to a web app I've developed for work:

// Import the functions you need from the SDKs you need
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.1.1/firebase-app.js";
import { getFirestore } from "https://www.gstatic.com/firebasejs/9.1.1/firebase-firestore.js"
import { collection, getDocs, addDoc, Timestamp } from "https://www.gstatic.com/firebasejs/9.1.1/firebase-firestore.js"
import { query, orderBy, limit, where, onSnapshot } from "https://www.gstatic.com/firebasejs/9.1.1/firebase-firestore.js"
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "xxxxxx.firebaseapp.com",
projectId: "xxxx9",
storageBucket: "xxxxx.appspot.com",
messagingSenderId: "xxxxx",
appId: "1:xxx:web:xxx"
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);

export { app, db, collection, getDocs, Timestamp, addDoc };
export { query, orderBy, limit, where, onSnapshot };

Upvotes: 19

samthecodingman
samthecodingman

Reputation: 26171

When you use import { ... } from "some/package", you are expected to use a bundler like Webpack or Rollup to compile your code prior to accessing it on a website. This pulls the pieces you need out from your dependencies ready for use by your code.

Especially in v9+ of the SDK, the Firebase SDK was rewritten to support these bundlers, so expect many code examples you see to have been written for the now deprecated v8 or older. How to move this older code is covered in this migration guide.

A key takeaway from that guide is that firebase is no longer a global object. As you are new to Firebase, I would avoid writing any code that uses the old syntax. You can spot older syntax by looking for code like firebase.initializeApp(), firebase.database(), firebase.firestore() and so on. In the SDK those examples have been replaced by initializeApp(), getDatabase() and getFirestore() respectively.

If you intend to use modular code directly in your browser (using <script type="module" src="..."></script>), it is important to remember that the code is isolated from the browser console - you can't run console.log(firebaseConfig) and expect it to have your object.

This next section is not for production code, just for trying things out in a familiar environment.

If you want to tinker around with the Firebase libraries in your browser console, you will add something similar to this:

<script type="module">
  window.FIREBASE_MODULES = window.FM = {};

  async function loadFirebaseModule(serviceName, sinkErrors) {      
    const name = serviceName.toLowerCase();
    if (window.FIREBASE_MODULES[name]) return window.FIREBASE_MODULES[name];
      
    try {
      // uses unpkg to get the latest semver
      if (!loadFirebaseModule.version) {
        const response = await fetch("https://unpkg.com/firebase/firebase-app.js", { method: "HEAD" });
        const match = /@\d+(?:\.\d+)*/.exec(response.url);
        if (!match) {
          console.log("Unexpected resource URL (SemVer could not be determined, falling back to v9.0.0): " + response.url);
          loadFirebaseModule.version = "9.0.0";
        } else {
          loadFirebaseModule.version = match[0].slice(1);
        }
      }
      
      // use the found semver to pull from Google's CDN
      const module = await import(`https://www.gstatic.com/firebasejs/${loadFirebaseModule.version}/firebase-${name}.js`);
      window.FIREBASE_MODULES[name] = module;
        
      console.log(`Successfully imported "${name}" module`)
      return module;
    } catch (err) {
      if (sinkErrors) {
        console.error(`Failed to import "${name}" module`, err);
      } else {
        throw err;
      }
    }
  }
  window.loadFirebaseModule = loadFirebaseModule;
</script>

That little snippet will now allow you to run code like this either in-page or in the browser's console. It returns a Promise, so make sure to wait for it to finish resolving if you are using it inside a script.

loadFirebaseModule('app')
  .then(({ initializeApp }) => {
    initializeApp({ /* ... config ... */ });
  });

loadFirebaseModule('storage');
loadFirebaseModule('storage', true); // import & ignore the error

Once a module is loaded, you can use const { getApp } = FM.app similar to how you would use import { getApp } from "firebase/app".

Upvotes: 8

Related Questions