Ошибка ссылки: документ не определен. Работник сферы обслуживания. Рабочий ящик

#service-worker #workbox

Вопрос:

Я учусь писать код сервисного работника и застрял с ошибкой «Ошибка ссылки: документ не определен» в моем app.js файл. Я использую библиотеку workbox в режиме InjectManifest. Я думаю, что проблема в webpack.config.js, потому что когда я удаляю InjectManifest в webpack.config.js ошибка исчезает.

Мой webpack.config.js

 const path = require('path');
const webpack = require('webpack');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const {InjectManifest} = require('workbox-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
      {
        test: /.html$/i,
        use: [
          {
            loader: 'html-loader',
          },
        ],
      },
      {
        test: /.css$/,
        use: [
          MiniCssExtractPlugin.loader, 'css-loader',
        ],
      },
      {
        test: /.(png|jpg|gif)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
            },
          },
        ],
      },
    ],
  },
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: './src/index.html',
      filename: './index.html',
    }),
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
     new InjectManifest({
       swSrc: './src/js/service.worker.js',
       swDest: 'service.worker.js',
    }),
  ],
};
 

Мой service.worker.js файл:

 import { precacheAndRoute } from 'workbox-precaching/precacheAndRoute';
import { cinemaNews } from './cinemaNews';
import { url } from './app';

precacheAndRoute(self.__WB_MANIFEST);

const CACHE_NAME = 'v1';

const responseCache = new Response(JSON.stringify(cinemaNews));

self.addEventListener('install', (evt) => {
  console.log('install')
  evt.waitUntil((async () => {
    console.log('install waitUntil')
    const cache = await caches.open(CACHE_NAME);
    await cache.put(url, responseCache);
    await self.skipWaiting();
  })());
});
  
self.addEventListener('activate', (evt) => {
  console.log('activate')
  evt.waitUntil(self.clients.claim());
});

self.addEventListener('fetch', (evt) => {
  console.log('sw fetch')
  const requestUrl = new URL(evt.request.url);
  
  if (!requestUrl.pathname.startsWith('/news')) return;
  
  evt.respondWith((async () => {
    console.log('respondWith')
    const cache = await caches.open(CACHE_NAME);
    const cachedResponse = await cache.match(evt.request);
    return cachedResponse;
  })());
  
  evt.waitUntil((async () => {
    console.log('waitUntil');
    const response = await fetch(evt.request.url);
    const client = await clients.get(evt.clientId);
    let json = await response.json();
    client.postMessage(json);
  })());
});
 

Комментарии:

1. Какой код есть в вашем ./src/js/service.worker.js файле? Можете ли вы опубликовать этот вопрос?

2. @JeffPosnick Да, конечно. Я добавил

Ответ №1:

Это заявление:

 import { url } from './app';
 

по-видимому, это вызывает проблему, так как внутри вас должен быть код app.js , который выполняется с помощью этого импорта и который предполагает, что document это будет определено. (Это не определено внутри ServiceWorkerGlobalScope .)

Исходя из того, как вы используете экспорт, я предполагаю, что это просто строковая константа, содержащая общий URL-адрес, который вы хотите использовать как из своего основного веб-приложения, так и из вашего сервисного работника. Предполагая, что это так, проще всего было бы провести рефакторинг ваших модулей, чтобы создать constants.js модуль (или с похожим названием), который экспортирует только ваши строковые константы и не пытается запускать какой-либо код, на который ссылается document . Затем вы можете без проблем импортировать константу либо из своего веб-приложения, либо из сотрудника службы.

 // constants.js

export const url = '/path/to/url';
 
 // service-worker.js

import {url} from './constants';
// do something with url
 
 // app.js

import {url} from './constants';
// do something with url