首页 > 解决方案 > Service Worker 注册成功后出现“bad-precaching-response”错误

问题描述

在我的项目中,我使用的是 NextJS+KOA+Apollo。我的 nextJS 应用程序位于根目录中的客户端内。我正在使用 next-offline 将其转换为 PWA。

Nextjs 应用程序位于客户端目录中。koa 服务器位于服务器目录中。

当我通过以下命令构建应用程序时:

next build client && tsc --project tsconfig.server.json

它在客户端内为 nextjs 创建一个构建目录,并在顶层为 koa 服务器创建一个 dist 目录。

我通过以下命令在生产中运行代码

NODE_ENV=production node dist/server/index.js

ISSUE 服务工作者正在正确注册。但我得到以下错误:

PrecacheController.mjs:194 
Uncaught (in promise) bad-precaching-response: bad-precaching-response :: [{"url":"https://my-domain/_next/bo.svg?__WB_REVISION__=e02afe0476bb357aebde18136fda06e0","status":404}] 
at l.o (https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-precaching.prod.js:1:1749) 
at async Promise.all (index 0) 
at async l.install (https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-precaching.prod.js:1:1221)

在此处输入图像描述

下面是我生成的构建文件:

在此处输入图像描述

tsconfig.server.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs",
    "outDir": "dist",
    "target": "es2017",
    "isolatedModules": false,
    "noEmit": false
  },
  "include": ["server/**/*.ts"]
}

下面是我的 next.config.js (在客户端目录中)

/* eslint-disable @typescript-eslint/no-var-requires */
const withPlugins = require("next-compose-plugins");
const offline = require("next-offline");
const pino = require("next-pino");
const withTypescript = require("@zeit/next-typescript");
const withCSS = require("@zeit/next-css");
const withLess = require("@zeit/next-less");
const Dotenv = require("dotenv-webpack");
const path = require("path");
const _ = require("lodash");

const nextConfig = {
  distDir: "build",
  webpack(config) {
    config.module.rules.push({
      test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
      use: {
        loader: "url-loader",
        options: {
          limit: 100000,
          name: "[name].[ext]",
        },
      },
    });
    config.plugins.push(
      new Dotenv({
        path: path.resolve(process.cwd(), ".env"),
        systemvars: true,
      }),
    );
    return config;
  },
  // overwrites values given in the .env file with the current
  // process.env value
  env: _.omitBy(
    {
      GRAPHQL_SERVER: process.env.GRAPHQL_SERVER,
    },
    _.isUndefined,
  ),
  workboxOpts: {
    globPatterns: ["static/**/*"],
    globDirectory: "client",
    runtimeCaching: [
      {
        urlPattern: /^https?.*/,
        handler: "NetworkFirst",
        options: {
          cacheName: "offlineCache",
          expiration: {
            maxEntries: 200,
          },
        },
      },
    ],
  },
};

const cssConfig = {
  cssModules: true,
  cssLoaderOptions: {
    importLoaders: 1,
    localIdentName: "[local]",
  },
};

const lessConfig = cssConfig;

module.exports = withPlugins(
  [
    [offline],
    [pino],
    [withTypescript],
    [withCSS, cssConfig],
    [withLess, lessConfig],
  ],
  nextConfig,
);

下面是我启动 koa 服务器的文件

import Router from "koa-router";
 const server = new Koa();
const dev = !["production", "staging"].includes(process.env.NODE_ENV || "");
const app = next({ dir: "./client", dev });
const publicRouter = new Router();

const handle = app.getRequestHandler();

publicRouter.get("/service-worker.js", async ctx => {
      const pathname = await join(
        __dirname,
        "../../../client/build",
        "service-worker.js",
      );
      ctx.body = await app.serveStatic(ctx.req, ctx.res, pathname);
      ctx.respond = false;
    });

publicRouter.get("*", async ctx => {
      if (!ctx.path.match(/graphql/)) {
        await handle(ctx.req, ctx.res);
        ctx.respond = false;
      }
    });

server.use(async (ctx, next) => {
      ctx.res.statusCode = 200;
      await next();
    });
server.use(publicRouter.routes()).use(publicRouter.allowedMethods());
 server.listen({ port: 3000 });

==================================================== ===============

我现在做了一个肮脏的修复。我不确定如何正确处理它。如果有人能就此提出意见,我将不胜感激。

作为bo.svg,firfox.svg,所有这些静态文件都在我的文件中抛出404,Ex - (/_next/bo.svg?WB_REVISION=e02afe0476bb357aebde18136fda06e0) 以启动koa服务器,添加了一个条件来检查这个URL并提供静态文件从如下构建目录:

publicRouter.get("*", async ctx => {
      if (ctx.path.match(/\_next/) && ctx.path.match(/\.svg/)) {
        const pathname = await join(
          __dirname,
          "../../../client/build",
          ctx.path.replace("_next/", ""),
        );
        ctx.body = await app.serveStatic(ctx.req, ctx.res, pathname);
        ctx.respond = false;
      } else if (!ctx.path.match(/graphql/)) {
        await handle(ctx.req, ctx.res);
        ctx.respond = false;
      }
    });

它现在符合我的目的,但不确定如何正确处理。

标签: service-workernext.jskoa

解决方案


推荐阅读