Open msonowal opened 1 year ago
I have same issue trying to convert a Vite + Vue + Laravel project to PWA
-Following
same problem what to do?
@msonowal you can use globDirectory
on injectManifest
to change the build folder: you also need to move globPatterns
from workbox
to injectManifest
, check workbox-build documentation
It seems you are using TypeScript in your custom service worker, add type: 'module'
to your pwa devOptions
.
Here the reference: https://developer.chrome.com/docs/workbox/reference/workbox-build/#type-RequiredGlobDirectoryPartial
You'll need to also add outDir
on pwa options.
@userquin How about an fork with laravel + inertiajs integration with Vite-PWA support?
Has anyone got this working? For me, I'm not getting anything injected into the html - no service workers, no manifest...
VitePWA({
registerType: 'autoUpdate',
injectRegister: 'auto',
devOptions: {
enabled: true,
type: 'module',
},
manifest: {
name: 'My Awesome App',
short_name: 'MyApp',
description: 'My Awesome App description',
theme_color: '#ffffff',
icons: [
{
src: 'pwa-192x192.png',
sizes: '192x192',
type: 'image/png'
},
{
src: 'pwa-512x512.png',
sizes: '512x512',
type: 'image/png'
}
]
}
I'm sorry folks, I dont use laravel. can you provide folder structure?
Laravel projects are based on this and use the same folder structure https://github.com/laravel/laravel
Static files including js, vue files ect. are all put in the resources directory and then generated into the public/build/ folder by vite.
You can try to add this to pwa options:
plugins: [
VitePWA({
outDir: 'public/build',
})
],
You're kidding! Thank you, that's saved a lot of time.
For anyone else wondering, even though some files get generated in public/build you also need registerSW.js and workbox to be generated there - adding outDir: 'public/build',
does that.
It's still not auto injecting the script and manifest for me, but I've gotten around that by manually including them in the blade layout:
<link rel="manifest" href="/build/manifest.webmanifest">
<script src="/build/registerSW.js"></script>
@fredpedersen provide these pwa options:
plugins: [
VitePWA({
outDir: 'public/build',
scope: '/',
base: '/',
/* other options*/
manifest: {
id: '/',
scope: '/',
/* other options*/
}
})
],
@fredpedersen so the root/base for the app is /build
? can you change the build/dist folder in laravel?
@userquin the root of the app is /public
If the directory is like SERVER://public_html/public
the starting point of app will be in /public
only. So all favicons, will be located there.
@anburocky3 @fredpedersen can you try using this?
plugins: [
VitePWA({
outDir: 'public',
})
],
EDIT: this way you don't need to switch to manual injection, and you will be able to use VanillaJS virtual module for auto update and auto page reload.
You're kidding! Thank you, that's saved a lot of time.
For anyone else wondering, even though some files get generated in public/build you also need registerSW.js and workbox to be generated there - adding
outDir: 'public/build',
does that.It's still not auto injecting the script and manifest for me, but I've gotten around that by manually including them in the blade layout:
<link rel="manifest" href="/build/manifest.webmanifest"> <script src="/build/registerSW.js"></script>
Is there any way that, we can inject the script imports directly to our blade layout?
@anburocky3 @fredpedersen can you try using this?
plugins: [ VitePWA({ outDir: 'public', }) ],
I think, it is generating correctly, but it doesn't get inserted into app.blade.php
file. We have some directives like @vite()
which will import the js for us.
It will be cool, if it auto-imports the necessary scripts in our app.
FYI, this is the layout file: app.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title inertia>{{ config('app.name', 'Laravel') }}</title>
<meta name="csrf-token" content="{{ csrf_token() }}">
<!-- Scripts -->
@routes
@vite('resources/js/app.ts')
@inertiaHead
</head>
<body class="antialiased">
@inertia
</body>
</html>
Check my previous comment, I add EDIT entry: then in your layour you can just use in resources/js/app.ts
:
import { registerSW } from 'virtual:pwa-register'
/*other code*/
registerSW({ immediate: true })
For the web manifest you can use this another virtual virtual:pwa-info
:
import { pwaInfo } from 'virtual:pwa-info'
if (pwaInfo) {
const webManifest = pwaInfo.webManifest.linkTag
console.log(pwaInfo)
/* add link to head: webManifest is the link */
}
for example, we use it in SvelteKit layout: https://github.com/vite-pwa/sveltekit/blob/main/examples/sveltekit-ts/src/routes/%2Blayout.svelte
Based on suggestion, tried it. Here is the testing URL: https://jdskitchen.menuworkflow.com/
My Config:
VitePWA({
registerType: 'autoUpdate',
devOptions: {
enabled: true
},
// outDir: 'public/build',
outDir: 'public',
scope: '/',
base: '/',
includeAssets: ['favicon.ico', 'apple-touch-icon.png', 'masked-icon.svg'],
manifest: {
id: '/',
scope: '/',
name: 'MenuWorkflow',
short_name: 'MenuWorkflow',
description: 'Make order workflow ease.',
theme_color: '#ffffff',
icons: [
{
"src": "/img/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/img/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/img/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/img/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/img/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/img/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/img/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/img/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable any"
}
]
}
})
Issues found:
I mainly use PWA, to add this app in all native platforms. Is there any way, we can show This app is installable
, is there any view inbuild into this package?
@anburocky3 where is index.html
? if you are using /
instead, just add workbox.navigateFallback = '/'
to pwa options
From some testing:
import { pwaInfo } from 'virtual:pwa-info'
causes the service worker to get stuck on 'trying to install' and it never gets past this.
id: '/',
scope: '/',
also breaks it, saying trying to install regardless of manual or automatic injection
I now have a running and active service worker with manual injection and with:
outDir: 'public/build',
registerSW: true,
devOptions: {
enabled: true,
},
But it's throwing the error Uncaught (in promise) non-precached-url: non-precached-url :: [{"url":"index.html"}]
EDIT:
Scratch that it's working with workbox.navigateFallback = '/'
as above
@anburocky3 where is
index.html
? if you are using/
instead, just addworkbox.navigateFallback = '/'
to pwa options
I'm using Laravel app, as discussed above, the entry point of the app is in /public
From some testing:
import { pwaInfo } from 'virtual:pwa-info'
causes the service worker to get stuck on 'trying to install' and it never gets past this.id: '/', scope: '/',
also breaks it, saying trying to install regardless of manual or automatic injection
I now have a running and active service worker with manual injection and with:
outDir: 'public/build', registerSW: true, devOptions: { enabled: true, },
But it's throwing the error
Uncaught (in promise) non-precached-url: non-precached-url :: [{"url":"index.html"}]
EDIT: Scratch that it's working with
workbox.navigateFallback = '/'
as above
Can you share the entire config files, so it will be easy to understand.
@anburocky3 add it also on devOptions
@anburocky3 check the build folder and remove public/build/sw.js
and public/build/registerSW.js
virtual:pwa-info
dts: https://github.com/vite-pwa/vite-plugin-pwa/blob/main/info.d.ts
about virtual:pwa-info
you can check if present, if so, you can create the link manually, it was created to use it in meta framework integrations (SvelteKit and Astro)
https://github.com/vite-pwa/astro/blob/main/examples/pwa-prompt/src/layouts/DefaultLayout.astro#L31
Here's the full config at the moment:
VitePWA({
outDir: 'public',
scope: '/',
id: '/',
registerSW: true,
devOptions: {
enabled: true,
},
workbox: {
navigateFallback: '/',
},
manifest: {
name: "Codex",
short_name: "Codex",
theme_color: '#ffffff',
start_url: '/',
scope: '/',
id: '/',
icons: [
{
src: '/img/icons/android-chrome-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: '/img/icons/android-chrome-512x512.png',
sizes: '512x512',
type: 'image/png',
},
{
src: '/img/icons/android-chrome-512x512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'any maskable'
}
],
},
})
The current issue with that config is that it seems to be generating sw.js and workbox at /public
but registerSW.js and manifest at public/build
. The registerSW.js file references /public/build/sw.js
which doesn't exist
so Vite build is changed to public/build folder, revert outDir to public/build and remove sw.js, registerSW.js and workbox-*.js from public folder
@fredpedersen type error on this. How did you get rid of it?
With respect, @userquin if we register the registerSW
here, we don't need to have registerSW({immediate: true})
in resources/js/app.ts
right?
it is injectRegister: true
, and yes you can remove virtual:pwa-register
, but you're app will no auto reload page on auto update
so Vite build is changed to public/build folder, revert outDir to public/build and remove sw.js, registerSW.js and workbox-*.js from public folder
This semi works, however the root folder of laravel is /public
not public/build
which means all the files are at http://example.com/build/manifest.json and therefore the scope is limited to /build
too. Ideally we could get everything generated in the public dir
@anburocky3 sorry haven't seen that yet
that's a problem of mixing source and build folders in Vite, I'll check what we can do here to solve the problem: as I mention in some previous comment, the sw is inside build folder and the scope is /.
Maybe you can collect some info, I'll check later required changes to solve the problem:
configResolved
hook (you can check it on plugins/main.ts plugin here): just add a console.log for both entriesI'm pretty new to vite so I'm not sure how to do that. It looks like it's laravel-vite-plugin
that's moving everything to the /public/build folder however.
From the laravel vite plugin code:
/**
* The public subdirectory where compiled assets should be written.
*
* @default 'build'
*/
buildDirectory?: string;
It throws an error if it's manually set to '' or '/'.
Here's the full config at the moment:
VitePWA({ outDir: 'public', scope: '/', id: '/', registerSW: true, devOptions: { enabled: true, }, workbox: { navigateFallback: '/', }, manifest: { name: "Codex", short_name: "Codex", theme_color: '#ffffff', start_url: '/', scope: '/', id: '/', icons: [ { src: '/img/icons/android-chrome-192x192.png', sizes: '192x192', type: 'image/png', }, { src: '/img/icons/android-chrome-512x512.png', sizes: '512x512', type: 'image/png', }, { src: '/img/icons/android-chrome-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'any maskable' } ], }, })
The current issue with that config is that it seems to be generating sw.js and workbox at
/public
but registerSW.js and manifest atpublic/build
. The registerSW.js file references/public/build/sw.js
which doesn't exist
@fredpedersen Are you importing these manually or using script to automate this process?
<link rel="manifest" href="/build/manifest.webmanifest">
<script src="/build/registerSW.js"></script>
just try .
try setting outDir: '..'
in pwa options and injectRegister: false
, then add again virtual:register-pwa
@fredpedersen laravel will serve sw.js and workbox-*.js from public folder, no?
@anburocky3 is working for you? I mean, with your configuration
outDir appears to only effect the placement of sw.js and workbox-*.js. '..' just puts it in the parent directory of the main laravel app. These are in the right place with outDir:'public'. The issue is the location of registerSW and manifest.
Yep, laravel with serve from the public folder as /
@userquin I have couple of issues:
injectRegister: true
is not available and i have to use auto
or script
. registerSW
can't be found.
manifest.webmanifest
file. Been struck there. @fredpedersen are you importing manually or automatically?
import { pwaInfo } from 'virtual:pwa-info'
if (pwaInfo) { const webManifest = pwaInfo.webManifest.linkTag console.log(pwaInfo) / add link to head: webManifest is the link / }
m/vite-pwa/vite-plugin-pwa/blob/main/info.d.ts How to reference the types? Do we have inbuilt or should we create it and import it ourselves?
Update: Fixed with adding types
"vite-plugin-pwa/info"
totsconfig.json
I have found the problem: the web manifest is not being generate, we use generateBundle
hook and so Vite will copy to the build folder (it is the default in vite-plugin-laravel
), I'll try to check if we can fix this, maybe adding a new option or just detecting laravel plugin and changing the path.
Since laravel is mixing source and build folders vite base is not the same as laravel base: this plugin assuming root build dir is the same as base/scope path, and in that case this is not true.
m/vite-pwa/vite-plugin-pwa/blob/main/info.d.ts How to reference the types? Do we have inbuilt or should we create it and import it ourselves?
Add this line at top:
/// <reference types="vite-plugin-pwa/info" />
and/or to your tsconfig.json file in types:
"compilerOptions": {
/*other options*/
"types": ["vite/client", "vite-plugin-pwa/client", "vite-plugin-pwa/info"]
}
can you confirm serving sw.js from /build/sw.js
is working when registering it (confirm there is no errors in dev tools)?
4. @userquin Can i use DOM to insert the script tag inside the head?
yes
- @userquin Can i use DOM to insert the script tag inside the head?
yes
I tried to add it like this
if (pwaInfo) {
const webManifest = pwaInfo.webManifest.linkTag
/* add link to head: webManifest is the link */
document.head.appendChild(webManifest);
}
But since pwaInfo.webManifest
returns as string, can't able to use it directly on .appendChild()
which accepts the Node type.
you should create a link then use link.innerHtml = webManifest
@msonowal @fredpedersen @anburocky3
you should create a link the use
innerHtml = webManifest
I tried this, and its working cool
if (pwaInfo) {
const webManifest = pwaInfo.webManifest.href
/* add link to head: webManifest is the link */
const linkElement = document.createElement("link");
linkElement.setAttribute("rel", "manifest");
linkElement.setAttribute("href", webManifest);
document.head.appendChild(linkElement);
}
How about, we add an docs for future devs.?
@anburocky3 LGTM I'll add a new section, Integrations
in docs repo: I'll create a new branch and so you can contribute.
I use the fresh default laravel vite config which can be re-produced by creating a new project with laravel
and install jetstream with inertia stack.
Now try to configure the service worker and plugin, As per my tries and findings it generates the paths incorrectly which refers to the build folder.
This is my current vite config