简体   繁体   English

从 create-react-app 中的 service worker 缓存中排除 index.html

[英]exclude index.html from service worker cache in create-react-app

I have a reactJs app using create-react-app .我有一个使用create-react-appreactJs应用程序。 The app uses service-worker and other PWA features but somehow I am seeing that despite updating the website or deploying a new build, chrome always picks index.html from service worker and does not make a network call at all.该应用程序使用service-worker和其他 PWA 功能,但不知何故,尽管更新了网站或部署了新版本,chrome 总是从 service worker 中选择index.html并且根本不进行网络调用。

I think caching the index.html using the service worker is the issue but have not been able to exclude it from getting cached, I did check a few questions on SO and issues on github but could not get a fix for this.我认为使用服务工作者缓存 index.html 是问题,但无法将其排除在缓存之外,我确实检查了一些关于 SO 的问题和 github 上的问题,但无法解决此问题。

I am using the default service-worker registration我正在使用默认的 service-worker 注册

registerServiceWorker.js registerServiceWorker.js

// In production, we register a service worker to serve assets from local cache.

// 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 the "N+1" visit to a page, since previously
// cached resources are updated in the background.


// This link also includes instructions on opting out of this behavior.

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 default function register() {

    if (/*process.env.NODE_ENV === 'production' &&*/ 'serviceWorker' in navigator) {
       // alert('found' + process.env.NODE_ENV);
        // The URL constructor is available in all browsers that support SW.
        const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
        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/facebookincubator/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. Lets check if a service worker still exists or not.
                checkValidServiceWorker(swUrl);
            } else {
                // Is not local host. Just register service worker
                registerValidSW(swUrl);
            }
        });


    } else {
        //alert('not found' + process.env.NODE_ENV);
    }
}

function registerValidSW(swUrl) {
    navigator.serviceWorker
        .register(swUrl)
        .then(registration => {

            registration.onupdatefound = () => {
                const installingWorker = registration.installing;

                installingWorker.onstatechange = () => {
                    if (installingWorker.state === 'installed') {
                        if (navigator.serviceWorker.controller) {
                            // At this point, the old content will have been purged and
                            // the fresh content will have been added to the cache.
                            // It's the perfect time to display a "New content is
                            // available; please refresh." message in your web app.
                            console.log('New content is available; please refresh.');
                        } 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.');
                        }
                    }
                };
            };
        })
        .catch(error => {
            console.error('Error during service worker registration:', error);
        });
}

function checkValidServiceWorker(swUrl) {
    // 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.
            if (
                response.status === 404 ||
                response.headers.get('Content-Type').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);
            }
        })
        .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();
        });
    }
}

Please help.请帮忙。

After trying multiple options, the one that worked best was not I was really willing to implement but could not find anything better. 在尝试了多种选择之后,最有效的选择不是我真的不愿意实施,但却找不到更好的选择。

From the service-worker.js file remove below lines service-worker.js文件中删除以下行

workbox.routing.registerNavigationRoute("/index.html", {

  blacklist: [/^\/_/,/\/[^\/]+\.[^\/]+$/],
});

This will not cache index.html and try to pull it every time from the server, though this does not sound best but does the trick. 尽管听起来并不是最好的方法,但它不会缓存index.html并尝试每次从服务器将其拉出。

If you have ejected from create-react-app you can go into /config/webpack.config.js and change the default arguments for GenerateSW() to the following: 如果您从create-react-app中退出,则可以进入/config/webpack.config.js并将GenerateSW()的默认参数更改为以下内容:

new WorkboxWebpackPlugin.GenerateSW({
          clientsClaim: true,
          exclude: [/\.map$/, /asset-manifest\.json$/, /index.html/],
          importWorkboxFrom: "cdn",
          navigateFallbackBlacklist: [
            // Exclude URLs starting with /_, as they're likely an API call
            new RegExp("^/_"),
            // Exclude URLs containing a dot, as they're likely a resource in
            // public/ and not a SPA route
            new RegExp("/[^/]+\\.[^/]+$")
          ]

This way you don't have to manually change your serviceworker.js after every building. 这样,您不必在每次构建后都手动更改serviceworker.js。

For people using InjectManifest instead of GenerateSW对于使用 InjectManifest 而不是 GenerateSW 的人

As you probably found out, the blacklist and navigateFallbackBlacklist options are not allowed with InjectManifest.正如您可能发现的那样,InjectManifest 不允许使用blacklistnavigateFallbackBlacklist选项。

My solution was to make a index-shell.html which can be cached and keep the original index.html out of the cache.我的解决方案是制作一个可以缓存的 index-shell.html 并将原始 index.html 保留在缓存之外。

new InjectManifest({
   include: [
      /index-shell\.html$/,
   ],
   exclude: [
      /index\.html$/,
   ],
   modifyURLPrefix: {'/public/': '/'}, // solved my routing issues with publicPath and what not...
   ...
})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Service Worker无法使用create-react-app - Service Worker not working with create-react-app 没有使用 create-react-app 获得服务人员 - Not getting service worker with create-react-app Create-React-App 应用程序中 index.html 和 index.js 之间的连接在哪里? - Where's the connection between index.html and index.js in a Create-React-App application? 我可以在没有 npm 启动和 npx create-react-app 的情况下使用 React 运行 index.html 吗? - Can I run index.html with React without npm start and npx create-react-app? React-snapshot 使用 create-react-app 和 serve 在所有路由上预渲染 index.html - React-snapshot pre-renders index.html on all routes with create-react-app and serve 服务工作者不会在'/'上缓存golang服务器提供的index.html - Service worker does not cache index.html served by golang server on '/' 如何将 create-react-app 与提供 index.html 的后端一起使用? - How to use create-react-app with a backend which serves index.html? reactjs create-react-app在src文件夹中缺少index.html - reactjs create-react-app missing index.html in src folder 服务工作者仅在添加“ index.html”时从缓存中获取URL。 - Service worker only fetches url from cache when adding “index.html” 如何使用 index.php 而不是 index.html 在 XAMP 上运行由 create-react-app 创建的 ReactApp? - How to run ReactApp created by create-react-app on XAMP using index.php rather than index.html?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM