firebase / firebase-js-sdk

Firebase Javascript SDK
https://firebase.google.com/docs/web/setup
Other
4.74k stars 868 forks source link

FirebaseError: Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker for scope ('http://localhost:3000/firebase-cloud-messaging-push-scope') with script ('http://localhost:3000/firebase-messaging-sw.js'): A bad HTTP response code (404) was received when fetching the script. (messaging/failed-service-worker-registration). #8205

Closed Jmyerzzz closed 2 weeks ago

Jmyerzzz commented 3 weeks ago

Operating System

MacOS 14

Browser Version

Chrome v124

Firebase SDK Version

10.11.0

Firebase SDK Product:

Messaging

Describe your project's tooling

React app with webpack

Describe the problem

When my app is rendered and this block of code runs to getToken() I receive the error in the title.

await getToken(messaging, {
      vapidKey: "***",
    })
      .then((currentToken: string) => {
        console.log('Current token for client: ', currentToken);
        // Perform any other neccessary action with the token
      })
      .catch((err: any) => {
        console.log('An error occurred while retrieving token. ', err);
      });

I have tried just about every stack overflow solution and others mentioned in github issues—all to no avail.

I suspect this is an issue with webpack. I have a blank firebase-messaging-sw.js file in my /public directory. My webpack config look like the following.

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
  cache: {
    type: 'filesystem',
    cacheDirectory: path.resolve(__dirname, '.webpack_cache'),
    buildDependencies: {
      config: [__filename],
    },
  },
  context: path.resolve(path.join(__dirname, './')),
  entry: {
    build: './src/index.tsx',
  },
  output: {
    filename: '[name].[fullhash].bundle.js',
    chunkFilename: '[name].[chunkhash].bundle.js',
    path: path.resolve(__dirname, './build/'),
    publicPath: '/',
    clean: true,
  },
  resolve: {
    fallback: { process: false, path: false },
    extensions: ['.ts', '.tsx', '.js'],
  },
  module: {
    rules: [
      {
        test: /\.ts(x?)$/,
        exclude: /node_modules/,
        use: {
          loader: 'ts-loader',
          options: {
            configFile: path.join(__dirname, './tsconfig.json'),
            projectReferences: true,
          },
        },
      },
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.(eot|woff|woff2|ttf|png|jpe?g|gif)(\?\S*)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 100000,
              name: '[name].[ext]',
            },
          },
        ],
      },
      {
        test: /\.svg$/,
        use: ['@svgr/webpack'],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin(),
    new ESLintPlugin({
      extensions: ['ts', 'tsx'],
    }),
    new webpack.ProvidePlugin({
      process: 'process/browser',
    }),
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, './public/images/'),
          to: path.resolve(__dirname, './build/assets/images/'),
        },
        {
          from: path.resolve(__dirname, './public/config'),
          to: path.resolve(__dirname, './build/config'),
        },
        {
          from: './firebase-messaging-sw.js',
          to: './firebase-messaging-sw.js',
        }
      ],
    }),
    new HtmlWebpackPlugin({
      template: './public/index.html',
      filename: 'index.html',
      inject: true,
    }),
    new FaviconsWebpackPlugin({
      logo: path.resolve(__dirname, './public/favicon.png'),
      prefix: 'assets/meta/',
      inject: true,
    }),
  ],
};

Any guidance on this is much appreciated. I am blocked by this error message.

Steps and code to reproduce issue

Steps to reproduce are listed in the description

hsubox76 commented 3 weeks ago

One quick check first: if you start up your dev server and navigate in your browser to http://localhost:3000/firebase-messaging-sw.js, do you get a 404?

jbalidiong commented 3 weeks ago

Hi @Jmyerzzz, I'm unable to reproduce the same behavior you're experiencing. But to add from what hsubox76 said. Usually this error is thrown because of runtime error in the sw script. If you could provide us a minimal repro, it'll help us out to a faster resolution. Thanks!

hsubox76 commented 3 weeks ago

Actually, to clarify, the 404 error is not thrown because of an error in the sw script, but if the sw script isn't there at all, i.e., if you navigate there using your browser's url field, you get a 404. There's a different error thrown if there's an error in the sw script that ends with the string "ServiceWorker script evaluation failed".

Jmyerzzz commented 2 weeks ago

Thanks for the help here, I was able to resolve this by adding to my webpack config

plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, './public/firebase-messaging-sw.js'),
          to: path.resolve(__dirname, './build/firebase-messaging-sw.js'),
        },
      ],
    }),
  ],

The error I'm now running into is SyntaxError: Cannot use import statement outside a module (at firebase-messaging-sw.js:1:1). I can resolve this by changing the file extension to .mjs in that webpack config but it then seems messaging doesn't work because firebase is expecting that specific file name.

I know this error is separate from the issue reported, so lmk if I should open a new one

jbalidiong commented 2 weeks ago

@Jmyerzzz, service worker doesn't yet support modularization. To use the latest version of the SDK, please use the compat version when importing the script. With that, I'll be closing the ticket now. If the issue persists, feel free to comment and reopen this issue.

/**
 * Here is is the code snippet to initialize Firebase Messaging in the Service
 * Worker when your app is not hosted on Firebase Hosting.

 // Give the service worker access to Firebase Messaging.
 // Note that you can only use Firebase Messaging here. Other Firebase libraries
 // are not available in the service worker.
 importScripts('https://www.gstatic.com/firebasejs/10.11.1/firebase-app-compat.js');
 importScripts('https://www.gstatic.com/firebasejs/10.11.1/firebase-messaging-compat.js');
jbalidiong commented 2 weeks ago

It looks like the initial issue was already solved. I'll be closing this issue now. If you encounter another issue, feel free to create a new one.