You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js中打包Service Worker并解决import语法错误?

问题描述

我正在按照Firebase官方指南配置Service Worker,用来拦截并修改fetch()请求,但现在出现了错误:

Uncaught SyntaxError: Cannot use import statement outside a module (at service-worker.js:1:1)

我怀疑这和指南里的提示有关:

Make sure that the service worker is bundled so that it will still work after the browser has been closed.

我对这个主题不太熟悉,用的是Next.js,只在Next.js文档里找到相关的打包内容。

我的Service Worker代码:

// public/service-worker.js

import { auth } from "@/firebase/firebase"
import { getIdToken, onAuthStateChanged } from "firebase/auth"

// Firebase docs use "activate" not "install"
self.addEventListener("install", (event) => {
  console.log("Installing...")
})

...

注册Service Worker的代码:

// src/app/signup/SignUpForm.js

"use client"

export function SignUpForm() {
  useEffect(() => {
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/service-worker.js', { scope: '/' })
    }
  }, [])
  ...
}

请问该如何解决这个错误?


解决方案

错误根源

Service Worker运行在独立的浏览器全局环境中,默认不支持ES模块的import语法;而且Next.js的public目录下的文件会被直接静态托管,不会经过模块打包流程,导致Firebase的导入语句无法被解析。

方案1:改用Firebase CDN脚本引入(快速解决)

直接在Service Worker中通过importScripts加载Firebase的兼容版SDK,避免使用ES模块导入:

// public/service-worker.js
// 加载Firebase兼容版SDK
importScripts('https://www.gstatic.com/firebasejs/9.23.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/9.23.0/firebase-auth-compat.js');

// 初始化Firebase(和你项目中的配置完全一致)
const firebaseConfig = {
  apiKey: "你的API_KEY",
  authDomain: "你的AUTH_DOMAIN",
  projectId: "你的PROJECT_ID",
  storageBucket: "你的STORAGE_BUCKET",
  messagingSenderId: "你的MESSAGING_SENDER_ID",
  appId: "你的APP_ID"
};

firebase.initializeApp(firebaseConfig);
const auth = firebase.auth();

// 后续正常使用Firebase Auth API
self.addEventListener("install", (event) => {
  console.log("Installing...")
});

// 其他拦截逻辑...

方案2:使用Next.js专用PWA插件(推荐,适配Next.js生态)

借助@ducanh2912/next-pwa插件自动打包Service Worker,支持ES模块导入:

  1. 安装依赖:
    npm install @ducanh2912/next-pwa
    
  2. 修改next.config.js配置:
    const withPWA = require('@ducanh2912/next-pwa').default({
      dest: 'public',
      register: true, // 自动注册Service Worker
      skipWaiting: true,
      customWorkerDir: 'src/service-worker', // 自定义Service Worker源码目录
    });
    
    module.exports = withPWA({
      // 你的Next.js原有配置
    });
    
  3. 将Service Worker源码移到src/service-worker/index.js,现在可以正常使用ES模块导入:
    // src/service-worker/index.js
    import { auth } from "@/firebase/firebase";
    import { getIdToken, onAuthStateChanged } from "firebase/auth";
    
    self.addEventListener("install", (event) => {
      console.log("Installing...")
    });
    
    // 其他逻辑...
    
  4. 移除组件中手动注册Service Worker的代码(插件会自动处理注册)。

方案3:手动打包Service Worker(自定义流程)

用esbuild或webpack单独打包Service Worker源码,将ES模块转换为浏览器兼容格式:

  1. 安装esbuild:
    npm install esbuild --save-dev
    
  2. 创建打包脚本build-sw.js:
    require('esbuild').build({
      entryPoints: ['src/service-worker.js'],
      bundle: true,
      outfile: 'public/service-worker.js',
      format: 'iife', // 输出自执行函数,适配Service Worker环境
      platform: 'browser',
    }).catch(() => process.exit(1));
    
  3. 在package.json中添加打包命令:
    "scripts": {
      "build:sw": "node build-sw.js",
      "build": "npm run build:sw && next build"
    }
    
  4. 将Service Worker源码移到src/service-worker.js,正常使用ES模块导入,每次构建时会自动打包到public目录。

内容的提问来源于stack exchange,提问作者Ben

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 08:52:28