Merge branch 'vite-sw2' into 'develop'

Build the ServiceWorker with Vite

See merge request soapbox-pub/soapbox!2681
This commit is contained in:
Alex Gleason 2023-09-15 19:55:09 +00:00
commit 0a30a31e61
9 changed files with 888 additions and 27 deletions

View File

@ -8,7 +8,7 @@ import { HStack, Text, Stack } from 'soapbox/components/ui';
import { captureException } from 'soapbox/monitoring'; import { captureException } from 'soapbox/monitoring';
import KVStore from 'soapbox/storage/kv-store'; import KVStore from 'soapbox/storage/kv-store';
import sourceCode from 'soapbox/utils/code'; import sourceCode from 'soapbox/utils/code';
import { unregisterSw } from 'soapbox/utils/sw'; import { unregisterSW } from 'soapbox/utils/sw';
import SiteLogo from './site-logo'; import SiteLogo from './site-logo';
@ -96,7 +96,7 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
e.preventDefault(); e.preventDefault();
unregisterSw().then(goHome).catch(goHome); unregisterSW().then(goHome).catch(goHome);
} }
}; };

View File

@ -3,7 +3,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import List, { ListItem } from 'soapbox/components/list'; import List, { ListItem } from 'soapbox/components/list';
import { HStack, Text, Column, FormActions, Button, Stack, Icon } from 'soapbox/components/ui'; import { HStack, Text, Column, FormActions, Button, Stack, Icon } from 'soapbox/components/ui';
import { unregisterSw } from 'soapbox/utils/sw'; import { unregisterSW } from 'soapbox/utils/sw';
import Indicator from './components/indicator'; import Indicator from './components/indicator';
@ -99,7 +99,7 @@ const ServiceWorkerInfo: React.FC<IServiceWorkerInfo> = () => {
}; };
const handleRestart = async() => { const handleRestart = async() => {
await unregisterSw(); await unregisterSW();
window.location.reload(); window.location.reload();
}; };

View File

@ -25,13 +25,14 @@ import './precheck';
import { default as Soapbox } from './containers/soapbox'; import { default as Soapbox } from './containers/soapbox';
import * as monitoring from './monitoring'; import * as monitoring from './monitoring';
import ready from './ready'; import ready from './ready';
import { registerSW } from './utils/sw';
// Sentry // Sentry
monitoring.start(); monitoring.start();
// Print console warning
if (BuildConfig.NODE_ENV === 'production') { if (BuildConfig.NODE_ENV === 'production') {
printConsoleWarning(); printConsoleWarning();
registerSW('/sw.js');
} }
ready(() => { ready(() => {

View File

@ -3,14 +3,14 @@ import IntlMessageFormat from 'intl-messageformat';
import 'intl-pluralrules'; import 'intl-pluralrules';
import unescape from 'lodash/unescape'; import unescape from 'lodash/unescape';
import locales from './web-push-locales';
import type { import type {
Account as AccountEntity, Account as AccountEntity,
Notification as NotificationEntity, Notification as NotificationEntity,
Status as StatusEntity, Status as StatusEntity,
} from 'soapbox/types/entities'; } from 'soapbox/types/entities';
const locales = import.meta.compileTime('./web-push-locales.ts');
/** Limit before we start grouping device notifications into a single notification. */ /** Limit before we start grouping device notifications into a single notification. */
const MAX_NOTIFICATIONS = 5; const MAX_NOTIFICATIONS = 5;
/** Tag for the grouped notification. */ /** Tag for the grouped notification. */

View File

@ -1,16 +1,14 @@
/* @preval */ import fs from 'node:fs';
import path from 'path';
const fs = require('fs'); const filtered: Record<string, Record<string, string>> = {};
const path = require('path');
const filtered = {};
const filenames = fs.readdirSync(path.resolve(__dirname, '../locales')); const filenames = fs.readdirSync(path.resolve(__dirname, '../locales'));
filenames.forEach(filename => { filenames.forEach(filename => {
if (!filename.match(/\.json$/) || filename.match(/defaultMessages|whitelist/)) return; if (!filename.match(/\.json$/) || filename.match(/defaultMessages|whitelist/)) return;
const content = fs.readFileSync(path.resolve(__dirname, `../locales/${filename}`), 'utf-8'); const content = fs.readFileSync(path.resolve(__dirname, `../locales/${filename}`), 'utf-8');
const full = JSON.parse(content); const full = JSON.parse(content) as Record<string, string>;
const locale = filename.split('.')[0]; const locale = filename.split('.')[0];
filtered[locale] = { filtered[locale] = {
@ -35,4 +33,6 @@ filenames.forEach(filename => {
}; };
}); });
module.exports = JSON.parse(JSON.stringify(filtered)); export default () => ({
data: filtered,
});

View File

@ -1,6 +1,15 @@
/** Register the ServiceWorker. */
function registerSW(path: string) {
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register(path, { scope: '/' });
});
}
}
/** Unregister the ServiceWorker */ /** Unregister the ServiceWorker */
// https://stackoverflow.com/a/49771828/8811886 // https://stackoverflow.com/a/49771828/8811886
const unregisterSw = async(): Promise<void> => { const unregisterSW = async(): Promise<void> => {
if (navigator.serviceWorker) { if (navigator.serviceWorker) {
// FIXME: this only works if using a single tab. // FIXME: this only works if using a single tab.
// Send a message to sw.js instead to refresh all tabs. // Send a message to sw.js instead to refresh all tabs.
@ -11,5 +20,6 @@ const unregisterSw = async(): Promise<void> => {
}; };
export { export {
unregisterSw, registerSW,
unregisterSW,
}; };

View File

@ -19,7 +19,8 @@
"scripts": { "scripts": {
"start": "npx vite serve", "start": "npx vite serve",
"dev": "${npm_execpath} run start", "dev": "${npm_execpath} run start",
"build": "npx vite build", "build": "npx vite build --emptyOutDir",
"preview": "npx vite preview",
"audit:fix": "npx yarn-audit-fix", "audit:fix": "npx yarn-audit-fix",
"manage:translations": "npx ts-node ./scripts/translationRunner.ts", "manage:translations": "npx ts-node ./scripts/translationRunner.ts",
"i18n": "rm -rf build tmp && npx cross-env NODE_ENV=production ${npm_execpath} run build && ${npm_execpath} manage:translations en", "i18n": "rm -rf build tmp && npx cross-env NODE_ENV=production ${npm_execpath} run build && ${npm_execpath} manage:translations en",
@ -209,6 +210,7 @@
"stylelint-config-standard-scss": "^6.1.0", "stylelint-config-standard-scss": "^6.1.0",
"tailwindcss": "^3.3.3", "tailwindcss": "^3.3.3",
"ts-jest": "^29.0.0", "ts-jest": "^29.0.0",
"vite-plugin-pwa": "^0.16.5",
"yargs": "^17.6.2" "yargs": "^17.6.2"
}, },
"resolutions": { "resolutions": {

View File

@ -4,6 +4,7 @@ import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import compileTime from 'vite-plugin-compile-time'; import compileTime from 'vite-plugin-compile-time';
import { createHtmlPlugin } from 'vite-plugin-html'; import { createHtmlPlugin } from 'vite-plugin-html';
import { VitePWA } from 'vite-plugin-pwa';
import vitePluginRequire from 'vite-plugin-require'; import vitePluginRequire from 'vite-plugin-require';
import { viteStaticCopy } from 'vite-plugin-static-copy'; import { viteStaticCopy } from 'vite-plugin-static-copy';
@ -28,6 +29,7 @@ export default defineConfig({
plugins: [ plugins: [
// @ts-ignore // @ts-ignore
vitePluginRequire.default(), vitePluginRequire.default(),
compileTime(),
createHtmlPlugin({ createHtmlPlugin({
template: 'index.html', template: 'index.html',
}), }),
@ -38,7 +40,25 @@ export default defineConfig({
configFile: './babel.config.cjs', configFile: './babel.config.cjs',
}, },
}), }),
compileTime(), VitePWA({
injectRegister: null,
strategies: 'injectManifest',
injectManifest: {
injectionPoint: undefined,
plugins: [
// @ts-ignore
compileTime(),
],
},
manifestFilename: 'manifest.json',
manifest: {
name: 'Soapbox',
short_name: 'Soapbox',
description: 'A social media frontend with a focus on custom branding and ease of use.',
},
srcDir: 'soapbox/service-worker',
filename: 'sw.ts',
}),
viteStaticCopy({ viteStaticCopy({
targets: [{ targets: [{
src: '../node_modules/twemoji/assets/svg/*', src: '../node_modules/twemoji/assets/svg/*',

846
yarn.lock

File diff suppressed because it is too large Load Diff