You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Please tell us about your environment:
MacOS/Linux
Browser: iOS Safari
Current behavior:
After an update to my application (can be as small as editing text), iOS shows a blank screen after refreshing the page/launching the add-to-homescreen web app. After clearing Safari's cache, the application works again.
Note that I have set up sw-precache to make the application work offline completely. The app runs completely in the client, so all assets can be cached.
Expected/desired behavior:
I expect the updated version to function. I am aware that would require the service worker to check for updates on the server and use the cached version when the server's not available. I don't know how to configure that though.
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:
const PUBLIC_PATH = 'https://www.bigtimer.net/'; // For SW Precache. webpack needs the trailing slash for output.publicPath
const env = require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'),
publicPath: PUBLIC_PATH, // For SW Precache.
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to false will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to true because we are seeing that sourcemaps are included in the codesplit bundle as well when it's false,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
]),
// service worker caching
new SWPrecacheWebpackPlugin({
cacheId: 'big-timer',
filename: 'service-worker.js',
staticFileGlobs: ['dist/**/*.{js,html,css}'],
minify: true,
navigateFallback: PUBLIC_PATH,
stripPrefix: 'dist/',
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
})
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpack version:
3.12
sw-precache-webpack-plugin version:
0.11.5
Please tell us about your environment:
MacOS/Linux
Browser: iOS Safari
Current behavior:
After an update to my application (can be as small as editing text), iOS shows a blank screen after refreshing the page/launching the add-to-homescreen web app. After clearing Safari's cache, the application works again.
Note that I have set up sw-precache to make the application work offline completely. The app runs completely in the client, so all assets can be cached.
Expected/desired behavior:
I expect the updated version to function. I am aware that would require the service worker to check for updates on the server and use the cached version when the server's not available. I don't know how to configure that though.
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:
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
var SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin')
const PUBLIC_PATH = 'https://www.bigtimer.net/'; // For SW Precache. webpack needs the trailing slash for output.publicPath
const env = require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'),
publicPath: PUBLIC_PATH, // For SW Precache.
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to
false
will not extract CSS from codesplit chunks.// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to
true
because we are seeing that sourcemaps are included in the codesplit bundle as well when it'sfalse
,// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
'use strict'
var precacheConfig = [
['index.html', '277d4fc013034f1ce06a422f6feba69e'],
['service-worker.js', 'dd58fb74f7d4ad37db7d0ed0ade9858d'],
['static/404.html', '1b8119d030279687e0fae58aad5456b5'],
[
'static/css/app.9f44cebdd85d64e5f7283ddd7d7020fa.css',
'e3c073dabe268a54b64eea30dd70cefd'
],
[
'static/js/app.f2959bcb7abc904fbf43.js',
'96240dc4b7ddc3955b983d1e68d59b8d'
],
[
'static/js/manifest.28eddcffd035f5f85795.js',
'479b2f524fbd82c9ec2f28925b4e0521'
],
[
'static/js/vendor.25551477f25f30579d9c.js',
'69af8d0745788253d601840a8caad28b'
]
],
cacheName =
'sw-precache-v3-big-timer-' +
(self.registration ? self.registration.scope : ''),
ignoreUrlParametersMatching = [/^utm_/],
addDirectoryIndex = function(e, t) {
var n = new URL(e)
return '/' === n.pathname.slice(-1) && (n.pathname += t), n.toString()
},
cleanResponse = function(e) {
return e.redirected
? ('body' in e ? Promise.resolve(e.body) : e.blob()).then(function(t) {
return new Response(t, {
headers: e.headers,
status: e.status,
statusText: e.statusText
})
})
: Promise.resolve(e)
},
createCacheKey = function(e, t, n, r) {
var a = new URL(e)
return (
(r && a.pathname.match(r)) ||
(a.search +=
(a.search ? '&' : '') +
encodeURIComponent(t) +
'=' +
encodeURIComponent(n)),
a.toString()
)
},
isPathWhitelisted = function(e, t) {
if (0 === e.length) return !0
var n = new URL(t).pathname
return e.some(function(e) {
return n.match(e)
})
},
stripIgnoredUrlParameters = function(e, t) {
var n = new URL(e)
return (
(n.hash = ''),
(n.search = n.search
.slice(1)
.split('&')
.map(function(e) {
return e.split('=')
})
.filter(function(e) {
return t.every(function(t) {
return !t.test(e[0])
})
})
.map(function(e) {
return e.join('=')
})
.join('&')),
n.toString()
)
},
hashParamName = '_sw-precache',
urlsToCacheKeys = new Map(
precacheConfig.map(function(e) {
var t = e[0],
n = e[1],
r = new URL(t, self.location),
a = createCacheKey(r, hashParamName, n, !1)
return [r.toString(), a]
})
)
function setOfCachedUrls(e) {
return e
.keys()
.then(function(e) {
return e.map(function(e) {
return e.url
})
})
.then(function(e) {
return new Set(e)
})
}
self.addEventListener('install', function(e) {
e.waitUntil(
caches
.open(cacheName)
.then(function(e) {
return setOfCachedUrls(e).then(function(t) {
return Promise.all(
Array.from(urlsToCacheKeys.values()).map(function(n) {
if (!t.has(n)) {
var r = new Request(n, {credentials: 'same-origin'})
return fetch(r).then(function(t) {
if (!t.ok)
throw new Error(
'Request for ' +
n +
' returned a response with status ' +
t.status
)
return cleanResponse(t).then(function(t) {
return e.put(n, t)
})
})
}
})
)
})
})
.then(function() {
return self.skipWaiting()
})
)
}),
self.addEventListener('activate', function(e) {
var t = new Set(urlsToCacheKeys.values())
e.waitUntil(
caches
.open(cacheName)
.then(function(e) {
return e.keys().then(function(n) {
return Promise.all(
n.map(function(n) {
if (!t.has(n.url)) return e.delete(n)
})
)
})
})
.then(function() {
return self.clients.claim()
})
)
}),
self.addEventListener('fetch', function(e) {
if ('GET' === e.request.method) {
var t,
n = stripIgnoredUrlParameters(
e.request.url,
ignoreUrlParametersMatching
)
;(t = urlsToCacheKeys.has(n)) ||
((n = addDirectoryIndex(n, 'index.html')), (t = urlsToCacheKeys.has(n)))
!t &&
'navigate' === e.request.mode &&
isPathWhitelisted([], e.request.url) &&
((n = new URL('https://www.bigtimer.net/', self.location).toString()),
(t = urlsToCacheKeys.has(n))),
t &&
e.respondWith(
caches
.open(cacheName)
.then(function(e) {
return e.match(urlsToCacheKeys.get(n)).then(function(e) {
if (e) return e
throw Error(
'The cached response that was expected is missing.'
)
})
})
.catch(function(t) {
return (
console.warn(
'Couldn't serve response for "%s" from cache: %O',
e.request.url,
t
),
fetch(e.request)
)
})
)
}
})
The text was updated successfully, but these errors were encountered: