🧑‍💻(frontend) env var service-worker dev mode

Add a new environment variable to enable or disable
the service worker in development mode.
By default, the service worker is disabled
in development mode, it can cause problems
when developing the application with the hmr.
It can creates useless log in the console
as well.
We can easily enable it by setting
NEXT_PUBLIC_SW_DEACTIVATED to false in the
.env.development file.
We will use this new var to not use the service
worder with the CI as well.
This commit is contained in:
Anthony LC
2024-06-14 16:12:39 +02:00
committed by Anthony LC
parent 3b77e1254e
commit c2aa5be8ff
6 changed files with 81 additions and 5 deletions

View File

@@ -1,2 +1,3 @@
NEXT_PUBLIC_API_ORIGIN=http://localhost:8071
NEXT_PUBLIC_SIGNALING_URL=ws://localhost:4444
NEXT_PUBLIC_SW_DEACTIVATED=true

View File

@@ -11,7 +11,7 @@ const nextConfig = {
// Enables the styled-components SWC transform
styledComponents: true,
},
webpack(config, { isServer, dev }) {
webpack(config, { isServer }) {
// Grab the existing rule that handles SVG imports
const fileLoaderRule = config.module.rules.find((rule) =>
rule.test?.test?.('.svg'),
@@ -33,7 +33,7 @@ const nextConfig = {
},
);
if (!isServer && !dev) {
if (!isServer && process.env.NEXT_PUBLIC_SW_DEACTIVATED !== 'true') {
config.plugins.push(
new InjectManifest({
swSrc: './src/core/service-worker.ts',

View File

@@ -5,7 +5,7 @@
"scripts": {
"dev": "next dev",
"build": "prettier --check . && yarn stylelint && next build",
"build:ci": "cp .env.development .env.local && cross-env NEXT_PUBLIC_CI=true yarn build",
"build:ci": "cp .env.development .env.local && yarn build",
"build-theme": "cunningham -g css,ts -o src/cunningham --utility-classes",
"start": "npx -y serve@latest out",
"lint": "tsc --noEmit && next lint",
@@ -21,7 +21,6 @@
"@gouvfr-lasuite/integration": "1.0.1",
"@openfun/cunningham-react": "2.9.3",
"@tanstack/react-query": "5.48.0",
"cross-env": "*",
"i18next": "23.11.5",
"lodash": "4.17.21",
"luxon": "3.4.4",
@@ -49,6 +48,7 @@
"@types/node": "*",
"@types/react": "18.3.3",
"@types/react-dom": "*",
"cross-env": "*",
"dotenv": "16.4.5",
"eslint-config-impress": "*",
"fetch-mock": "9.11.0",

View File

@@ -0,0 +1,71 @@
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import { Router } from 'next/router';
import { PropsWithChildren, ReactElement } from 'react';
import App from '@/pages/_app';
import { AppWrapper } from '@/tests/utils';
import { NextPageWithLayout } from '@/types/next';
const Page: NextPageWithLayout = () => {
return <div>Test Page</div>;
};
Page.getLayout = function getLayout(page: ReactElement) {
return <div>{page}</div>;
};
jest.mock('@/core/', () => ({
...jest.requireActual('@/core/'),
AppProvider: ({ children }: PropsWithChildren) => <div>{children}</div>,
}));
describe('App', () => {
it('checks service-worker is register', () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
const registerSpy = jest.fn();
registerSpy.mockImplementation(
() =>
new Promise((reject) => {
reject('error');
}),
);
Object.defineProperty(navigator, 'serviceWorker', {
value: {
register: registerSpy,
},
writable: true,
});
render(<App Component={Page} router={{} as Router} pageProps={{}} />, {
wrapper: AppWrapper,
});
expect(registerSpy).toHaveBeenCalledWith('/service-worker.js');
});
it('checks service-worker is not register', () => {
process.env.NEXT_PUBLIC_SW_DEACTIVATED = 'true';
const registerSpy = jest.fn();
registerSpy.mockImplementation(
() =>
new Promise((reject) => {
reject('error');
}),
);
Object.defineProperty(navigator, 'serviceWorker', {
value: {
register: registerSpy,
},
writable: true,
});
render(<App Component={Page} router={{} as Router} pageProps={{}} />, {
wrapper: AppWrapper,
});
expect(registerSpy).not.toHaveBeenCalledWith('/service-worker.js');
});
});

View File

@@ -21,5 +21,6 @@ namespace NodeJS {
interface ProcessEnv {
NEXT_PUBLIC_API_ORIGIN?: string;
NEXT_PUBLIC_SIGNALING_URL?: string;
NEXT_PUBLIC_SW_DEACTIVATED?: string;
}
}

View File

@@ -17,7 +17,10 @@ export default function App({ Component, pageProps }: AppPropsWithLayout) {
const { t } = useTranslation();
useEffect(() => {
if ('serviceWorker' in navigator && process.env.NEXT_PUBLIC_CI !== 'true') {
if (
'serviceWorker' in navigator &&
process.env.NEXT_PUBLIC_SW_DEACTIVATED !== 'true'
) {
navigator.serviceWorker.register('/service-worker.js').catch((err) => {
console.error('Service worker registration failed:', err);
});