├── public
├── robots.txt
├── favicon.ico
├── img
│ └── icons
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── apple-touch-icon.png
│ │ ├── mstile-150x150.png
│ │ ├── android-chrome-192x192.png
│ │ ├── android-chrome-512x512.png
│ │ ├── apple-touch-icon-60x60.png
│ │ ├── apple-touch-icon-76x76.png
│ │ ├── apple-touch-icon-120x120.png
│ │ ├── apple-touch-icon-152x152.png
│ │ ├── apple-touch-icon-180x180.png
│ │ ├── msapplication-icon-144x144.png
│ │ └── safari-pinned-tab.svg
├── manifest.json
├── index.html
└── firebase-messaging-sw.js
├── .browserslistrc
├── babel.config.js
├── .firebaserc
├── postcss.config.js
├── src
├── assets
│ └── logo.png
├── shims-vue.d.ts
├── views
│ ├── About.vue
│ └── Home.vue
├── store.ts
├── shims-tsx.d.ts
├── App.vue
├── router.ts
├── registerServiceWorker.ts
├── main.ts
└── components
│ └── HelloWorld.vue
├── firebase.json
├── .gitignore
├── tslint.json
├── README.md
├── package.json
└── tsconfig.json
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not ie <= 8
4 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "vue-pwa-tutorial"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {}
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import Vue from 'vue';
3 | export default Vue;
4 | }
5 |
--------------------------------------------------------------------------------
/public/img/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/img/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/public/img/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/img/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This is an about page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/img/icons/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/img/icons/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/img/icons/mstile-150x150.png
--------------------------------------------------------------------------------
/public/img/icons/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/img/icons/android-chrome-192x192.png
--------------------------------------------------------------------------------
/public/img/icons/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/img/icons/android-chrome-512x512.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/img/icons/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/img/icons/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/img/icons/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/img/icons/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/img/icons/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/public/img/icons/msapplication-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n11sh1/vue-pwa-tutorial/HEAD/public/img/icons/msapplication-icon-144x144.png
--------------------------------------------------------------------------------
/src/store.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 |
4 | Vue.use(Vuex);
5 |
6 | export default new Vuex.Store({
7 | state: {
8 |
9 | },
10 | mutations: {
11 |
12 | },
13 | actions: {
14 |
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "hosting": {
3 | "public": "dist",
4 | "ignore": [
5 | "firebase.json",
6 | "**/.*",
7 | "**/node_modules/**"
8 | ],
9 | "rewrites": [
10 | {
11 | "source": "**",
12 | "destination": "/index.html"
13 | }
14 | ]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw*
22 |
23 | .firebase
--------------------------------------------------------------------------------
/src/shims-tsx.d.ts:
--------------------------------------------------------------------------------
1 | import Vue, { VNode } from 'vue';
2 |
3 | declare global {
4 | namespace JSX {
5 | // tslint:disable no-empty-interface
6 | interface Element extends VNode {}
7 | // tslint:disable no-empty-interface
8 | interface ElementClass extends Vue {}
9 | interface IntrinsicElements {
10 | [elem: string]: any;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "warning",
3 | "extends": [
4 | "tslint:recommended"
5 | ],
6 | "linterOptions": {
7 | "exclude": [
8 | "node_modules/**"
9 | ]
10 | },
11 | "rules": {
12 | "quotemark": [true, "single"],
13 | "indent": [true, "spaces", 2],
14 | "interface-name": false,
15 | "ordered-imports": false,
16 | "object-literal-sort-keys": false,
17 | "no-consecutive-blank-lines": false
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
5 |
6 |
7 |
8 |
19 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-pwa-tutorial",
3 | "short_name": "vue-pwa-tutorial",
4 | "icons": [
5 | {
6 | "src": "./img/icons/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "./img/icons/android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "start_url": "./index.html",
17 | "display": "standalone",
18 | "background_color": "#000000",
19 | "theme_color": "#4DBA87",
20 | "gcm_sender_id": "103953800507"
21 | }
22 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | vue-pwa-tutorial
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-pwa-tutorial
2 | Document
3 |
4 | Vue CLI 3 で PWA やってみた(Service Workers / Add to Home Screen / Push Notifications)
5 | https://qiita.com/n11sh1/items/5d64c337ef927ac8d5d6
6 |
7 | ## Project setup
8 | ```
9 | npm install
10 | ```
11 |
12 | ### Compiles and hot-reloads for development
13 | ```
14 | npm run serve
15 | ```
16 |
17 | ### Compiles and minifies for production
18 | ```
19 | npm run build
20 | ```
21 |
22 | ### Run your tests
23 | ```
24 | npm run test
25 | ```
26 |
27 | ### Lints and fixes files
28 | ```
29 | npm run lint
30 | ```
31 |
32 | ### Customize configuration
33 | See [Configuration Reference](https://cli.vuejs.org/config/).
34 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Home |
5 | About
6 |
7 |
8 |
9 |
10 |
11 |
32 |
--------------------------------------------------------------------------------
/src/router.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Router from 'vue-router';
3 | import Home from './views/Home.vue';
4 |
5 | Vue.use(Router);
6 |
7 | export default new Router({
8 | mode: 'history',
9 | base: process.env.BASE_URL,
10 | routes: [
11 | {
12 | path: '/',
13 | name: 'home',
14 | component: Home,
15 | },
16 | {
17 | path: '/about',
18 | name: 'about',
19 | // route level code-splitting
20 | // this generates a separate chunk (about.[hash].js) for this route
21 | // which is lazy-loaded when the route is visited.
22 | component: () => import(/* webpackChunkName: "about" */ './views/About.vue'),
23 | },
24 | ],
25 | });
26 |
--------------------------------------------------------------------------------
/public/firebase-messaging-sw.js:
--------------------------------------------------------------------------------
1 | // [START initialize_firebase_in_sw]
2 | // Give the service worker access to Firebase Messaging.
3 | // Note that you can only use Firebase Messaging here, other Firebase libraries
4 | // are not available in the service worker.
5 | importScripts('https://www.gstatic.com/firebasejs/5.5.6/firebase-app.js');
6 | importScripts('https://www.gstatic.com/firebasejs/5.5.6/firebase-messaging.js');
7 | // Initialize the Firebase app in the service worker by passing in the messagingSenderId.
8 | firebase.initializeApp({
9 | 'messagingSenderId': '630674987445'
10 | });
11 |
12 | // Retrieve an instance of Firebase Messaging so that it can handle background messages.
13 | const messaging = firebase.messaging();
14 | // [END initialize_firebase_in_sw]
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-pwa-tutorial",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "firebase": "^5.8.0",
12 | "register-service-worker": "^1.5.2",
13 | "vue": "^2.5.21",
14 | "vue-class-component": "^6.0.0",
15 | "vue-property-decorator": "^7.0.0",
16 | "vue-router": "^3.0.1",
17 | "vuex": "^3.0.1"
18 | },
19 | "devDependencies": {
20 | "@vue/cli-plugin-babel": "^3.3.0",
21 | "@vue/cli-plugin-pwa": "^3.3.0",
22 | "@vue/cli-plugin-typescript": "^3.3.0",
23 | "@vue/cli-service": "^3.3.0",
24 | "typescript": "^3.0.0",
25 | "vue-template-compiler": "^2.5.21"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "importHelpers": true,
8 | "moduleResolution": "node",
9 | "experimentalDecorators": true,
10 | "esModuleInterop": true,
11 | "allowSyntheticDefaultImports": true,
12 | "sourceMap": true,
13 | "baseUrl": ".",
14 | "types": [
15 | "webpack-env"
16 | ],
17 | "paths": {
18 | "@/*": [
19 | "src/*"
20 | ]
21 | },
22 | "lib": [
23 | "esnext",
24 | "dom",
25 | "dom.iterable",
26 | "scripthost"
27 | ]
28 | },
29 | "include": [
30 | "src/**/*.ts",
31 | "src/**/*.tsx",
32 | "src/**/*.vue",
33 | "tests/**/*.ts",
34 | "tests/**/*.tsx"
35 | ],
36 | "exclude": [
37 | "node_modules"
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/src/registerServiceWorker.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable:no-console */
2 |
3 | import { register } from 'register-service-worker';
4 |
5 | if (process.env.NODE_ENV === 'production') {
6 | register(`${process.env.BASE_URL}service-worker.js`, {
7 | ready() {
8 | console.log(
9 | 'App is being served from cache by a service worker.\n' +
10 | 'For more details, visit https://goo.gl/AFskqB',
11 | );
12 | },
13 | registered() {
14 | console.log('Service worker has been registered.');
15 | },
16 | cached() {
17 | console.log('Content has been cached for offline use.');
18 | },
19 | updatefound() {
20 | console.log('New content is downloading.');
21 | },
22 | updated() {
23 | console.log('New content is available; please refresh.');
24 | },
25 | offline() {
26 | console.log('No internet connection found. App is running in offline mode.');
27 | },
28 | error(error) {
29 | console.error('Error during service worker registration:', error);
30 | },
31 | });
32 | }
33 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import App from './App.vue';
3 | import router from './router';
4 | import store from './store';
5 | import './registerServiceWorker';
6 | import * as firebase from "firebase";
7 |
8 | Vue.config.productionTip = false;
9 |
10 | // Initialize Firebase
11 | var config = {
12 | apiKey: "xxxxxxxxxxx",
13 | authDomain: "xxxxxxxxxxx",
14 | databaseURL: "xxxxxxxxxxx",
15 | projectId: "xxxxxxxxxxx",
16 | storageBucket: "xxxxxxxxxxx",
17 | messagingSenderId: "xxxxxxxxxxx"
18 | };
19 | firebase.initializeApp(config);
20 |
21 | // Retrieve Firebase Messaging object.
22 | const messaging = firebase.messaging();
23 |
24 | // Add the public key generated from the console here.
25 | messaging.usePublicVapidKey("xxxxxxxxxxx");
26 |
27 | messaging.requestPermission().then(() => {
28 | console.log('Notification permission granted.');
29 | messaging.getToken().then((token) => {
30 | console.log(token);
31 | })
32 | }).catch((err) => {
33 | console.log('Unable to get permission to notify.', err);
34 | });
35 |
36 | new Vue({
37 | router,
38 | store,
39 | render: (h) => h(App),
40 | }).$mount('#app');
41 |
--------------------------------------------------------------------------------
/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
5 | For a guide and recipes on how to configure / customize this project,
6 | check out the
7 | vue-cli documentation.
8 |
9 |
Installed CLI Plugins
10 |
15 |
Essential Links
16 |
23 |
Ecosystem
24 |
31 |
32 |
33 |
34 |
42 |
43 |
44 |
60 |
--------------------------------------------------------------------------------
/public/img/icons/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
150 |
--------------------------------------------------------------------------------