ReferenceError: document is not defined. Service worker. Workbox
ReferenceError: document is not defined. Service worker. Workbox
我正在学习如何编写 service worker 的代码,但在我的 app.js 文件中遇到了错误“ReferenceError: document is not defined”。我在 InjectManifest 模式下使用工作箱库。我认为问题在 webpack.config.js,因为当我在 webpack.config.js 中删除 InjectManifest 时,错误消失了。
我的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);
})());
});
这条语句:
import { url } from './app';
似乎触发了该问题,因为您的 app.js
中必须有通过该导入执行的代码,并且假定 document
将被定义。 (它没有在 ServiceWorkerGlobalScope
内部定义。)
根据您使用导出的方式,我假设它只是一个包含共享 URL 的字符串常量,您希望从主 Web 应用程序和服务工作者中使用它。假设是这种情况,最简单的事情就是重构你的模块,有一个 constants.js
(或一些类似的名称)模块只导出你的字符串常量,并且不会尝试 运行 任何引用 document
的代码。然后,您可以毫无问题地从您的 Web 应用程序或 Service Worker 导入常量。
// 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
我正在学习如何编写 service worker 的代码,但在我的 app.js 文件中遇到了错误“ReferenceError: document is not defined”。我在 InjectManifest 模式下使用工作箱库。我认为问题在 webpack.config.js,因为当我在 webpack.config.js 中删除 InjectManifest 时,错误消失了。
我的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);
})());
});
这条语句:
import { url } from './app';
似乎触发了该问题,因为您的 app.js
中必须有通过该导入执行的代码,并且假定 document
将被定义。 (它没有在 ServiceWorkerGlobalScope
内部定义。)
根据您使用导出的方式,我假设它只是一个包含共享 URL 的字符串常量,您希望从主 Web 应用程序和服务工作者中使用它。假设是这种情况,最简单的事情就是重构你的模块,有一个 constants.js
(或一些类似的名称)模块只导出你的字符串常量,并且不会尝试 运行 任何引用 document
的代码。然后,您可以毫无问题地从您的 Web 应用程序或 Service Worker 导入常量。
// 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