vite-pwa / vite-plugin-pwa

Zero-config PWA for Vite
https://vite-pwa-org.netlify.app/
MIT License
3.2k stars 209 forks source link

Anyone with success implementing this in Vue2? #81

Closed hubert17 closed 3 years ago

hubert17 commented 3 years ago

I fortunately was able to create a production build of my supposed to be NO cli-node-webpack Vue project using Vite courtesy of this guy: https://www.mathew-paul.nz/posts/how-to-use-vue2-with-vite/

The simple Vue/Vuetify app can be serve with or without build process.
https://github.com/hubert17/GabsVuetifyNoCLINodeWebpack

I would like to turn this into PWA and I wonder if anyone here has success using vite-plugin-pwa with Vue 2.

Thanks.

userquin commented 3 years ago

@hubert17 I haven't tested on vue2, but should work, I'll give a try on, I'll push changes to my fork once tested:

https://github.com/hubert17/GabsVuetifyNoCLINodeWebpack

hubert17 commented 3 years ago

@userquin You are awesome man. I'll keep watching the fork. :) https://github.com/userquin/GabsVuetifyNoCLINodeWebpack

hubert17 commented 3 years ago

I don't match about Vue 3. I am stuck in here import { useRegisterSW } from 'virtual:pwa-register/vue'

Says.. Failed to resolve import "vue" from "............\@vite-plugin-pwa\virtual:pwa-register\vue". Does the file exist?

Here's my wild adventure: https://github.com/hubert17/GabsVuetifyNoCLINodeWebpack/blob/pwa-vue/src/components/ReloadPrompt.js

userquin commented 3 years ago

I don't match about Vue 3. I am stuck in here import { useRegisterSW } from 'virtual:pwa-register/vue'

Says.. Failed to resolve import "vue" from "............@vite-plugin-pwa\virtual:pwa-register\vue". Does the file exist?

Here's my wild adventure: https://github.com/hubert17/GabsVuetifyNoCLINodeWebpack/blob/pwa-vue/src/components/ReloadPrompt.js

You haven't installed any dependency... I will simplify a little the app to only show the app, without any page...

Just compare with your branch: missing vue, vuex, vue-router, vuetify and sass stuff from dev dependencies:

// package.json
{
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "serve": "vite preview"
  },
  "dependencies": {
    "vite-plugin-vue2": "^1.6.2",
    "vue": "^2.6.14",
    "vue-router": "^3.5.1",
    "vuetify": "^2.5.4",
    "vuex": "^3.6.2"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^1.2.3",
    "deepmerge": "^4.2.2",
    "sass": "^1.35.1",
    "sass-loader": "^12.1.0",
    "vite": "^2.3.7",
    "vite-plugin-pwa": "^0.8.1"
  }
}

About using virtual:pwa-register/vue right now it is not possible since its target is only for vue3, maybe we can take a look to use vue-demi allowing to be used also on vue2.

userquin commented 3 years ago

I will provide a mixin for vue2 and maybe added to the docs...

userquin commented 3 years ago

seem to work, just adding some images to work offline...

userquin commented 3 years ago

REVIEW ALL YOUR COMMENTS ON README.md, SINCE YOU NEED TO INSTALL SOME DEPENDENCIES AS DEV REVIEW package.json on my fork, I get a lot of warning using vuetify, I cannot spent time to see what happening with vuetify

Sorry for template after script in all vue files, this year I only work with script setup with typescript and is more usable ;). I cannot use the oldest style.

If you test both registerType options, when switching between them, go to chrome dev tools > Application > Storage and clean data for http://localhost:5000. Once data cleared, go to Application > Service workers and check the current sw is deleted (must appear with a gray dot and is redundant state).

Once you run first time, you need stop the server, do some change in same place, then npm run build && npm run serve, then refresh brower page.

For registerType: autoUpdate, second time you start the server, you will see the reload automatically, for registerType: 'prompt' the reload prompt will appear, you can navigate to see the change are not applied, and once click on refresh you will see the changes.

You can also work with autoUpdate and ReloadpPrompt component, to show the ready to work offline. In that case you need to comment out the router::isReady callback on src/router.js, include the ReloadPrompt component on src/App.vue and configure registerType: 'autoUpdate' on vite.config.js. Remember you are with autoUpdate so the prompt will not appear when sw needs to be updated.

You can also set offline the browser and check that works.

I have pushed the changes, working with autoUpdate, if you want make it working with prompt: 1) Uncomment from src/App.vue (also the import and the components):

<!-- Include this component if you want to use `autoUpdate`: also add `onReady` callback on `src/router.js` -->
<reload-prompt />

2) Go to src/router.js and comment router callback:

/* 
comment these callback if you want to use `prompt`
*/
/*
router.onReady(async() => {
  const { registerSW } = await import("virtual:pwa-register")
  registerSW({ immediate: true })
})
*/

3) Go to vite.config.js and change registerType entry to prompt or just comment out/delete the option:

    VitePWA({
      // for prompt comment out this option or just remove it, since it is the default behavior */
      registerType: 'prompt',
    ...
    ... 

You have a mixin for virtual:pwa-register/vue on src/mixins/useRegisterSW.js, you can see src/components/ReloadPrompt.vue how it is used:

export default {
  name: "useRegisterSW",
  data: () => ({
    updateSW: undefined,
    offlineReady: false,
    needRefresh: false,
  }),
  async mounted() {
    const { registerSW } = await import("virtual:pwa-register")
    const vm = this;
    this.updateSW =  registerSW({
      immediate: true,
      onOfflineReady() {
        vm.offlineReady = true;
        vm.onOfflineReadyFn();
      } ,
      onNeedRefresh() {
        vm.needRefresh = true;
        vm.onNeedRefreshFn()
      },
    })
  },
  methods: {
    async closePrompt() {
      this.offlineReady = false;
      this.needRefresh = false;
    },
    onOfflineReadyFn() {
      console.log('onOfflineReady');
    },
    onNeedRefreshFn() {
      console.log('onNeedRefresh');
    },
    updateServiceWorker() {
      this.updateSW && this.updateSW(true)
    }
  }
}

imagen

userquin commented 3 years ago

I'll keep open this issue until tmr... so please, close it yourself if the sample on my fork works for you,

hubert17 commented 3 years ago

Success! Thanks @userquin image image

It's working even using CDN hosted packages. I have only installed devdependency packages. It took me sometime to figure out how this done until I read this.. image

I'm looking at this issue thu. Hope you can advise me on this. image

hubert17 commented 3 years ago

It's here: https://github.com/hubert17/GabsVuetifyNoCLINodeWebpack/tree/pwa-vue

userquin commented 3 years ago

I'll give a try, seems something missing...

userquin commented 3 years ago

Move the logic from the mixin to the ReloadPrompt component, it seems the mixin cannot be used in the way you create you components: remove also the mixin import.

Also comment out the onReady callback on src/router.js.

And finally add this style to the class .pwa-toast: background-color: white; on ReloadPrompt component.

imagen

imagen

userquin commented 3 years ago
// import useRegisterSW from "../mixins/useRegisterSW";
import { css } from 'https://cdn.jsdelivr.net/npm/goober@2.0.33/dist/goober.modern.js';

const styles = css /*css*/ `
    .pwa-toast {
    position: fixed;
    right: 0;
    bottom: 0;
    margin: 16px;
    padding: 12px;
    border: 1px solid #8885;
    border-radius: 4px;
    z-index: 1;
    text-align: left;
    box-shadow: 3px 4px 5px 0px #8885;
    background-color: white; 
    }
    .pwa-toast .message {
    margin-bottom: 8px;
    }
    .pwa-toast button {
    border: 1px solid #8885;
    outline: none;
    margin-right: 5px;
    border-radius: 2px;
    padding: 3px 10px;
    }

`

export default {
    name: "ReloadPrompt",

    data() {
        return {
            updateSW: undefined,
            offlineReady: false,
            needRefresh: false,
        }
    },
    async mounted() {
        const { registerSW } = await import("virtual:pwa-register")
        const vm = this;
        this.updateSW =  registerSW({
            immediate: true,
            onOfflineReady() {
                vm.offlineReady = true;
                vm.onOfflineReadyFn();
            } ,
            onNeedRefresh() {
                vm.needRefresh = true;
                vm.onNeedRefreshFn()
            },
        })
    },
    methods: {
        async closePrompt() {
            this.offlineReady = false;
            this.needRefresh = false;
        },
        onOfflineReadyFn() {
            console.log('onOfflineReady');
        },
        onNeedRefreshFn() {
            console.log('onNeedRefresh');
        },
        updateServiceWorker() {
            this.updateSW && this.updateSW(true)
        }
    },

    template: /*html*/ `

<div class=${styles}>
    <div
      v-if="offlineReady || needRefresh"
      class="pwa-toast"
      role="alert"
  >
    <div class="message">
      <span v-if="offlineReady">
        App ready to work offline
      </span>
      <span v-else>
        New content available, click on reload button to update.
      </span>
    </div>
    <button v-if="needRefresh" @click="updateServiceWorker">
      Reload
    </button>
    <button @click="closePrompt">
      Close
    </button>
  </div>
</div>

    `,
  };
userquin commented 3 years ago

Do not change anything, just remove the empty data method on your ReloadPrompt component!!!!

Dont forget to add the background color to the .pwa-toast class on src/components/ReloadPrompt.vue (it is transparent).

userquin commented 3 years ago
export default {
    name: "ReloadPrompt",
    mixins: [useRegisterSW],

/* WHAT ARE YOU DOING HERE?
    data() {

    },
*/
    template: /*html*/ `
userquin commented 3 years ago

upps, wrong button clicked, close the issue when tested please.

hubert17 commented 3 years ago

Working great now in Vue2! https://github.com/hubert17/GabsVuetifyNoCLINodeWebpack/tree/pwa-vue

...at least when hosted in root. However in Github Pages, I ended up with problem on base/paths. But that would be for another issue. Thank you again @userquin . Closing this now.