sw-precache-webpack-plugin icon indicating copy to clipboard operation
sw-precache-webpack-plugin copied to clipboard

wepback public path make index.html cache not working.

Open lili21 opened this issue 7 years ago • 27 comments

  • [x] I'm submitting a bug report
  • [ ] I'm submitting a feature request
  • [ ] I'm submitting a support request

webpack version: 2.2.1

sw-precache-webpack-plugin version: 0.9.2

Please tell us about your environment: OSX 10.12.4

Browser: [Chrome 58.0.3029.110 (64-bit)]

Current behavior:

// webpack.config.js
...
output: {
  publichPath: 'https://cdn.com/'
},
...
plugins: [
  new SWPrecacheWebpackPlugin({
    filename: 'sw.js',
    staticFileGlobsIgnorePatterns: [/\.map$/]
  })
]
//sw.js
...
var precacheConfig = [
  ['https://cdn.com/index.html', '1927d0eabd7c5d5d786731cf24b2675b']
...

That https://cdn.com/index.html make the index.html cache won't work. Cause the request url won't match.

Expected/desired behavior: index.html can be cached properly.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem along with your:

  • Webpack configuration:
// webpack.config.js
...
output: {
  publichPath: 'https://cdn.com/'
},
...
plugins: [
  new SWPrecacheWebpackPlugin({
    filename: 'sw.js',
    staticFileGlobsIgnorePatterns: [/\.map$/]
  })
]
  • Generated service worker (not minified):
//sw.js
...
var precacheConfig = [
  ['https://cdn.com/index.html', '1927d0eabd7c5d5d786731cf24b2675b']
...

lili21 avatar Jun 01 '17 10:06 lili21

So index.html is not caching as you would like? Is it generated by webpack (using a loader like html-webpack-plugin)?

goldhand avatar Jun 01 '17 15:06 goldhand

no and yes. user visit https://example.com/, the request url will be https://example.com/, and service worker will check https://example.com/ and https://eample.com/index.html , apparently, none of this will match https://cdn.com/index.html. so no, index.html is not caching as I would like, it not caching at all.

yes, it is generated by html-webpack-plugin.

lili21 avatar Jun 01 '17 16:06 lili21

Related: https://github.com/facebookincubator/create-react-app/pull/2432

(I'm not sure this is a supported use case.)

jeffposnick avatar Jun 02 '17 20:06 jeffposnick

I thought only service worker need to be same origin. right ?

lili21 avatar Jun 03 '17 00:06 lili21

I got the same issue with @lili21. All of my files is cached, but my webpack public path is directed to the other URL as explained by @lili21. So I can't refresh my page while offline because my index file is pointed to cdn.

I've read @jeffposnick reference, but still can't find any solution. What he actually did is comparing the public path and the origin then if it is different, dissable the Service Worker.

It is useless. My goal is to make this SW works no matter if the public path and the origin is different. Is there any way to overwrite the SW generated by sw-precache-webpack-plugin? so my index file can be cache correctly (not using webpack public path).

I've tried to overwrite my service worker generated by sw-precache-webpack-plugin manually from http://cdn.com/index.html to index.html and the offline mode works well, but I can't make it that way since it won't be efficient if we should maintain our service worker file manually everytime someone re-build our app.

darrylsepeda avatar Jun 13 '17 13:06 darrylsepeda

@darrylsepeda to clarify: Your index.html is hosted at the same url as your website example.com/index.html and your other assets and webpack.public_path are cdn.com/assets/

Since index.html is at example.com (and not cdn.com) service worker is not caching the index.html correctly.

goldhand avatar Jun 13 '17 15:06 goldhand

@goldhand yes, thats right. And if we change the cdn.com/index.html to index.html in service worker that generated by sw-precache-webpack-plugin, the index.html is cached by service worker correctly.

I thought we can add if file index.html, then don't add the webpack public path. So the service worker will have:

var precacheConfig = [
  ['/index.html', 'http://cdn.com/bla.1927d0eabd7c5d5d786731cf24b2675b.js']

darrylsepeda avatar Jun 14 '17 01:06 darrylsepeda

Seems like a legitimate feature request, will think about an api for this unless you have a suggestion @darrylsepeda

goldhand avatar Jun 14 '17 14:06 goldhand

@goldhand please kindly check my code? I tried to edit the part when sw-precache-webpack concat webpack public path with the filename. https://github.com/goldhand/sw-precache-webpack-plugin/pull/88

darrylsepeda avatar Jun 15 '17 11:06 darrylsepeda

My solution still wrong.. I'm still trying to solve it

darrylsepeda avatar Jun 20 '17 04:06 darrylsepeda

Finally I found the workaround for this.

I took out the compiled file from this plugin (located in lib folder) and put in somewhere in my project folder, then I replace the compiled string contained index.html (after line 218):

218 return _swPrecache2.default.generate(this.workerOptions).then(function (serviceWorkerFileContents) {
219         var newSW = serviceWorkerFileContents.replace(/\/(prod|stag|dev)\/index.html)/g, '/index.html');

then I change the webpack.config.js file to import the sw-precache-webpack from the updated file: const SWPrecacheWebpackPlugin = require('./additional/sw-precache-webpack')

This is the workaround since I need it to be done a few days ago.

darrylsepeda avatar Jun 22 '17 08:06 darrylsepeda

👍 For exposing an API for handling this use case. I have the exact same need as well. Some assets come from a CDN while some (index.html) need to come from the applications url.

erictaylor avatar Jun 24 '17 08:06 erictaylor

So what will that look like?

/**
 * API
 */
publicPathsMap: {
  [bundle: string]: [publicUrl: sring],
} 

/**
 * Example
 */
import SWPrecacheWebpackPlugin from 'sw-precache-webpack-plugin';
const CDN_URL =  'https://cdn.com/';  // notice the ending slash
const WEBSITE_URL = 'https://website.com/';

module.exports = {
  ...
  plugins: [
    new SWPrecacheWebpackPlugin({
      publicPathsMap: {
        main: CDN_URL,
        index: WEBSITE_URL,
        vendor: CDN_URL,
      },
    }),
  ],
}

Maybe that...?

goldhand avatar Jun 25 '17 08:06 goldhand

Well I know I've kinda hacked around this limitation temporarily by running a script that modifies the outputted file and replaces the https://cdn.com/index.html line with just /index.html. I haven't had a need for anything outside of needing to change the url for the index.html, everything else is pushed and loaded from the CDN.

Based on my assumption of your proposal above, I assume you are saying that you'd map the output from CommonChunks?

In my use case I'm using the HtmlWebpackPlugin to generate my index.html how would that work?

erictaylor avatar Jun 25 '17 18:06 erictaylor

Is the only use for index.html? If that's the case, and it's certain, then we don't need to worry about much of an api. If there are other use cases, we probably want something more customizable.

I think my suggestion was assuming we could reference the bundles that we wanted. Maybe using the filepath instead of the bundle as the key.

publicPathsMap: {
  [filepath: string]: [publicUrl: sring],
} 

Example:

publicPathsMap: {
  [path.resolve(__dirname, 'src/index.html')]: '/',
} 

goldhand avatar Jun 25 '17 23:06 goldhand

I mean my use cases so far have only needed the index.html because everything else goes goes to one CDN, but I could see the potential for being able to specify things by bundle ¯\(ツ)

erictaylor avatar Jun 26 '17 01:06 erictaylor

new SWPrecacheWebpackPlugin({
      cacheId: 'fancy',
      filename: 'service-worker.js',
      // staticFileGlobs: ['dist/**/*.{js,html,css}'],
      staticFileGlobs: ['dist/index.html'],
      staticFileGlobsIgnorePatterns:[/\.map$/],
      // minify: true, todo: close in deploy
      mergeStaticsConfig:true,
      stripPrefix: 'dist/'
    })

it will output index.html alone image

hodor-cn avatar Jun 29 '17 01:06 hodor-cn

@hodor-cn not alone, Your configuration will only output index.html.

lili21 avatar Jun 29 '17 02:06 lili21

var precacheConfig = [
  ["//cdn.com/dist/css/app.8e50af800688ab69cf8da5b9a0ba053c.css","8e50af800688ab69cf8da5b9a0ba053c"],
  ["//cdn.com/dist/favicon.ico","c03bce8a8efaa811e1d6e32c88930d67"],
  ["//cdn.com/dist/index.html","4dabed415bcd6573e160078d66f551f7"],
  ["//cdn.com/dist/js/app.dbb6850538e27a599b90.js","013824ccba8972cf4798311695251ec3"],
  ["//cdn.com/dist/js/manifest.77931f469b723c419d9c.js","a51944eb0bc6250959940a6292bd6468"],
  ["//cdn.com/dist/js/vendor.5953645b5f4b4a670ad7.js","288999c45126fbfa47aceb17bafe6101"],
  ["//cdn.com/dist/manifest.json","f6c47fe2e29257b16d81835eb1c6fcff"],
  ["//cdn.com/dist/touch-icon-115.png","7d1135731b1e1202bba0e639f5f87faf"],
  ["index.html","4dabed415bcd6573e160078d66f551f7"]];

@lili21 works fine in my case, the index.html is alone and other assets is in cdn image

hodor-cn avatar Jun 29 '17 03:06 hodor-cn

Huh, I guess the mergeStaticsConfig make it work. maybe ?

lili21 avatar Jun 29 '17 03:06 lili21

@hodor-cn you're caching the index twice though with the same hash.

erictaylor avatar Jun 29 '17 04:06 erictaylor

@Psiablo i won't use the path //cdn.com/dist/index.htmlindex.html is use in another domain's root such as 'https://a.com'

hodor-cn avatar Jun 29 '17 04:06 hodor-cn

@hodor-cn, well done, that looks good to me! :smile:

mergeStaticsConfig:true,
staticFileGlobs: ['dist/index.html'],
stripPrefix: 'dist/'

Will add instructions to README and close this? Or is this still an issue?

goldhand avatar Jun 29 '17 16:06 goldhand

The purist in me says this is still an issue because in @hodor-cn's case you are caching or attempting to cache a duplicate that is never used or consumed.

["//cdn.com/dist/index.html","4dabed415bcd6573e160078d66f551f7"], shouldn't even be in there if its never used.

erictaylor avatar Jun 29 '17 16:06 erictaylor

I experience something similar. I am producing my index with the html-webpack-plugin and the generated file is at assets\index.html, with express route, the routing is basically /index.html => /assets/index.html. When using the precache-plugin, the /assets/index.html is cached, as it should, but when users offline refreshes the page, the "offline" page is displayed, since /index.html is not cached, but /assets/index.html is.

My current config:

new SWPrecacheWebpackPlugin({
  cacheId: 'da-project',
  filename: 'da-project-sw.js',
  minify: true,
  maximumFileSizeToCacheInBytes: 3500000,
  filepath: path.join(assetsDir, '/da-project-sw.js'),
  staticFileGlobs: [
    'dist/assets/*.{json,webmanifest}',
    'dist/assets/*.css',
    'dist/assets/*.{ttf,woff,woff2,eof}',
    'dist/assets/*.js',
    'dist/assets/*.map',
    'dist/assets/*.html',
    'dist/assets/*.{png,jpg,jpeg,ico,gif,svg}'
  ],
  staticFileGlobsIgnorePatterns: [/da-project-sw\.js$/i],
  stripPrefixMulti: {
    'dist/assets/': 'assets/'
  },
  navigateFallback: '/index.html'
})

How do I make sure the index.html-file is cached as /index.html and not /assets/index.html ?

Basically, something like this would be nice:

stripPrefixMulti: {
  'dist/assets/': 'assets/',
  'dist/assets/index.html': 'index.html'
},

phun-ky avatar Nov 27 '17 14:11 phun-ky

Any solution for this case ?

erdoganoksuz avatar Apr 06 '18 11:04 erdoganoksuz

@erdoganoksuz I don't know if it helps your issue, but here is my working config:

new SWPrecacheWebpackPlugin({
  cacheId: 'da-project',
  filename: 'da-project-sw.js',
  minify: true,
  maximumFileSizeToCacheInBytes: 3500000,
  filepath: path.join(assetsDir, '/da-project-sw.js'),
  staticFileGlobs: ['dist/assets/index.html', 'dist/assets/down.html'],
  mergeStaticsConfig: true,
  runtimeCaching: [
    {
      urlPattern: /features\/all/,
      handler: 'networkFirst'
    },
    {
      urlPattern: /\/api\//,
      handler: 'networkFirst'
    }
  ],
  staticFileGlobsIgnorePatterns: [/da-project-sw\.js$/i],
  stripPrefix: 'dist/assets/',
  navigateFallback: '/index.html'
})

phun-ky avatar Apr 09 '18 06:04 phun-ky