mattermost-webapp 애플리케이션에 서비스 워커를 통합할 때 오류가 발생했습니다.
설명:
현재 내 신청서는
http://localhost:8065/static/ 그러나 본질적으로 정확하려면 http://localhost:8065/에서 시작해야 합니다.
따라서 내 Pwa 응용 프로그램을 시작할 때 start_url은 http://localhost:8065/static/이며 404 오류가 발생해야 합니다.
표적:
start_url을 http://localhost:8065/으로 설정해야 합니다. 아니면 서비스 워커가 제대로 작동하고 루트 폴더에서 초기화되는 방법이 있습니까? 해결책이 필요해
도와주세요
내 코드 설명은 다음과 같습니다.
root.jsx에 serviceWorker를 등록합니다.
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
// Scope will be restricted to the path where the src-sw.js file is located
navigator.serviceWorker.register('/static/sw.js', {scope: '/static/'}).then((registration) => {
console.log('Service Worker registered: ', registration);
}).catch((registrationError) => {
console.log('Service Worker registration failed: ', registrationError);
});
});
}
이것은 webpack.config.js입니다.
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
const childProcess = require('child_process');
const path = require('path');
const url = require('url');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const WebpackPwaManifest = require('webpack-pwa-manifest');
const LiveReloadPlugin = require('webpack-livereload-plugin');
const WorkboxPlugin = require('workbox-webpack-plugin');
const NPM_TARGET = process.env.npm_lifecycle_event; //eslint-disable-line no-process-env
const targetIsRun = NPM_TARGET === 'run';
const targetIsTest = NPM_TARGET === 'test';
const targetIsStats = NPM_TARGET === 'stats';
const targetIsDevServer = NPM_TARGET === 'dev-server';
const DEV = targetIsRun || targetIsStats || targetIsDevServer;
const STANDARD_EXCLUDE = [
path.join(__dirname, 'node_modules'),
];
// react-hot-loader requires eval
const CSP_UNSAFE_EVAL_IF_DEV = targetIsDevServer ? ' \'unsafe-eval\'' : '';
var MYSTATS = {
// Add asset Information
assets: false,
// Sort assets by a field
assetsSort: '',
// Add information about cached (not built) modules
cached: true,
// Show cached assets (setting this to `false` only shows emitted files)
cachedAssets: true,
// Add children information
children: true,
// Add chunk information (setting this to `false` allows for a less verbose output)
chunks: true,
// Add built modules information to chunk information
chunkModules: true,
// Add the origins of chunks and chunk merging info
chunkOrigins: true,
// Sort the chunks by a field
chunksSort: '',
// `webpack --colors` equivalent
colors: true,
// Display the distance from the entry point for each module
depth: true,
// Display the entry points with the corresponding bundles
entrypoints: true,
// Add errors
errors: true,
// Add details to errors (like resolving log)
errorDetails: true,
// Exclude modules which match one of the given strings or regular expressions
exclude: [],
// Add the hash of the compilation
hash: true,
// Set the maximum number of modules to be shown
maxModules: 0,
// Add built modules information
modules: false,
// Sort the modules by a field
modulesSort: '!size',
// Show performance hint when file size exceeds `performance.maxAssetSize`
performance: true,
// Show the exports of the modules
providedExports: true,
// Add public path information
publicPath: true,
// Add information about the reasons why modules are included
reasons: true,
// Add the source code of modules
source: true,
// Add timing information
timings: true,
// Show which exports of a module are used
usedExports: true,
// Add webpack version information
version: true,
// Add warnings
warnings: true,
// Filter warnings to be shown (since webpack 2.4.0),
// can be a String, Regexp, a function getting the warning and returning a boolean
// or an Array of a combination of the above. First match wins.
warningsFilter: '',
};
let publicPath = '/static/';
// Allow overriding the publicPath in dev from the exported SiteURL.
if (DEV) {
const siteURL = process.env.MM_SERVICESETTINGS_SITEURL || ''; //eslint-disable-line no-process-env
if (siteURL) {
publicPath = path.join(new url.URL(siteURL).pathname, 'static') + '/';
}
}
var config = {
entry: ['./root.jsx', 'root.html'],
output: {
path: path.join(__dirname, 'dist'),
publicPath,
filename: '[name].[hash].js',
chunkFilename: '[name].[contenthash].js',
},
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)?$/,
exclude: STANDARD_EXCLUDE,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
// Babel configuration is in .babelrc because jest requires it to be there.
},
},
},
{
type: 'javascript/auto',
test: /\.json$/,
include: [
path.resolve(__dirname, 'i18n'),
],
exclude: [/en\.json$/],
use: [
{
loader: 'file-loader?name=i18n/[name].[hash].[ext]',
},
],
},
{
test: /\.scss$/,
use: [
DEV ? 'style-loader' : MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
},
{
loader: 'sass-loader',
options: {
sassOptions: {
includePaths: ['node_modules/compass-mixins/lib', 'sass'],
},
},
},
],
},
{
test: /\.css$/,
use: [
DEV ? 'style-loader' : MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
},
],
},
{
test: /\.(png|eot|tiff|svg|woff2|woff|ttf|gif|mp3|jpg)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'files/[hash].[ext]',
},
},
{
loader: 'image-webpack-loader',
options: {},
},
],
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
options: {
attributes: {
list: [
{
tag: 'link',
attribute: 'href',
type: 'src',
},
],
},
},
},
],
},
],
},
resolve: {
modules: [
'node_modules',
path.resolve(__dirname),
],
alias: {
jquery: 'jquery/src/jquery',
superagent: 'node_modules/superagent/lib/client',
},
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
performance: {
hints: 'warning',
},
target: 'web',
plugins: [
new webpack.ProvidePlugin({
'window.jQuery': 'jquery',
$: 'jquery',
jQuery: 'jquery',
}),
new webpack.DefinePlugin({
COMMIT_HASH: JSON.stringify(childProcess.execSync('git rev-parse HEAD || echo dev').toString()),
}),
new MiniCssExtractPlugin({
filename: '[name].[contentHash].css',
chunkFilename: '[name].[contentHash].css',
}),
new HtmlWebpackPlugin({
filename: 'root.html',
inject: 'head',
template: 'root.html',
title: 'Progressive Web Application',
meta: {
csp: {
'http-equiv': 'Content-Security-Policy',
content: 'script-src \'self\' \'unsafe-eval\' cdn.rudderlabs.com *.facebook.com *.fbcdn.net *.facebook.net *.google-analytics.com *.virtualearth.net *.google.com 127.0.0.1:* *.spotilocal.com:* ' + CSP_UNSAFE_EVAL_IF_DEV,
},
},
}),
new CopyWebpackPlugin({
patterns: [
{from: 'images/emoji', to: 'emoji'},
{from: 'images/img_trans.gif', to: 'images'},
{from: 'images/logo-email.png', to: 'images'},
{from: 'images/circles.png', to: 'images'},
{from: 'images/favicon', to: 'images/favicon'},
{from: 'images/appIcons.png', to: 'images'},
{from: 'images/warning.png', to: 'images'},
{from: 'images/logo-email.png', to: 'images'},
{from: 'images/browser-icons', to: 'images/browser-icons'},
],
}),
// Generate manifest.json, honouring any configured publicPath. This also handles injecting
// <link rel="apple-touch-icon" ... /> and <meta name="apple-*" ... /> tags into root.html.
new WebpackPwaManifest({
name: 'ChatOps',
short_name: 'ChatOps',
start_url: './',
description: 'ChatOps is Seamless Collaboration Platform',
background_color: '#ffffff',
inject: true,
ios: true,
fingerprints: false,
orientation: 'any',
filename: 'manifest.json',
icons: [{
src: path.resolve('images/favicon/android-chrome-192x192.png'),
type: 'image/png',
sizes: '192x192',
}, {
src: path.resolve('images/favicon/apple-touch-icon-120x120.png'),
type: 'image/png',
sizes: '120x120',
ios: true,
}, {
src: path.resolve('images/favicon/apple-touch-icon-144x144.png'),
type: 'image/png',
sizes: '144x144',
ios: true,
}, {
src: path.resolve('images/favicon/apple-touch-icon-152x152.png'),
type: 'image/png',
sizes: '152x152',
ios: true,
}, {
src: path.resolve('images/favicon/apple-touch-icon-57x57.png'),
type: 'image/png',
sizes: '57x57',
ios: true,
}, {
src: path.resolve('images/favicon/apple-touch-icon-60x60.png'),
type: 'image/png',
sizes: '60x60',
ios: true,
}, {
src: path.resolve('images/favicon/apple-touch-icon-72x72.png'),
type: 'image/png',
sizes: '72x72',
ios: true,
}, {
src: path.resolve('images/favicon/apple-touch-icon-76x76.png'),
type: 'image/png',
sizes: '76x76',
ios: true,
}, {
src: path.resolve('images/favicon/favicon-16x16.png'),
type: 'image/png',
sizes: '16x16',
}, {
src: path.resolve('images/favicon/favicon-32x32.png'),
type: 'image/png',
sizes: '32x32',
}, {
src: path.resolve('images/favicon/favicon-96x96.png'),
type: 'image/png',
sizes: '96x96',
}],
}),
new WorkboxPlugin.InjectManifest({
swSrc: './src-sw.js',
swDest: 'sw.js',
exclude: [
/\.map$/,
/manifest$/,
/\.htaccess$/,
/service-worker\.js$/,
/sw\.js$/,
],
}),
],
};
if (!targetIsStats) {
config.stats = MYSTATS;
}
// Development mode configuration
if (DEV) {
config.mode = 'development';
config.devtool = 'source-map';
}
// Production mode configuration
if (!DEV) {
config.mode = 'production';
config.devtool = 'source-map';
}
const env = {};
if (DEV) {
env.PUBLIC_PATH = JSON.stringify(publicPath);
if (process.env.MM_LIVE_RELOAD) { //eslint-disable-line no-process-env
config.plugins.push(new LiveReloadPlugin());
}
} else {
env.NODE_ENV = JSON.stringify('production');
}
config.plugins.push(new webpack.DefinePlugin({
'process.env': env,
}));
// Test mode configuration
if (targetIsTest) {
config.entry = ['./root.jsx'];
config.target = 'node';
config.externals = [nodeExternals()];
}
if (targetIsDevServer) {
config = {
...config,
devtool: 'cheap-module-eval-source-map',
devServer: {
hot: true,
injectHot: true,
liveReload: false,
overlay: true,
proxy: [{
context: () => true,
bypass(req) {
if (req.url.indexOf('/api') === 0 ||
req.url.indexOf('/plugins') === 0 ||
req.url.indexOf('/static/plugins/') === 0 ||
req.url.indexOf('/sockjs-node/') !== -1) {
return null; // send through proxy to the server
}
if (req.url.indexOf('/static/') === 0) {
return path; // return the webpacked asset
}
// redirect (root, team routes, etc)
return '/static/root.html';
},
logLevel: 'silent',
target: 'http://localhost:8065',
xfwd: true,
ws: true,
}],
port: 9005,
watchContentBase: true,
writeToDisk: false,
},
performance: false,
optimization: {
...config.optimization,
splitChunks: false,
},
resolve: {
...config.resolve,
alias: {
...config.resolve.alias,
'react-dom': '@hot-loader/react-dom',
},
},
};
}
// Export PRODUCTION_PERF_DEBUG=1 when running webpack to enable support for the react profiler
// even while generating production code. (Performance testing development code is typically
// not helpful.)
// See https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html and
// https://gist.github.com/bvaughn/25e6233aeb1b4f0cdb8d8366e54a3977
if (process.env.PRODUCTION_PERF_DEBUG) { //eslint-disable-line no-process-env
console.log('Enabling production performance debug settings'); //eslint-disable-line no-console
config.resolve.alias['react-dom'] = 'react-dom/profiling';
config.resolve.alias['schedule/tracing'] = 'schedule/tracing-profiling';
config.optimization = {
// Skip minification to make the profiled data more useful.
minimize: false,
};
}
module.exports = config;
이것은 src-sw.js입니다.
"workbox-webpack-plugin": "4.3.1",
"workbox-window": "4.3.1",
if ('workbox' in self) {
workbox.precaching.precacheAndRoute(self.__precacheManifest);
// self.__precacheManifest
workbox.routing.registerRoute(
/https:\/\/api\.exchangeratesapi\.io\/latest/,
new workbox.strategies.NetworkFirst({
cacheName: 'ChatOpsDemoCache',
plugins: [
new workbox.expiration.Plugin({
maxAgeSeconds: 10 * 60, // 10 minutes
}),
],
}),
);
}
addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
skipWaiting();
}
});
Reference
이 문제에 관하여(mattermost-webapp 애플리케이션에 서비스 워커를 통합할 때 오류가 발생했습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/aitranxuan/error-when-integrating-service-worker-into-mattermost-webapp-application-213k텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)