I am working on NextJS app that runs next-pwa but only works on local environment. But when I deploy to vercel, it seems that sw.js is redundant. I spent so many hours on this but feel stuck anyway.
Here's my next.config.js
const { withPlugins } = require("next-compose-plugins");
const withPWA = require("next-pwa");
const runtimeCaching = require("next-pwa/cache");
const nextConfig = {
env: {
API_URL: "https://multikart-graphql-dun.vercel.app/server.js",
},
// if you want to run with local graphQl un-comment below one and comment the above code
// env: {
// API_URL: "http://localhost:4000/graphql",
// },
webpack(config, options) {
config.module.rules.push({
test: /\.svg$/,
issuer: {
test: /\.(js|ts)x?$/,
},
use: ["#svgr/webpack"],
});
return config;
},
};
module.exports = withPlugins(
[
[withImages],
[
withPWA,
{
// reactStrictMode: true,
pwa: {
dest: "public",
sw: "sw.js",
// swSrc: "service-worker.js",
// scope: "/",
// register: true,
// skipWaiting: true,
// buildExcludes: [/middleware-manifest.json$/],
},
},
],
],
[nextConfig]
);
and here's my manifest.json
{
"short_name": "App",
"name": "App: App",
"start_url": "/",
"display": "standalone",
"theme_color": "#b8d8e6",
"background_color": "#b8d8e6",
"prefer_related_applications": true,
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "/icons/imagedummy192.png",
"type": "image/png",
"sizes": "192x192",
"purpose": "any maskable"
},
{
"src": "/icons/imagedummy512.png",
"type": "image/png",
"sizes": "512x512"
}
]
}
I commented the rest of the config (runTimeCaching, skipWaiting, register), since it makes no difference
I have followed https://github.com/vercel/next.js/issues/30692 and https://github.com/shadowwalker/next-pwa/issues/295
I also have followed basic config on this repo: https://github.com/shadowwalker/next-pwa/tree/master/examples/minimal
I also did turn off the adblocker
but nothing seems to work, and sw.js always redundant
Can anybody help, What did I do wrong? 🙏
I found an answer to the question.
So to make the service worker works, I needed to build the service worker on production build ( npx next build ).
After the build complete, I remove the service worker on .gitignore to make it deployed to the repository.
And then voilaa.. the next-pwa works. Although, it needs 10 minutes for service worker success to build.
Related
I want to deploy a project that includes a React App as frontend (client/) and an Express API backend (api/) on vercel. I'm able to deploy the api but how can I deploy also the client?
My project structure:
-api/
-package.json
-index.js
-client/
-package.json
-public/...
-src/...
-vercel.json
My current vercel.json:
{
"version": 2,
"builds": [
{
"src": "./api/index.js",
"use": "#vercel/node"
},
// that is what I tried but it's not working:
{
"src": "./client/package.json",
"use": "#vercel/static-build"
}
// End of the non-functional code
],
"routes": [
{
"src": "api/.*",
"dest": "api/index.js"
},
// that is what I tried but it's not working:
{
"src": "client/build/static/.*",
"dest": "static/.*"
},
{
"src": "client/build/index.html",
"dest": "index.html"
}
// End of the non-functional code
]
}
I've seen at least 4 threads with the same problem and tried solutions from them, but none of them worked for me.
When I deploy my react app to firebase hosting I get blank page and a following error:
The only way to get it working is to empty cache and hard reload, but then reloading it again would cause exactly the same error.
I double checked my build html gets assets from correct folders using %PUBLIC_URL% as part of the routes in public/index.html
I also commented out manifest and the whole registering of the serviceWorker function, then rebuild it and deployed it, but I still have exactly the same problem.
At this point I'm a bit dumbfounded cause I think it was caused by whole caching system and now that I disabled it, it still remains so I don't know anymore how this whole thing actually works
My firebase.json
{
"hosting": {
"public": "build",
"site": "react-pukinn",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
],
"headers": [
{ "source":"/serviceWorker.js", "headers": [{"key": "Cache-Control", "value": "no-cache"}] }
]
}
}
My serviceWorker.js:
let CACHE_NAME = 'pukinn';
const urlsToCache = [
'/',
'/index.html',
];
self.addEventListener('install', (event) => {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
self.addEventListener('fetch', (event) => {
event.respondWith(caches.match(event.request)
.then(function(response) {
if (response) {
return response;
}
return fetch(event.request);
})
);
});
self.addEventListener('install', (event) => {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
self.skipWaiting();
});
manifest.json
{
"short_name": "Púkinn",
"name": "Púkinn",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "icons/knight_demon-192x192-min.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "icons/knight_demon-512x512-min.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": "index.html",
"display": "standalone",
"theme_color": "#ed1c24",
"background_color": "#212121"
}
I found the problem. My serviceWorker.js file was in the root of the project instead of my ./src folder. So what happed is that on build it did not include it into build folder that is used for hosting.
Really dumb mistake on my part.
I have react + webpack app
My manifest.webmanifest
{
"name": "x",
"short_name": "x",
"start_url": "./index.html",
"display": "fullscreen",
"background_color": "white",
"theme_color": "white",
"icons": [
{
"src": "favicon-16x16.png",
"type": "image/png",
"sizes": "16x16"
},
{
"src": "favicon-32x32.png",
"type": "image/png",
"sizes": "32x32"
}
]
}
Index.html
<link crossorigin="use-credentials" rel="manifest" href="manifest.webmanifest" />
I tried different combination but always get error in Chorome (at localhost):
Line: 1, column: 1, Syntax error;
In which folder should manifest.webmanifest be? (src, public, public/img ????) index.html is in src folder
What to write in href in index.html? (href="manifest.webmanifest", href="./manifest.webmanifest" ???)
What to write in 'start_url' in manifest.webmanifest?
Where to store favicon-16x16.png and favicon-32x32.png (src, public ???)
What to write in icons src in manifest.webmanifest
"icons": [
{
"src": ?????????,
"type": "image/png",
"sizes": "16x16"
},
Do I need to write something additional in the settings of Webpack?
I found the answer!))
The problem was that Webpack does not include manifest.webmanifest and icons img in result bundle. We need do it manually, writing the necessary paths in Webpack config:
add const CopyWebpackPlugin = require('copy-webpack-plugin'); at webpack.config.js
...
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, 'src/manifest.webmanifest'),
to: path.resolve(__dirname, 'build'),
},
{
from: path.resolve(__dirname, 'public/img/icons/'),
to: path.resolve(__dirname, 'build/icons/'),
},
],
}),
...
now all images and manifest.webmanifest are in result build folder!
I have been following a lot of tutorials of how to install workbox-webpack-plugin but I haven't succesfully managed to install it correctly. The service worker appears to be installing but its installing in the dist folder of my app (This is my webpacks output path). I think there's nothing wrong with this but when I run my app, there are no errors but the service worker is not functioning and I notice that it is being installed at localhost:8080/dist (The output path) and even if I try to run it in a heroku free server it gets installed at the url "https://myherokuapp.com/dist" (The same output path) I can't find a way to fix and think this might be related with another webpack module?
Here's my webpack config:
module.exports = (env) => {
const isProduction = env === 'production';
const CSSExtract = new ExtractTextPlugin('styles.css');
return {
entry: ['babel-polyfill', './src/app.js'],
output: {
path: path.join(__dirname, 'public', 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
loader: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/
}, {
test: /\.s?css$/,
use: CSSExtract.extract({
use: [
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
})
}]
},
plugins: [
CSSExtract,
new webpack.DefinePlugin({
'process.env.FIREBASE_API_KEY': JSON.stringify(process.env.FIREBASE_API_KEY),
'process.env.FIREBASE_AUTH_DOMAIN': JSON.stringify(process.env.FIREBASE_AUTH_DOMAIN),
'process.env.FIREBASE_DATABASE_URL': JSON.stringify(process.env.FIREBASE_DATABASE_URL),
'process.env.FIREBASE_PROJECT_ID': JSON.stringify(process.env.FIREBASE_PROJECT_ID),
'process.env.FIREBASE_STORAGE_BUCKET': JSON.stringify(process.env.FIREBASE_STORAGE_BUCKET),
'process.env.FIREBASE_MESSAGING_SENDER_ID': JSON.stringify(process.env.FIREBASE_MESSAGING_SENDER_ID)
}),
new CopyWebpackPlugin([
{
from: './public/index.html',
to: 'index.html'
}
]),
new WorkboxPlugin.InjectManifest({
swSrc: './public/sw.js',
swDest: 'service-worker.js'
})
],
devtool: isProduction ? 'source-map' : 'inline-source-map',
devServer: {
contentBase: path.join(__dirname, 'public'),
historyApiFallback: true,
publicPath: '/dist/'
}
};
};
The service worker I am providing to workbox at swSrc:
workbox.routing.registerNavigationRoute('https://my-app123.herokuapp.com/dashboard');
workbox.skipWaiting();
workbox.precaching.precacheAndRoute(self.__precacheManifest);
And my manifest:
{
"dir": "ltr",
"lang": "ES",
"name": "PWAPRB",
"icons": [
{
"src": "/images/icons/app-icon-48x48.png",
"type": "image/png",
"sizes": "48x48"
},
{
"src": "/images/icons/app-icon-96x96.png",
"type": "image/png",
"sizes": "96x96"
},
{
"src": "/images/icons/app-icon-144x144.png",
"type": "image/png",
"sizes": "144x144"
},
{
"src": "/images/icons/app-icon-192x192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "/images/icons/app-icon-256x256.png",
"type": "image/png",
"sizes": "256x256"
},
{
"src": "/images/icons/app-icon-384x384.png",
"type": "image/png",
"sizes": "384x384"
},
{
"src": "/images/icons/app-icon-512x512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"display": "standalone",
"start_url": "https://my-app123.herokuapp.com/dashboard",
"scope": ".",
"short_name": "PRBW",
"theme_color": "#204080",
"orientation": "any",
"background_color": "#204080",
"related_applications": [],
"prefer_related_applications": false
}
And here is the registration from the SW where I see that its installed in the /dist url
I really appreciate any help since I'm very new to webpack and workbox and I'm completely stuck. Thank you all!!.
The problem is the scope of your Service Worker. Because the sw is inside dist/, it can only control requests to resources inside the /dist/` folder.
I'd recommend using HTMLWebpackPlugin for your index.html which would then be processed by Webpack and ends up in the dist/, and then you'd deploy your dist/ folder
We are using Extjs 6 and we are using sencha cmd to build our application.
We are facing one issue. Every time we release production version of our application like 6.3 to 6.4, bundled app.js does not get updated and browser take that file from (from disk cache). So every time we have to tell our users that please clear your browser's cache after you got new release. That's annoying.
This is my app.json file.
"output": {
"base": "${workspace.build.dir}/${build.environment}/${app.name}",
"page": "index.html",
"manifest": "${build.id}.json",
"js": "${build.id}/.js",
"appCache": {
"enable": false,
"update": "full"
},
"resources": {
"path": "${build.id}/resources",
"shared": "resources"
}
},
"production": {
"output": {
"appCache": {
"enable": false,
"path": "cache.appcache"
}
},
......
"cache": {
"enable": false
}
...
Here are two options to solve your issue:
Customize app.js filename
{
"production": {
"output": {
"js": "${build.id}/app_${build.timestamp}.js"
},
"cache": {
"enable": true
},
"js": [
{
"path": "${build.id}/app.js",
"bundle": true,
"includeInBundle": false
}
],
"output": {
"base": "${workspace.build.dir}/${build.environment}/${app.name}",
"page": "index.html",
"manifest": "${build.id}.json",
"js": "${build.id}/app_${app.version}.js",
"appCache": {
"enable": false,
"update": "full"
},
"resources": {
"path": "${build.id}/resources",
"shared": "resources"
}
}
}
With this, you get every time you build your app an new file name for app.js.
Add static cache parameter
{
"production": {
"loader": {
"cache": "${build.timestamp}"
},
"cache": {
"enable": true
}
}
}
With this solution ExtJs will append a ?_dc=12345678 parameter to the app.js request. This parameter stays the same until your next build.
I have found solution:
"js": [
{
"path": "app.js",
"bundle": true,
"includeInBundle": false
}
],
.....
"output": {
"base": "${workspace.build.dir}/${build.environment}/${app.name}",
"page": "index.html",
"manifest": "${build.id}.json",
"js": "${build.id}/app_${app.version}.js",
"appCache": {
"enable": false,
"update": "full"
},
"resources": {
"path": "${build.id}/resources",
"shared": "resources"
}
},
....
This will not include app.js file in production build and create new app.js file with version appended at last to it like: app_6.4.js.