From 96a8939cd2c2e157b2261516705c647d1f72d590 Mon Sep 17 00:00:00 2001 From: aelassas Date: Fri, 20 Dec 2024 17:08:11 +0100 Subject: [PATCH] Fix lighthouse issues --- backend/package-lock.json | 190 ++++++++++++++++++++++++++++- backend/package.json | 4 +- backend/vite.config.ts | 71 +++++++++-- frontend/package-lock.json | 183 ++++++++++++++++++++++++++- frontend/package.json | 4 +- frontend/src/assets/css/footer.css | 2 +- frontend/src/assets/css/home.css | 12 +- frontend/src/components/Footer.tsx | 10 +- frontend/src/components/Slick.tsx | 1 - frontend/vite.config.ts | 70 +++++++++-- 10 files changed, 515 insertions(+), 32 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index 32c96a6ba..998a216a7 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -38,10 +38,12 @@ "vite": "^6.0.3" }, "devDependencies": { + "@babel/plugin-transform-runtime": "^7.25.9", "eslint-config-airbnb": "^19.0.4", "npm-check-updates": "^17.1.11", "stylelint": "^16.12.0", - "stylelint-config-standard": "^36.0.1" + "stylelint-config-standard": "^36.0.1", + "terser": "^5.37.0" } }, "node_modules/@ampproject/remapping": { @@ -166,6 +168,23 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", + "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/helper-module-imports": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", @@ -290,6 +309,37 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz", + "integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/runtime": { "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", @@ -1163,6 +1213,17 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", @@ -2499,6 +2560,58 @@ "npm": ">=6" } }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", + "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.3", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", + "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.3" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2558,6 +2671,13 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -2682,6 +2802,13 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2710,6 +2837,20 @@ "node": ">=18" } }, + "node_modules/core-js-compat": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -5119,6 +5260,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -6230,6 +6378,27 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6685,6 +6854,25 @@ "dev": true, "license": "MIT" }, + "node_modules/terser": { + "version": "5.37.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", + "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", diff --git a/backend/package.json b/backend/package.json index dc53ee6da..b36bfbd1f 100644 --- a/backend/package.json +++ b/backend/package.json @@ -45,9 +45,11 @@ "vite": "^6.0.3" }, "devDependencies": { + "@babel/plugin-transform-runtime": "^7.25.9", "eslint-config-airbnb": "^19.0.4", "npm-check-updates": "^17.1.11", "stylelint": "^16.12.0", - "stylelint-config-standard": "^36.0.1" + "stylelint-config-standard": "^36.0.1", + "terser": "^5.37.0" } } diff --git a/backend/vite.config.ts b/backend/vite.config.ts index f18f0c8a3..fa6a778ab 100644 --- a/backend/vite.config.ts +++ b/backend/vite.config.ts @@ -1,14 +1,22 @@ +import path from 'node:path' import { defineConfig, loadEnv } from 'vite' import react from '@vitejs/plugin-react' -import path from 'node:path' // https://vitejs.dev/config/ export default ({ mode }: { mode: string }) => { process.env = { ...process.env, ...loadEnv(mode, process.cwd(), '') } return defineConfig({ - plugins: [react()], - + plugins: [ + react({ + // Babel optimizations + babel: { + plugins: [ + ['@babel/plugin-transform-runtime'], + ] + } + }) + ], resolve: { alias: { '@': path.resolve(__dirname, './src'), @@ -21,19 +29,66 @@ export default ({ mode }: { mode: string }) => { server: { host: '0.0.0.0', - port: Number.parseInt(process.env.VITE_PORT || '3005', 10), + port: Number.parseInt(process.env.VITE_PORT || '3001', 10), }, build: { - outDir: 'build', - target: 'esnext', + outDir: 'build', // Output directory + target: 'esnext', // Use esnext to ensure the best performance modulePreload: true, // Keep modulePreload enabled to ensure the best performance - sourcemap: false, - minify: 'esbuild', // Use esbuild for fast minification + sourcemap: false, // Disable sourcemaps in production + cssCodeSplit: true, // Enable CSS code splitting + + // Minification settings (Use terser for minification with aggressive settings) + minify: 'terser', // Can also use 'esbuild' which is faster but less optimized + terserOptions: { + compress: { + drop_console: true, // Removes console.* calls + drop_debugger: true, // Removes debugger statements + dead_code: true, // Removes unreachable code + passes: 3, // Number of compression passes + unsafe_math: true, // Optimize math expressions + conditionals: true, // Optimize if-s and conditional expressions + sequences: true, // Join consecutive simple statements using the comma operator + booleans: true, // various optimizations for boolean context + unused: true, // Drop unreferenced functions and variables + if_return: true, // Optimizations for if/return and if/continue + join_vars: true, // Join consecutive var statements + }, + format: { + comments: false, // Remove comments + }, + mangle: { + properties: false // Don't rename properties (safer) + } + }, + + // Control chunk size + chunkSizeWarningLimit: 1000, // Warn if a chunk exceeds 1000kb + + // Chunk splitting strategy rollupOptions: { treeshake: true, // Enable Tree Shaking: Ensure unused code is removed by leveraging ES modules and proper imports + output: { + // Chunk splitting strategy + manualChunks: { + vendor: ['react', 'react-dom'], + router: ['react-router-dom'], + }, + // Generate chunk names + assetFileNames: 'assets/[name]-[hash][extname]', + chunkFileNames: 'chunks/[name]-[hash].js', + entryFileNames: 'entries/[name]-[hash].js', + }, }, assetsInlineLimit: 8192, // This reduces the number of small chunk files }, + optimizeDeps: { + include: [ + 'react', + 'react-dom', + 'react-router-dom', + ], + }, }) } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 7ebd7fbb0..59ef9cda5 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -53,10 +53,12 @@ "vite": "^6.0.3" }, "devDependencies": { + "@babel/plugin-transform-runtime": "^7.25.9", "eslint-config-airbnb": "^19.0.4", "npm-check-updates": "^17.1.11", "stylelint": "^16.12.0", - "stylelint-config-standard": "^36.0.1" + "stylelint-config-standard": "^36.0.1", + "terser": "^5.37.0" } }, "node_modules/@ampproject/remapping": { @@ -181,6 +183,23 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", + "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/helper-module-imports": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", @@ -305,6 +324,37 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz", + "integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/runtime": { "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", @@ -1178,6 +1228,17 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", @@ -2591,6 +2652,58 @@ "npm": ">=6" } }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", + "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.3", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", + "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.3" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2650,6 +2763,13 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -2780,6 +2900,13 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2808,6 +2935,20 @@ "node": ">=18" } }, + "node_modules/core-js-compat": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -6451,6 +6592,27 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/string-convert": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", @@ -6912,6 +7074,25 @@ "dev": true, "license": "MIT" }, + "node_modules/terser": { + "version": "5.37.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", + "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 5bdc298d0..9c5a94012 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -60,9 +60,11 @@ "vite": "^6.0.3" }, "devDependencies": { + "@babel/plugin-transform-runtime": "^7.25.9", "eslint-config-airbnb": "^19.0.4", "npm-check-updates": "^17.1.11", "stylelint": "^16.12.0", - "stylelint-config-standard": "^36.0.1" + "stylelint-config-standard": "^36.0.1", + "terser": "^5.37.0" } } diff --git a/frontend/src/assets/css/footer.css b/frontend/src/assets/css/footer.css index 38d917d97..928fb6f57 100644 --- a/frontend/src/assets/css/footer.css +++ b/frontend/src/assets/css/footer.css @@ -77,7 +77,7 @@ div.footer div.footer-contact a:hover { div.footer div.footer-contact .social-icon { color: #525252; - margin-right: 12px; + /* margin-right: 12px; */ } div.footer div.footer-contact .social-icon:hover{ diff --git a/frontend/src/assets/css/home.css b/frontend/src/assets/css/home.css index 96e832ce6..964cea9fa 100644 --- a/frontend/src/assets/css/home.css +++ b/frontend/src/assets/css/home.css @@ -306,7 +306,7 @@ div.home div.car-size div.boxes div.box div.box-content span.price { div.home div.car-size div.boxes div.box div.box-content span.unit { font-size: 14px; - color: #A9A9A9; + color: #696969; } div.home div.car-size div.boxes div.box div.car-size-action { @@ -392,21 +392,21 @@ div.home div.customer-care div.customer-care-img img { @media only screen and (width <=960px) { div.home div.home-content { - padding: 60px 0; + padding: 85px 0; justify-content: flex-start !important; - height: 480px; + height: 560px; } - div.home-title { + div.home div.home-title { font-size: 22px; font-weight: 500; margin-bottom: 20px; } - div.home-cover { + div.home div.home-cover { font-size: 40px; font-weight: 800; - padding: 20px 5px 10px; + padding: 0 10px; } div.home div.search div.home-search { diff --git a/frontend/src/components/Footer.tsx b/frontend/src/components/Footer.tsx index 0edd1db5b..4a4b5d13c 100644 --- a/frontend/src/components/Footer.tsx +++ b/frontend/src/components/Footer.tsx @@ -1,6 +1,6 @@ import React from 'react' import { useNavigate } from 'react-router-dom' -import { Link } from '@mui/material' +import { IconButton } from '@mui/material' import { MailOutline, FacebookTwoTone as FacebookIcon, @@ -47,10 +47,10 @@ const Footer = () => { info@bookcars.ma
- - - - + + + +
diff --git a/frontend/src/components/Slick.tsx b/frontend/src/components/Slick.tsx index ae61e8f78..a6e9a4d63 100644 --- a/frontend/src/components/Slick.tsx +++ b/frontend/src/components/Slick.tsx @@ -95,7 +95,6 @@ const Slick = forwardRef(({ children, ...props }, ref) =
{child}
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 7621aa1b9..11316032f 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,13 +1,22 @@ +import path from 'node:path' import { defineConfig, loadEnv } from 'vite' import react from '@vitejs/plugin-react' -import path from 'node:path' // https://vitejs.dev/config/ export default ({ mode }: { mode: string }) => { process.env = { ...process.env, ...loadEnv(mode, process.cwd(), '') } return defineConfig({ - plugins: [react()], + plugins: [ + react({ + // Babel optimizations + babel: { + plugins: [ + ['@babel/plugin-transform-runtime'], + ] + } + }) + ], resolve: { alias: { @@ -21,19 +30,66 @@ export default ({ mode }: { mode: string }) => { server: { host: '0.0.0.0', - port: Number.parseInt(process.env.VITE_PORT || '3006', 10), + port: Number.parseInt(process.env.VITE_PORT || '3002', 10), }, build: { - outDir: 'build', - target: 'esnext', + outDir: 'build', // Output directory + target: 'esnext', // Use esnext to ensure the best performance modulePreload: true, // Keep modulePreload enabled to ensure the best performance - sourcemap: false, - minify: 'esbuild', // Use esbuild for fast minification + sourcemap: false, // Disable sourcemaps in production + cssCodeSplit: true, // Enable CSS code splitting + + // Minification settings (Use terser for minification with aggressive settings) + minify: 'terser', // Can also use 'esbuild' which is faster but less optimized + terserOptions: { + compress: { + drop_console: true, // Removes console.* calls + drop_debugger: true, // Removes debugger statements + dead_code: true, // Removes unreachable code + passes: 3, // Number of compression passes + unsafe_math: true, // Optimize math expressions + conditionals: true, // Optimize if-s and conditional expressions + sequences: true, // Join consecutive simple statements using the comma operator + booleans: true, // various optimizations for boolean context + unused: true, // Drop unreferenced functions and variables + if_return: true, // Optimizations for if/return and if/continue + join_vars: true, // Join consecutive var statements + }, + format: { + comments: false, // Remove comments + }, + mangle: { + properties: false // Don't rename properties (safer) + } + }, + + // Control chunk size + chunkSizeWarningLimit: 1000, // Warn if a chunk exceeds 1000kb + + // Chunk splitting strategy rollupOptions: { treeshake: true, // Enable Tree Shaking: Ensure unused code is removed by leveraging ES modules and proper imports + output: { + // Chunk splitting strategy + manualChunks: { + vendor: ['react', 'react-dom'], + router: ['react-router-dom'], + }, + // Generate chunk names + assetFileNames: 'assets/[name]-[hash][extname]', + chunkFileNames: 'chunks/[name]-[hash].js', + entryFileNames: 'entries/[name]-[hash].js', + }, }, assetsInlineLimit: 8192, // This reduces the number of small chunk files }, + optimizeDeps: { + include: [ + 'react', + 'react-dom', + 'react-router-dom', + ], + }, }) }