diff --git a/packages/react-dev-utils/FileSizeReporter.js b/packages/react-dev-utils/FileSizeReporter.js
index b2b4cc6904d..80a1b4e7244 100644
--- a/packages/react-dev-utils/FileSizeReporter.js
+++ b/packages/react-dev-utils/FileSizeReporter.js
@@ -16,11 +16,7 @@ var stripAnsi = require('strip-ansi');
var gzipSize = require('gzip-size').sync;
function canReadAsset(asset) {
- return (
- /\.(js|css)$/.test(asset) &&
- !/service-worker\.js/.test(asset) &&
- !/precache-manifest\.[0-9a-f]+\.js/.test(asset)
- );
+ return /\.(js|css)$/.test(asset);
}
// Prints a detailed summary of build files.
diff --git a/packages/react-dev-utils/WebpackDevServerUtils.js b/packages/react-dev-utils/WebpackDevServerUtils.js
index d43f141c387..c9b954aeb69 100644
--- a/packages/react-dev-utils/WebpackDevServerUtils.js
+++ b/packages/react-dev-utils/WebpackDevServerUtils.js
@@ -113,9 +113,9 @@ function createCompiler({
}) {
// "Compiler" is a low-level interface to Webpack.
// It lets us listen to some events and provide our own custom messages.
- let compiler;
+ let masterCompiler;
try {
- compiler = webpack(config);
+ masterCompiler = webpack(config);
} catch (err) {
console.log(chalk.red('Failed to compile.'));
console.log();
@@ -128,7 +128,7 @@ function createCompiler({
// recompiling a bundle. WebpackDevServer takes care to pause serving the
// bundle, so if you refresh, it'll wait instead of serving the old one.
// "invalid" is short for "bundle invalidated", it doesn't imply any errors.
- compiler.hooks.invalid.tap('invalid', () => {
+ masterCompiler.hooks.invalid.tap('invalid', () => {
if (isInteractive) {
clearConsole();
}
@@ -136,39 +136,53 @@ function createCompiler({
});
let isFirstCompile = true;
- let tsMessagesPromise;
- let tsMessagesResolver;
+ let tsMessagesPromises = [];
- if (useTypeScript) {
- compiler.hooks.beforeCompile.tap('beforeCompile', () => {
- tsMessagesPromise = new Promise(resolve => {
- tsMessagesResolver = msgs => resolve(msgs);
- });
- });
+ masterCompiler.compilers.forEach((compiler, compilerIndex) => {
+ let tsMessagesResolver;
- forkTsCheckerWebpackPlugin
- .getCompilerHooks(compiler)
- .receive.tap('afterTypeScriptCheck', (diagnostics, lints) => {
- const allMsgs = [...diagnostics, ...lints];
- const format = message =>
- `${message.file}\n${typescriptFormatter(message, true)}`;
-
- tsMessagesResolver({
- errors: allMsgs.filter(msg => msg.severity === 'error').map(format),
- warnings: allMsgs
- .filter(msg => msg.severity === 'warning')
- .map(format),
+ if (useTypeScript) {
+ compiler.hooks.beforeCompile.tap('beforeCompile', () => {
+ tsMessagesPromises[compilerIndex] = new Promise(resolve => {
+ tsMessagesResolver = msgs => resolve(msgs);
});
});
- }
+
+ forkTsCheckerWebpackPlugin
+ .getCompilerHooks(compiler)
+ .receive.tap('afterTypeScriptCheck', (diagnostics, lints) => {
+ const allMsgs = [...diagnostics, ...lints];
+ const format = message =>
+ `${message.file}\n${typescriptFormatter(message, true)}`;
+
+ tsMessagesResolver({
+ errors: allMsgs.filter(msg => msg.severity === 'error').map(format),
+ warnings: allMsgs
+ .filter(msg => msg.severity === 'warning')
+ .map(format),
+ });
+ });
+ }
+ });
// "done" event fires when Webpack has finished recompiling the bundle.
// Whether or not you have warnings or errors, you will get this event.
- compiler.hooks.done.tap('done', async stats => {
+ masterCompiler.hooks.done.tap('done', async stats => {
if (isInteractive) {
clearConsole();
}
+ stats.compilation = {
+ errors: stats.stats.reduce(
+ (previousErrors, s) => [...previousErrors, ...s.compilation.errors],
+ []
+ ),
+ warnings: stats.stats.reduce(
+ (previousErrors, s) => [...previousErrors, ...s.compilation.warnings],
+ []
+ ),
+ };
+
// We have switched off the default Webpack output in WebpackDevServer
// options so we are going to "massage" the warnings and errors and present
// them in a readable focused way.
@@ -189,7 +203,14 @@ function createCompiler({
);
}, 100);
- const messages = await tsMessagesPromise;
+ const masterMessages = await Promise.all(tsMessagesPromises);
+ const messages = masterMessages.reduce(
+ (previousMessages, currentMessages) => ({
+ errors: [...previousMessages.errors, ...currentMessages.errors],
+ warnings: [...previousMessages.warnings, ...currentMessages.warnings],
+ }),
+ { errors: [], warnings: [] }
+ );
clearTimeout(delayedMsg);
if (tscCompileOnError) {
statsData.warnings.push(...messages.errors);
@@ -269,12 +290,12 @@ function createCompiler({
arg => arg.indexOf('--smoke-test') > -1
);
if (isSmokeTest) {
- compiler.hooks.failed.tap('smokeTest', async () => {
- await tsMessagesPromise;
+ masterCompiler.hooks.failed.tap('smokeTest', async () => {
+ await Promise.all(tsMessagesPromises);
process.exit(1);
});
- compiler.hooks.done.tap('smokeTest', async stats => {
- await tsMessagesPromise;
+ masterCompiler.hooks.done.tap('smokeTest', async stats => {
+ await Promise.all(tsMessagesPromises);
if (stats.hasErrors() || stats.hasWarnings()) {
process.exit(1);
} else {
@@ -283,7 +304,7 @@ function createCompiler({
});
}
- return compiler;
+ return masterCompiler;
}
function resolveLoopback(proxy) {
diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json
index 9b399e19792..e54ab586b56 100644
--- a/packages/react-dev-utils/package.json
+++ b/packages/react-dev-utils/package.json
@@ -1,6 +1,6 @@
{
- "name": "react-dev-utils",
- "version": "9.1.0",
+ "name": "@ouihelp/react-dev-utils",
+ "version": "9001000.0.0",
"description": "Webpack utilities used by Create React App",
"repository": {
"type": "git",
diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js
index e5a3e0b5374..c2a6a4f428a 100644
--- a/packages/react-scripts/config/paths.js
+++ b/packages/react-scripts/config/paths.js
@@ -81,6 +81,7 @@ module.exports = {
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
+ appServiceWorkerJs: resolveModule(resolveApp, 'src/service-worker.entry'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
appTsConfig: resolveApp('tsconfig.json'),
@@ -104,6 +105,7 @@ module.exports = {
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
+ appServiceWorkerJs: resolveModule(resolveApp, 'src/service-worker.entry'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
appTsConfig: resolveApp('tsconfig.json'),
@@ -139,6 +141,10 @@ if (
appPublic: resolveOwn('template/public'),
appHtml: resolveOwn('template/public/index.html'),
appIndexJs: resolveModule(resolveOwn, 'template/src/index'),
+ appServiceWorkerJs: resolveModule(
+ resolveOwn,
+ 'template/src/service-worker.entry'
+ ),
appPackageJson: resolveOwn('package.json'),
appSrc: resolveOwn('template/src'),
appTsConfig: resolveOwn('template/tsconfig.json'),
diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js
index f4391c39fb7..2b04bf10b86 100644
--- a/packages/react-scripts/config/webpack.config.js
+++ b/packages/react-scripts/config/webpack.config.js
@@ -23,7 +23,6 @@ const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const safePostCssParser = require('postcss-safe-parser');
const ManifestPlugin = require('webpack-manifest-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
-const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
@@ -147,7 +146,7 @@ module.exports = function(webpackEnv) {
return loaders;
};
- return {
+ const originalConfig = {
mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
// Stop compilation early in production
bail: isEnvProduction,
@@ -680,24 +679,6 @@ module.exports = function(webpackEnv) {
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
- // Generate a service worker script that will precache, and keep up to date,
- // the HTML & assets that are part of the Webpack build.
- isEnvProduction &&
- new WorkboxWebpackPlugin.GenerateSW({
- clientsClaim: true,
- exclude: [/\.map$/, /asset-manifest\.json$/],
- importWorkboxFrom: 'cdn',
- navigateFallback: publicUrl + '/index.html',
- navigateFallbackBlacklist: [
- // Exclude URLs starting with /_, as they're likely an API call
- new RegExp('^/_'),
- // Exclude any URLs whose last part seems to be a file extension
- // as they're likely a resource and not a SPA route.
- // URLs containing a "?" character won't be blacklisted as they're likely
- // a route with query params (e.g. auth callbacks).
- new RegExp('/[^/?]+\\.[^/]+$'),
- ],
- }),
// TypeScript type checking
useTypeScript &&
new ForkTsCheckerWebpackPlugin({
@@ -742,4 +723,59 @@ module.exports = function(webpackEnv) {
// our own hints via the FileSizeReporter
performance: false,
};
+
+ const serviceWorkerConfig = {
+ target: 'webworker',
+ mode: originalConfig.mode,
+ bail: originalConfig.bail,
+ devtool: originalConfig.devtool,
+ entry: { 'service-worker': paths.appServiceWorkerJs },
+ output: {
+ path: originalConfig.output.path,
+ pathinfo: originalConfig.output.pathinfo,
+ filename: 'sw.js',
+ publicPath: originalConfig.output.publicPath,
+ devtoolModuleFilenameTemplate:
+ originalConfig.output.devtoolModuleFilenameTemplate,
+ },
+ optimization: {
+ minimize: originalConfig.optimization.minimize,
+ minimizer: originalConfig.optimization.minimizer,
+ },
+ resolve: originalConfig.resolve,
+ resolveLoader: originalConfig.resolveLoader,
+ module: originalConfig.module,
+ plugins: [
+ new webpack.DefinePlugin(env.stringified),
+ useTypeScript &&
+ new ForkTsCheckerWebpackPlugin({
+ typescript: resolve.sync('typescript', {
+ basedir: paths.appNodeModules,
+ }),
+ async: isEnvDevelopment,
+ useTypescriptIncrementalApi: true,
+ checkSyntacticErrors: true,
+ resolveModuleNameModule: process.versions.pnp
+ ? `${__dirname}/pnpTs.js`
+ : undefined,
+ resolveTypeReferenceDirectiveModule: process.versions.pnp
+ ? `${__dirname}/pnpTs.js`
+ : undefined,
+ tsconfig: paths.appTsConfig,
+ reportFiles: [
+ '**',
+ '!**/__tests__/**',
+ '!**/?(*.)(spec|test).*',
+ '!**/src/setupProxy.*',
+ '!**/src/setupTests.*',
+ ],
+ watch: paths.appSrc,
+ silent: true,
+ // The formatter is invoked directly in WebpackDevServerUtils during development
+ formatter: isEnvProduction ? typescriptFormatter : undefined,
+ }),
+ ].filter(Boolean),
+ };
+
+ return [originalConfig, serviceWorkerConfig];
};
diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json
index a21817920a7..c2e6d55b386 100644
--- a/packages/react-scripts/package.json
+++ b/packages/react-scripts/package.json
@@ -1,6 +1,6 @@
{
- "name": "react-scripts",
- "version": "3.2.0",
+ "name": "@ouihelp/react-scripts",
+ "version": "3002000.0.0",
"description": "Configuration and scripts for Create React App.",
"repository": {
"type": "git",
@@ -29,6 +29,7 @@
"types": "./lib/react-app.d.ts",
"dependencies": {
"@babel/core": "7.6.0",
+ "@ouihelp/react-dev-utils": "9001000.0.0",
"@svgr/webpack": "4.3.2",
"@typescript-eslint/eslint-plugin": "^2.2.0",
"@typescript-eslint/parser": "^2.2.0",
diff --git a/packages/react-scripts/scripts/build.js b/packages/react-scripts/scripts/build.js
index 54e0d4b82aa..afbc04d9099 100644
--- a/packages/react-scripts/scripts/build.js
+++ b/packages/react-scripts/scripts/build.js
@@ -40,7 +40,7 @@ const paths = require('../config/paths');
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
-const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
+const FileSizeReporter = require('@ouihelp/react-dev-utils/FileSizeReporter');
const printBuildError = require('react-dev-utils/printBuildError');
const measureFileSizesBeforeBuild =
@@ -111,7 +111,7 @@ checkBrowsers(paths.appPath, isInteractive)
const appPackage = require(paths.appPackageJson);
const publicUrl = paths.publicUrl;
- const publicPath = config.output.publicPath;
+ const publicPath = config[0].output.publicPath;
const buildFolder = path.relative(process.cwd(), paths.appBuild);
printHostingInstructions(
appPackage,
@@ -124,9 +124,11 @@ checkBrowsers(paths.appPath, isInteractive)
err => {
const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true';
if (tscCompileOnError) {
- console.log(chalk.yellow(
- 'Compiled with the following type errors (you may want to check these before deploying your app):\n'
- ));
+ console.log(
+ chalk.yellow(
+ 'Compiled with the following type errors (you may want to check these before deploying your app):\n'
+ )
+ );
printBuildError(err);
} else {
console.log(chalk.red('Failed to compile.\n'));
diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js
index 6c2602f04ff..992ddacfcea 100644
--- a/packages/react-scripts/scripts/start.js
+++ b/packages/react-scripts/scripts/start.js
@@ -42,7 +42,7 @@ const {
createCompiler,
prepareProxy,
prepareUrls,
-} = require('react-dev-utils/WebpackDevServerUtils');
+} = require('@ouihelp/react-dev-utils/WebpackDevServerUtils');
const openBrowser = require('react-dev-utils/openBrowser');
const paths = require('../config/paths');
const configFactory = require('../config/webpack.config');
diff --git a/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js b/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js
index ebd93d7b667..b072e5a3e57 100644
--- a/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js
+++ b/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js
@@ -256,7 +256,7 @@ function verifyTypeScriptSetup() {
if (!fs.existsSync(paths.appTypeDeclarations)) {
fs.writeFileSync(
paths.appTypeDeclarations,
- `/// ${os.EOL}`
+ `/// ${os.EOL}`
);
}
}
diff --git a/packages/react-scripts/template-typescript/src/index.tsx b/packages/react-scripts/template-typescript/src/index.tsx
index 87d1be55189..395b74997b2 100644
--- a/packages/react-scripts/template-typescript/src/index.tsx
+++ b/packages/react-scripts/template-typescript/src/index.tsx
@@ -2,11 +2,5 @@ import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
-import * as serviceWorker from './serviceWorker';
ReactDOM.render(, document.getElementById('root'));
-
-// If you want your app to work offline and load faster, you can change
-// unregister() to register() below. Note this comes with some pitfalls.
-// Learn more about service workers: https://bit.ly/CRA-PWA
-serviceWorker.unregister();
diff --git a/packages/react-scripts/template-typescript/src/service-worker.entry.ts b/packages/react-scripts/template-typescript/src/service-worker.entry.ts
new file mode 100644
index 00000000000..ec9c52b86d7
--- /dev/null
+++ b/packages/react-scripts/template-typescript/src/service-worker.entry.ts
@@ -0,0 +1,2 @@
+console.log('Inside service-worker.entry.ts');
+export {};
diff --git a/packages/react-scripts/template-typescript/src/serviceWorker.ts b/packages/react-scripts/template-typescript/src/serviceWorker.ts
deleted file mode 100644
index 15d90cb81a1..00000000000
--- a/packages/react-scripts/template-typescript/src/serviceWorker.ts
+++ /dev/null
@@ -1,143 +0,0 @@
-// This optional code is used to register a service worker.
-// register() is not called by default.
-
-// This lets the app load faster on subsequent visits in production, and gives
-// it offline capabilities. However, it also means that developers (and users)
-// will only see deployed updates on subsequent visits to a page, after all the
-// existing tabs open on the page have been closed, since previously cached
-// resources are updated in the background.
-
-// To learn more about the benefits of this model and instructions on how to
-// opt-in, read https://bit.ly/CRA-PWA
-
-const isLocalhost = Boolean(
- window.location.hostname === 'localhost' ||
- // [::1] is the IPv6 localhost address.
- window.location.hostname === '[::1]' ||
- // 127.0.0.1/8 is considered localhost for IPv4.
- window.location.hostname.match(
- /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
- )
-);
-
-type Config = {
- onSuccess?: (registration: ServiceWorkerRegistration) => void;
- onUpdate?: (registration: ServiceWorkerRegistration) => void;
-};
-
-export function register(config?: Config) {
- if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
- // The URL constructor is available in all browsers that support SW.
- const publicUrl = new URL(
- (process as { env: { [key: string]: string } }).env.PUBLIC_URL,
- window.location.href
- );
- if (publicUrl.origin !== window.location.origin) {
- // Our service worker won't work if PUBLIC_URL is on a different origin
- // from what our page is served on. This might happen if a CDN is used to
- // serve assets; see https://github.com/facebook/create-react-app/issues/2374
- return;
- }
-
- window.addEventListener('load', () => {
- const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
-
- if (isLocalhost) {
- // This is running on localhost. Let's check if a service worker still exists or not.
- checkValidServiceWorker(swUrl, config);
-
- // Add some additional logging to localhost, pointing developers to the
- // service worker/PWA documentation.
- navigator.serviceWorker.ready.then(() => {
- console.log(
- 'This web app is being served cache-first by a service ' +
- 'worker. To learn more, visit https://bit.ly/CRA-PWA'
- );
- });
- } else {
- // Is not localhost. Just register service worker
- registerValidSW(swUrl, config);
- }
- });
- }
-}
-
-function registerValidSW(swUrl: string, config?: Config) {
- navigator.serviceWorker
- .register(swUrl)
- .then(registration => {
- registration.onupdatefound = () => {
- const installingWorker = registration.installing;
- if (installingWorker == null) {
- return;
- }
- installingWorker.onstatechange = () => {
- if (installingWorker.state === 'installed') {
- if (navigator.serviceWorker.controller) {
- // At this point, the updated precached content has been fetched,
- // but the previous service worker will still serve the older
- // content until all client tabs are closed.
- console.log(
- 'New content is available and will be used when all ' +
- 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
- );
-
- // Execute callback
- if (config && config.onUpdate) {
- config.onUpdate(registration);
- }
- } else {
- // At this point, everything has been precached.
- // It's the perfect time to display a
- // "Content is cached for offline use." message.
- console.log('Content is cached for offline use.');
-
- // Execute callback
- if (config && config.onSuccess) {
- config.onSuccess(registration);
- }
- }
- }
- };
- };
- })
- .catch(error => {
- console.error('Error during service worker registration:', error);
- });
-}
-
-function checkValidServiceWorker(swUrl: string, config?: Config) {
- // Check if the service worker can be found. If it can't reload the page.
- fetch(swUrl)
- .then(response => {
- // Ensure service worker exists, and that we really are getting a JS file.
- const contentType = response.headers.get('content-type');
- if (
- response.status === 404 ||
- (contentType != null && contentType.indexOf('javascript') === -1)
- ) {
- // No service worker found. Probably a different app. Reload the page.
- navigator.serviceWorker.ready.then(registration => {
- registration.unregister().then(() => {
- window.location.reload();
- });
- });
- } else {
- // Service worker found. Proceed as normal.
- registerValidSW(swUrl, config);
- }
- })
- .catch(() => {
- console.log(
- 'No internet connection found. App is running in offline mode.'
- );
- });
-}
-
-export function unregister() {
- if ('serviceWorker' in navigator) {
- navigator.serviceWorker.ready.then(registration => {
- registration.unregister();
- });
- }
-}
diff --git a/packages/react-scripts/template/src/index.js b/packages/react-scripts/template/src/index.js
index 87d1be55189..395b74997b2 100644
--- a/packages/react-scripts/template/src/index.js
+++ b/packages/react-scripts/template/src/index.js
@@ -2,11 +2,5 @@ import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
-import * as serviceWorker from './serviceWorker';
ReactDOM.render(, document.getElementById('root'));
-
-// If you want your app to work offline and load faster, you can change
-// unregister() to register() below. Note this comes with some pitfalls.
-// Learn more about service workers: https://bit.ly/CRA-PWA
-serviceWorker.unregister();
diff --git a/packages/react-scripts/template/src/service-worker.entry.js b/packages/react-scripts/template/src/service-worker.entry.js
new file mode 100644
index 00000000000..03632d7e104
--- /dev/null
+++ b/packages/react-scripts/template/src/service-worker.entry.js
@@ -0,0 +1 @@
+console.log('Inside service-worker.entry.js');
diff --git a/packages/react-scripts/template/src/serviceWorker.js b/packages/react-scripts/template/src/serviceWorker.js
deleted file mode 100644
index f8c7e50c201..00000000000
--- a/packages/react-scripts/template/src/serviceWorker.js
+++ /dev/null
@@ -1,135 +0,0 @@
-// This optional code is used to register a service worker.
-// register() is not called by default.
-
-// This lets the app load faster on subsequent visits in production, and gives
-// it offline capabilities. However, it also means that developers (and users)
-// will only see deployed updates on subsequent visits to a page, after all the
-// existing tabs open on the page have been closed, since previously cached
-// resources are updated in the background.
-
-// To learn more about the benefits of this model and instructions on how to
-// opt-in, read https://bit.ly/CRA-PWA
-
-const isLocalhost = Boolean(
- window.location.hostname === 'localhost' ||
- // [::1] is the IPv6 localhost address.
- window.location.hostname === '[::1]' ||
- // 127.0.0.1/8 is considered localhost for IPv4.
- window.location.hostname.match(
- /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
- )
-);
-
-export function register(config) {
- if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
- // The URL constructor is available in all browsers that support SW.
- const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
- if (publicUrl.origin !== window.location.origin) {
- // Our service worker won't work if PUBLIC_URL is on a different origin
- // from what our page is served on. This might happen if a CDN is used to
- // serve assets; see https://github.com/facebook/create-react-app/issues/2374
- return;
- }
-
- window.addEventListener('load', () => {
- const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
-
- if (isLocalhost) {
- // This is running on localhost. Let's check if a service worker still exists or not.
- checkValidServiceWorker(swUrl, config);
-
- // Add some additional logging to localhost, pointing developers to the
- // service worker/PWA documentation.
- navigator.serviceWorker.ready.then(() => {
- console.log(
- 'This web app is being served cache-first by a service ' +
- 'worker. To learn more, visit https://bit.ly/CRA-PWA'
- );
- });
- } else {
- // Is not localhost. Just register service worker
- registerValidSW(swUrl, config);
- }
- });
- }
-}
-
-function registerValidSW(swUrl, config) {
- navigator.serviceWorker
- .register(swUrl)
- .then(registration => {
- registration.onupdatefound = () => {
- const installingWorker = registration.installing;
- if (installingWorker == null) {
- return;
- }
- installingWorker.onstatechange = () => {
- if (installingWorker.state === 'installed') {
- if (navigator.serviceWorker.controller) {
- // At this point, the updated precached content has been fetched,
- // but the previous service worker will still serve the older
- // content until all client tabs are closed.
- console.log(
- 'New content is available and will be used when all ' +
- 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
- );
-
- // Execute callback
- if (config && config.onUpdate) {
- config.onUpdate(registration);
- }
- } else {
- // At this point, everything has been precached.
- // It's the perfect time to display a
- // "Content is cached for offline use." message.
- console.log('Content is cached for offline use.');
-
- // Execute callback
- if (config && config.onSuccess) {
- config.onSuccess(registration);
- }
- }
- }
- };
- };
- })
- .catch(error => {
- console.error('Error during service worker registration:', error);
- });
-}
-
-function checkValidServiceWorker(swUrl, config) {
- // Check if the service worker can be found. If it can't reload the page.
- fetch(swUrl)
- .then(response => {
- // Ensure service worker exists, and that we really are getting a JS file.
- const contentType = response.headers.get('content-type');
- if (
- response.status === 404 ||
- (contentType != null && contentType.indexOf('javascript') === -1)
- ) {
- // No service worker found. Probably a different app. Reload the page.
- navigator.serviceWorker.ready.then(registration => {
- registration.unregister().then(() => {
- window.location.reload();
- });
- });
- } else {
- // Service worker found. Proceed as normal.
- registerValidSW(swUrl, config);
- }
- })
- .catch(() => {
- console.log(
- 'No internet connection found. App is running in offline mode.'
- );
- });
-}
-
-export function unregister() {
- if ('serviceWorker' in navigator) {
- navigator.serviceWorker.ready.then(registration => {
- registration.unregister();
- });
- }
-}