Reputation: 13
I have a frontend-backend project that is usually run with dotnent when we run the full-scale application. But now i have also created a completely mock-based site using MSW ( mock-service-worker ). This works just fine locally but after deployment i get a white screen from time to time on the deployed site. Sometimes it works and sometimes it doesnt, usually works after a reload of page. Ive tried various solutions but i cant really get it to work without the white-page from time to time. Anyone who has any suggestions?
Vite.config:
import { defineConfig, loadEnv } from 'vite';
import https from 'https';
import path from 'path';
import fs from 'fs';
import tsconfigPaths from 'vite-tsconfig-paths';
import react from '@vitejs/plugin-react';
import basicSsl from '@vitejs/plugin-basic-ssl';
import { visualizer } from 'rollup-plugin-visualizer';
// Enable visualizer when we are working with it
// import { visualizer } from 'rollup-plugin-visualizer';
function excludeMsw() {
return {
name: 'exclude-msw',
resolveId(source) {
return source === 'virtual-module' ? source : null;
},
renderStart(outputOptions, _inputOptions) {
const outDir = outputOptions.dir;
const msWorker = path.resolve(outDir, 'mockServiceWorker.js');
fs.rm(msWorker, () => console.log(`Deleted ${msWorker}`));
},
};
}
function translationReload() {
return {
// Since we are getting our translations with a http request
// We need to refetch them when any changes are made. Therefore we do a reload
name: 'translation-reload',
handleHotUpdate({ file, server }) {
if (file.includes('locales') && file.endsWith('.json')) {
const filePath = path.dirname(file);
const fileFolder = filePath.substring(filePath.lastIndexOf('/') + 1);
console.log(`Translation updated: ${fileFolder}/${path.basename(file)}. Reloading`);
server.ws.send({
type: 'full-reload',
path: '*',
});
}
},
};
}
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd());
const proxyContext = [
'/auth',
'/api',
'/loansapi',
'/cardsapi',
'/complianceapi',
'/savingsapi',
'/kreditzapi',
'/consentapi',
'/edgeapi',
];
const proxySettings = {
target: env.VITE_PROXY_TARGET || `https://localhost:44349`,
changeOrigin: true,
secure: false,
agent: new https.Agent(),
};
const proxy = proxyContext.reduce((result, path) => {
return { ...result, [path]: proxySettings };
}, {});
return {
plugins: [
react({
jsxImportSource: '@emotion/react',
babel: {
plugins: ['@emotion/babel-plugin'],
},
}),
tsconfigPaths(),
env.VITE_ENV !== 'development' ? basicSsl() : null,
translationReload(),
excludeMsw(),
// visualizer({
// filename: 'bundle-analysis.html',
// open: true,
// }),
],
define: {
'process.env': env,
},
server: {
allowedHosts: ['mocked-frontend-domain'],
proxy: env.VITE_ENV !== 'development' ? proxy : {},
https: env.VITE_ENV !== 'development',
open: false,
secure: false,
port: 3000,
watch: {
usePolling: true,
},
},
base: '/',
build: {
// Relative to the root
outDir: './build',
target: 'es2015',
rollupOptions: {
output: {
chunkFileNames: '[hash].js',
manualChunks: id => {
if (id.includes('features/applications/loans')) {
return 'vendor_loan_application';
}
if (id.includes('features/applications/savings')) {
return 'vendor_savings_application';
}
if (id.includes('features/applications/card')) {
return 'vendor_card_applications';
}
if (id.includes('src/features')) {
return 'vendor_features';
}
if (id.includes('node_modules')) {
if (id.includes('@mui/x-date-pickers')) {
return 'vendor_mui_date_pickers';
}
if (id.includes('@mui')) {
return 'vendor_mui';
}
if (id.includes('storybook')) {
return 'vendor_storybook';
}
if (id.includes('launchdarkly')) {
return 'vendor_launchdarkly';
}
if (id.includes('date-fns')) {
return 'vendor_datefns';
}
if (id.includes('i18next')) {
return 'vendor_i18next';
}
if (id.includes('react-query')) {
return 'vendor_reactquery';
}
// all other package goes here
return 'vendor';
}
},
},
},
},
test: {
globals: true,
environment: 'jsdom',
setupFiles: './scripts/setupTest.js',
exclude: ['e2e', 'node_modules/**/*', 'tests'],
},
resolve: {
preserveSymlinks: true,
},
};
});
Dockerfile:
FROM node:18-alpine
RUN specific fun commad ***
USER mock
WORKDIR /home/mock/app
COPY --chown=mock:mock package.json ./
RUN npm install
COPY --chown=mock:mock . .
RUN npm run build
ENV TMPDIR=/tmp
ENV VITE_CACHE_DIR=/tmp/vite-cache
EXPOSE 3000
CMD ["npm", "run", "dev"]
Package.json
{
"name": "NAME",
"version": "4.4.0",
"type": "module",
"description": "DESCRIPTION",
"main": "index.js",
"scripts": {
"prestart": "node scripts/aspnetcore-https.js && node scripts/setupEnv.js",
"dev": "cross-env VITE_ENV=development npm run serve",
"start": "npm run serve",
"serve": "vite serve --port 3000 --host",
"test:jest": "cross-env VITE_TEST=true vitest",
"test": "cross-env VITE_TEST=true vitest && npm run test:e2e",
"test:e2e": "playwright test",
"test:generate": "npm run dev & npx playwright codegen http://localhost:3000/overview",
"test:e2e:ci": "npx playwright test",
"test:noWatch": "vitest run",
"lint": "eslint src --ext .ts,.tsx --quiet --fix",
"tslint": "npx tsc --noEmit --project tsconfig.json",
"build": "npx msw init ./public && vite build",
"storybook": "storybook dev -p 6006 -s public",
"build-storybook": "storybook build"
},
"repository": {
"type": "git",
"url": ""
},
"license": "MIT",
"browserslist": "last 2 versions, > 1%",
"dependencies": {
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@hookform/resolvers": "^3.9.0",
"@mui/material": "^5.16.3",
"@mui/x-date-pickers": "^7.0.8",
"@opendevtools/clearingnummer": "^1.3.0",
"@tanstack/react-query": "^4.36.1",
"@tanstack/react-query-devtools": "^4.36.1",
"@types/react-dom": "^18.3.0",
"@types/react-recaptcha-v3": "^1.1.5",
"date-fns": "^2.29.3",
"i18n-iso-countries": "^7.5.0",
"i18next": "^24.0.2",
"i18next-http-backend": "^2.0.1",
"launchdarkly-react-client-sdk": "^3.0.6",
"next-i18next": "^15.3.1",
"polished": "^4.2.2",
"qrcode.react": "^3.1.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-ga4": "^2.0.0",
"react-google-recaptcha-v3": "^1.10.1",
"react-hook-form": "^7.53.0",
"react-i18next": "^15.1.0",
"react-router-dom": "6.11.1",
"uuid": "^9.0.0",
"whatwg-fetch": "3.0.0",
"yup": "^1.4.0"
},
"devDependencies": {
"@playwright/test": "^1.40.1",
"@storybook/addon-essentials": "7.4.5",
"@storybook/addon-interactions": "7.4.5",
"@storybook/addon-links": "7.4.5",
"@storybook/blocks": "7.4.5",
"@storybook/react": "7.4.5",
"@storybook/react-vite": "8.0.0",
"@storybook/testing-library": "0.2.1",
"@storybook/theming": "7.4.5",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^16.0.1",
"@types/jest": "^29.5.12",
"@types/react": "18.3.2",
"@types/testing-library__dom": "6.14.0",
"@types/uuid": "^9.0.2",
"@typescript-eslint/eslint-plugin": "^5.43.0",
"@typescript-eslint/parser": "^5.43.0",
"@vitejs/plugin-basic-ssl": "^1.0.1",
"@vitejs/plugin-react": "^4.0.0",
"babel-plugin-emotion": "11.0.0",
"cross-env": "^7.0.3",
"dotenv": "^16.0.1",
"eslint": "^8.2.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^17.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.35.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-storybook": "^0.6.14",
"eslint-plugin-unused-imports": "^2.0.0",
"jsdom": "^20.0.3",
"msw": "^1.3.2",
"msw-storybook-addon": "^1.8.0",
"prettier": "2.7.0",
"rollup-plugin-visualizer": "^5.9.0",
"sass": "^1.56.1",
"storybook": "^8.0.0",
"typescript": "^5.5.4",
"vite": "^5.4.14",
"vite-tsconfig-paths": "^4.2.0",
"vitest": "^2.1.6"
},
"resolutions": {
"@types/react": "18.3.5",
"@types/react-dom": "18.3.0"
},
"msw": {
"workerDirectory": "public"
}
}
Upvotes: 0
Views: 32