I am new to PWA and using Workbox; So I have this test folder with the following file structure, using localhost as my server (i.e. localhost/test)
index.html
test.css
test.jpg
test.js
sw.js (Code Shown below);
importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.0.0/workbox-sw.js');
if (workbox) {
console.log(`Yay! Workbox is loaded 🎉`);
} else {
console.log(`Boo! Workbox didn't load 😬`);
}
//precache all the site files
workbox.precaching.precacheAndRoute([
{
"url": "index.html",
"revision": "8e0llff09b765727bf6ae49ccbe60"
},
{
"url": "test.css",
"revision": "1fe106d7b2bedfd2dda77f06479fb676"
},
{
"url": "test.jpg",
"revision": "1afdsoaigyusga6d9a07sd9gsa867dgs"
},
{
"url": "test.js",
"revision": "8asdufosdf89ausdf8ausdfasdf98afd"
}
]);
Everything is working perfectly fine, Files are precached and I didn't get this regular offline message when I am in offline mode, as shown in the image below.
So, I copied the exact folder to have test-2 folder, then renamed my index.html file to to index.php and in my sw.js file I updated the url to below code
{
"url": "index.php",
"revision": "8e987fasd5727bf6ae49ccbe60"
},
- Please note that I changed the revision value too
I did this because I want to implement PWA using Workbox into my own custom built single page app (but its in .php format).
Coming to my browser to run localhost/test-2 (normal mode), my files were precached too, including my index.php file (no error messages in my console and service worker was working perfectly fine); Only for me to switch to (offline mode) in my source tab and refresh my browser to test the offline experience and Alas! I got this Offline Message as shown in the Image below :(
I don't know what went wrong, I have no Idea what happened and I tried to google out some reasons for days but I don't seem to get any right and corresponding answer. Most of the tutorials out there is with .html
So the question is how can I implement PWA with .php file, so that when the user is offline, they dont get the normal You're offline Message but Instead my webpage should render?
Thanks in Advance
To elaborate to #pate's answer.
Workbox by default tries to make sure that pretty URL's are supported out of the box.
So in the first example, you cached /test/index.html. So when you request /test/, Workbox precaching actually checks the precache for:
/test/
/test/index.html
If your page was /test/about.html, and you visited the page /test/about precache would append a .html and check for that.
When you switched to the .php extension this logic would suddenly no longer work.
There are a few options to get this working:
If you are using any of the workbox tools to build your manifest, you are use the templatedUrls feature to map to a file (More details here):
templatedUrls: {
'/test-2/': ['/test-2/index.php']
}
If you are making the precache list yourself server side, you can just tell it to precache the URL /test-2/ without the index.php and precaching will simply cache that. Please note that you must ensure the revision changes with any changes to index.php.
If you aren't making the precache manifest, you can use urlManipulaion option to tell precache to check for URL's, (More details here):
workbox.precaching.precacheAndRoute(
[
.....
],
{
urlManipulaion: ({url}) => {
// TODO: Check if the URL ends in slash or not
// Add index.php based on this.
return [url, `${url}.php`, `${url}index.php`];
}
}
);
This is most likely because in the error showing screenshot you're trying to access test-2/ instead of test-2/index.php.
Workbox, in the background, falls back to trying index.html for every route that ends in a slash. For this reason, even if you don't have "/" cached SW tries to give you "/" + "index.html" which seems to be cached, and the page works offline.
I bet your page works if you try to access test-2/index.php while offline. Does it?
Related
I am trying to import a json file from a website using p5.js, and i thought it would be quite easy, however when i tried it i realized the json was actually just in plain text on the page (It is the only thing on the page). I checked chrome web tools to look at index.html, but i was greeted by "(index)", is it a problem with google or am i just going to have to use something else than this?
function preload() {
httpGet('leaderboard.popcat.click', 'json', function(response) {
});
}
//there are the setup and draw functions aswell
I got an error when i ran the code aswell, it was
Error: JSONP request to url failed
here is a picture of the page btw, (the url is leaderboard.popcat.click)
EDIT: The main problem i am having is that there is no file in https://leaderboard.popcat.click/, not the getting of json.
The network tab says no such url exists, and i believe that is because of the fact that i didn't specify a file.
Here is the console output aswell
I solved my issue by starting chrome in no-cors mode or whatever it's called AND using the full path of the website. I got it into no-cors mode by making a shortcut with this link
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir=~/chromeTemp"
and running it as an administrator
I have a JSON file. It runs successfully for the first time. But when I update something in my json file, that update is not showing in my webpage. Only the old data is showing. I tried to refresh page several times, but its not working.
I am using xampp local server for and ajax for my code to call json data.
Please help.
My JSON file
[
{
"name": "Aseem",
"age":29,
"salary":50000
},
{
"name": "John",
"age":23,
"salary":53000
},
{
"name": "Erica",
"age":25,
"salary":52000
}
]
Often of the contents of something isn't refreshing, it is likely as a result of the cache. Web browsers cache content that is loaded over the network, to reduce future loading times and data required to load those resources.
You can test this yourself, by opening the Developer Tools in your browser (Ctrl+Shift+I in Google Chrome), go to the Network tab (or similar) and look for a tick box that says 'Disable cache'. Now if you refresh the page you should be able to see the updated version.
If you wanted to fix this programmatically, an easy way is to add a query to the end of the URL. Since this is technically a new URL, the browser will re-request the resource, but the query will be ignored by the webserver, so there's no side effect. An example of this can be seen below:
let noCache = Date.now().toString(16);
url = `${url}?noCache=${noCache}`;
// Make request with URL
check 2 points
1, ajax data is new?
2. clear your broswer cache and try it again.
I'm new to Vue and created a project with the PWA Service-worker plugin. After deploying a new version of my App I get these messages in console:
After refreshing the page (F5) these messages still appear the same way and the App is still in it's old state. I tried everything to clear the cache but it still won't load the new content.
I haven't changed anything from the default config after creating my project and didn't add any code which interacts with the serviceworker. What is going wrong? Am I missing something?
As I figured out, this question is really only related to beginners in PWA, which don't know that you can (and need) to configure PWA for achieving this. If you feel addressed now (and using VueJS) remember:
To automatically download the new content, you need to configure PWA. In my case (VueJS) this is done by creating a file vue.config.js in the root directory of my project (On the same level as package.json).
Inside this file you need this:
module.exports = {
pwa: {
workboxOptions: {
skipWaiting: true
}
}
}
Which will automatically download your new content if detected.
However, the content won't be displayed to your client yet, since it needs to refresh after downloading the content. I did this by adding window.location.reload(true) to registerServiceWorker.js in my src/ directory:
updated () {
console.log('New content is available: Please refresh.')
window.location.reload(true)
},
Now, if the Service Worker detects new content, it will download it automatically and refresh the page afterwards.
I figured out a different approach to this and from what I've seen so far it works fine.
updated() {
console.log('New content is available; please refresh.');
caches.keys().then(function(names) {
for (let name of names) caches.delete(name);
});
},
What's happening here is that when the updated function gets called in the service worker it goes through and deletes all the caches. This means that your app will start up slower if there is an update but if not then it will serve the cached assets. I like this approach better because service workers can be complicated to understand and from what I've read using skipWaiting() isn't recommend unless you know what it does and the side effects it has. This also works with injectManifest mode which is how I'm currently using it.
pass registration argument then use the update() with that.
the argument uses ServiceWorkerRegistration API
updated (registration) {
console.log('New content is available; please refresh.')
registration.update()
},
I am looking for a solution on how to create an offline compatible web app using html, JavaScript, and maybe jQuery. I looked into service workers, but they aren’t comparable with all mobile devices yet. I also looked at the manifest file thing, it worked but it didn’t update the files. So now I’m here asking for a solution. I intend this application to be a music website that can be a web app. I like music and i take it everywhere so I’m trying to find out how i can save the website files for offline use so even if I don’t have WiFi, i can listen to my saved music. btw the files I’d like to save are:
main.js
Main.css
Index.html
EDIT 1
Also, if you know how to properly use service workers, can you show an example?
For future reference:
1/ Create a service worker file in the app root folder.
Example sw.js:
let cacheName = "core" // Whatever name
// Pass all assets here
// This example use a folder named «/core» in the root folder
// It is mandatory to add an icon (Important for mobile users)
let filesToCache = [
"/",
"/index.html",
"/core/app.css",
"/core/main.js",
"/core/otherlib.js",
"/core/favicon.ico"
]
self.addEventListener("install", function(e) {
e.waitUntil(
caches.open(cacheName).then(function(cache) {
return cache.addAll(filesToCache)
})
)
})
self.addEventListener("fetch", function(e) {
e.respondWith(
caches.match(e.request).then(function(response) {
return response || fetch(e.request)
})
)
})
2/ Add an onload event anywhere in the app:
window.onload = () => {
"use strict";
if ("serviceWorker" in navigator && document.URL.split(":")[0] !== "file") {
navigator.serviceWorker.register("./sw.js");
}
}
3/ Create a manifest.json file in the app root folder.
{
"name": "APP",
"short_name": "App",
"lang": "en-US",
"start_url": "/index.html",
"display": "standalone"
}
4/ Test
Start a web server from the root folder:
php -S localhost:8090
Visit http://localhost:8090 one time.
Stop the web server with Ctrl + c.
Refresh http://localhost:8090, the page should respond.
To switch off when developing, remove the onload event, and in Firefox
visit about:debugging#workers to unregister the service.
Newest versions of Firefox are showing an application tab directly in the debugger instead. about:debugging#workers is not valid any more.
https://developer.mozilla.org/en-US/docs/Tools/Application/Service_workers
Source for more details
Manifest.json reference
If you need to save settings after the user left, you need to use cookies.
If you need some server data (and ajax requests for example), I'm afraid you can't do that offline.
For everything else (as far as I know), if you want it to work offline, you have to make the user's browser download all code it's going to use, including JQuery, Bootstrap, or any plugin code you want. You have to add them to your website sources and link them internally :
<script src="http://code.jquery.com/jquery-3-3-0-min.js"></script> <!-- Won't work offline.-->
<script src="./js/jquery-3-3-0-min.js"></script> <!-- Will work offline -->
Be careful about plugin dependencies ! For example Bootstrap 3.3.6 JS plugin needs JQuery 1.12.4
Hope it helps you !
I have a React web application that allows Image uploads.
After performing a fetch POST request for multiple images (in this case 6) to my API, the browser refreshes itself and reloads the current page. It is worth noting that this application allows images to be cropped and so for every image the user uploads there is a second image (cropped) to upload. So the above 6 images result in 12 POST requests.
The refresh behavior is INCONSISTENT and difficult to reproduce. I have inserted breakpoints within the function this behavior occurs. Using the chrome debugger tools I have stepped through the flow and found that the refresh occurs after this call.
this.ws.onmessage = function(e) {
debug('message event', e.data);
self.emit('message', e.data);
};
It is located inside the file websocket.js within the Library node_modules/react-dev-tools/node_modules/socketjs-client/lib/transport/websocket.js
I have narrowed it down to this file and ruled out any issues from my project codebase.
My theory is that the behavior of my application is triggering an external listener/case which is causing a full browser refresh.
I see that the file in question is inside react-dev-tools and thought that removing this module could solve the problem, however, this occurs in my production environment also and so I feel removing this could break the build.
Any thoughts as to better my investigation or potential solutions please are helpful.
I'm not sure how you're running your environments, but maybe this will help...
I ran into this exact issue and it took me 3 days (too long) to narrow it to nodemon (in development) and pm2 (in production). I'm not sure how you're serving your application/images, but for me, any time a new file was added, the service was intermittently restarted (sometimes it uploaded, sometimes it was cut off).
For development, I added a nodemon.json config file at the application root (nodemon app.js --config nodemon.json):
{
"ignore": ["uploads"]
}
For production, I created a prod.json at the application root and ran pm2 start prod.json:
{
"apps" : [{
"name" : "app-name",
"ignore_watch" : ["uploads"],
"script" : "./app.js",
"env": {
"NODE_ENV": "production"
}
}]
}
If you're using neither of the above packages, then I'd suggest looking into the possibility of reconfiguring how you're storing and serving images to the application (as a last resort).