feat: pwa support

This commit is contained in:
Sonny
2023-11-30 14:02:59 +01:00
parent db5fef08fc
commit d7fe801aa2
9 changed files with 1624 additions and 111 deletions

4
.gitignore vendored
View File

@@ -39,3 +39,7 @@ yarn-error.log*
# sitemap files (they are generated by postbuild script) # sitemap files (they are generated by postbuild script)
public/sitemap* public/sitemap*
public/robots.txt public/robots.txt
# pwa static files
/public/sw.js
/public/workbox-*.js

View File

@@ -1,7 +1,8 @@
const config = { const config = {
url: process.env.NEXT_PUBLIC_SITE_URL, url: process.env.NEXT_PUBLIC_SITE_URL,
name: 'MyLinks', name: 'MyLinks',
description: 'MyLinks is a free and open source software, that lets you manage your bookmarks in an intuitive interface' description:
} 'MyLinks is a free and open source software, that lets you manage your bookmarks in an intuitive interface',
};
export default config export default config;

View File

@@ -2,6 +2,6 @@
module.exports = { module.exports = {
siteUrl: process.env.NEXTAUTH_URL || 'https://www.mylinks.app', siteUrl: process.env.NEXTAUTH_URL || 'https://www.mylinks.app',
generateRobotsTxt: true, generateRobotsTxt: true,
output: "standalone", output: 'standalone',
exclude: ['/link/*', '/category/*'] exclude: ['/link/*', '/category/*'],
}; };

View File

@@ -1,7 +1,11 @@
const { i18n } = require('./next-i18next.config'); const { i18n } = require('./next-i18next.config');
const {
PHASE_DEVELOPMENT_SERVER,
PHASE_PRODUCTION_BUILD,
} = require('next/constants');
/** @type {import("next").NextConfig} */ /** @type {import("next").NextConfig} */
const config = { const nextConfig = {
i18n, i18n,
webpack(config) { webpack(config) {
config.module.rules.push({ config.module.rules.push({
@@ -24,4 +28,12 @@ const config = {
output: 'standalone', output: 'standalone',
}; };
module.exports = config; module.exports = (phase) => {
if (phase === PHASE_DEVELOPMENT_SERVER || phase === PHASE_PRODUCTION_BUILD) {
const withPWA = require('@ducanh2912/next-pwa').default({
dest: 'public',
});
return withPWA(nextConfig);
}
return nextConfig;
};

1646
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -11,6 +11,7 @@
"prepare": "husky install" "prepare": "husky install"
}, },
"dependencies": { "dependencies": {
"@ducanh2912/next-pwa": "^9.7.2",
"@prisma/client": "^5.6.0", "@prisma/client": "^5.6.0",
"@svgr/webpack": "^8.1.0", "@svgr/webpack": "^8.1.0",
"accept-language": "^3.0.18", "accept-language": "^3.0.18",

24
public/manifest.json Normal file
View File

@@ -0,0 +1,24 @@
{
"name": "MyLinks",
"short_name": "MyLinks",
"description": "MyLinks is a free and open source software, that lets you manage your favorite links in an intuitive interface",
"launch_handler": {
"client_mode": [
"focus-existing",
"auto"
]
},
"icons": [
{
"src": "/favicon.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
}
],
"theme_color": "#f0eef6",
"background_color": "#f0eef6",
"start_url": "/",
"display": "standalone",
"orientation": "portrait"
}

View File

@@ -2,7 +2,7 @@ import ErrorBoundary from 'components/ErrorBoundary/ErrorBoundary';
import * as Keys from 'constants/keys'; import * as Keys from 'constants/keys';
import PATHS from 'constants/paths'; import PATHS from 'constants/paths';
import { SessionProvider } from 'next-auth/react'; import { SessionProvider } from 'next-auth/react';
import { appWithTranslation } from 'next-i18next'; import { appWithTranslation, useTranslation } from 'next-i18next';
import { DefaultSeo } from 'next-seo'; import { DefaultSeo } from 'next-seo';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import nProgress from 'nprogress'; import nProgress from 'nprogress';
@@ -10,11 +10,12 @@ import 'nprogress/nprogress.css';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import 'styles/globals.scss'; import 'styles/globals.scss';
import nextI18nextConfig from '../../next-i18next.config';
import config from '../../config'; import config from '../../config';
import nextI18nextConfig from '../../next-i18next.config';
function MyApp({ Component, pageProps: { session, ...pageProps } }) { function MyApp({ Component, pageProps: { session, ...pageProps } }) {
const router = useRouter(); const router = useRouter();
const { i18n } = useTranslation();
useHotkeys(Keys.CLOSE_SEARCH_KEY, () => router.push(PATHS.HOME), { useHotkeys(Keys.CLOSE_SEARCH_KEY, () => router.push(PATHS.HOME), {
enabled: router.pathname !== PATHS.HOME, enabled: router.pathname !== PATHS.HOME,
@@ -41,16 +42,18 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }) {
defaultTitle='MyLinks' defaultTitle='MyLinks'
openGraph={{ openGraph={{
type: 'website', type: 'website',
locale: 'en_US', locale: i18n.language,
url: config.url, url: config.url,
siteName: config.name, siteName: config.name,
description: config.description, description: config.description,
images: [{ images: [
url: '/logo-light.png', {
width: 500, url: '/logo-light.png',
height: 165, width: 500,
alt: 'MyLinks logo', height: 165,
}], alt: 'MyLinks logo',
},
],
}} }}
twitter={{ twitter={{
handle: '@handle', handle: '@handle',

View File

@@ -17,6 +17,18 @@ const Document = () => (
href='/favicon.png' href='/favicon.png'
type='image/png' type='image/png'
/> />
<link
rel='manifest'
href='/manifest.json'
/>
<link
rel='apple-touch-icon'
href='/favicon.png'
/>
<link
rel='icon'
href='/favicon.png'
/>
</Head> </Head>
<body> <body>
<noscript>Vous devez activer JavaScript pour utiliser ce site</noscript> <noscript>Vous devez activer JavaScript pour utiliser ce site</noscript>