From 59fc03bb438ff25230a1f63402e011536bf24187 Mon Sep 17 00:00:00 2001
From: Scai <59282365+alexevladgabriel@users.noreply.github.com>
Date: Wed, 17 Jul 2024 22:27:36 +0300
Subject: [PATCH 1/4] final wip (includes vitest, vite, workflows, types
rewrite)
---
.eslintrc.js | 1 -
.github/workflows/{build.yaml => ui.yaml} | 9 +-
.gitignore | 1 +
app/Http/ViewComposers/AssetComposer.php | 8 -
app/Services/Helpers/AssetHashService.php | 117 -
babel.config.js | 34 -
jest.config.js | 28 -
package.json | 45 +-
resources/scripts/TransitionRouter.tsx | 2 +-
resources/scripts/api/definitions/helpers.ts | 2 +-
.../scripts/api/definitions/user/models.d.ts | 2 +-
.../api/definitions/user/transformers.ts | 2 +-
.../api/server/backups/createServerBackup.ts | 2 +-
resources/scripts/api/server/getServer.ts | 2 +-
.../api/server/updateStartupVariable.ts | 2 +-
resources/scripts/api/swr/getServerBackups.ts | 2 +-
resources/scripts/api/swr/getServerStartup.ts | 2 +-
resources/scripts/api/transformers.ts | 2 +-
.../scripts/assets/css/GlobalStylesheet.ts | 2 +-
resources/scripts/components/App.tsx | 3 +-
resources/scripts/components/MessageBox.tsx | 2 +-
.../scripts/components/NavigationBar.tsx | 2 +-
.../components/auth/LoginFormContainer.tsx | 2 +-
.../dashboard/AccountOverviewContainer.tsx | 2 +-
.../components/dashboard/ServerRow.tsx | 2 +-
.../dashboard/forms/CreateApiKeyForm.tsx | 2 +-
.../dashboard/search/SearchModal.tsx | 2 +-
.../dashboard/ssh/CreateSSHKeyForm.tsx | 2 +-
.../scripts/components/elements/Button.tsx | 2 +-
.../components/elements/CodemirrorEditor.tsx | 2 +-
.../components/elements/ContentContainer.tsx | 2 +-
.../components/elements/DropdownMenu.tsx | 2 +-
.../scripts/components/elements/Fade.tsx | 2 +-
.../components/elements/GreyRowBox.tsx | 2 +-
.../scripts/components/elements/Input.tsx | 2 +-
.../components/elements/InputSpinner.tsx | 2 +-
.../scripts/components/elements/Label.tsx | 2 +-
.../scripts/components/elements/Modal.tsx | 2 +-
.../components/elements/Pagination.tsx | 2 +-
.../components/elements/ProgressBar.tsx | 2 +-
.../components/elements/ScreenBlock.tsx | 2 +-
.../scripts/components/elements/Select.tsx | 2 +-
.../scripts/components/elements/Spinner.tsx | 2 +-
.../components/elements/SubNavigation.tsx | 2 +-
.../scripts/components/elements/Switch.tsx | 2 +-
.../components/elements/dialog/context.ts | 2 +-
.../server/backups/BackupContextMenu.tsx | 2 +-
.../components/server/backups/BackupRow.tsx | 2 +-
.../server/files/FileDropdownMenu.tsx | 4 +-
.../server/files/FileEditContainer.tsx | 2 +-
.../components/server/files/FileNameModal.tsx | 2 +-
.../components/server/files/FileObjectRow.tsx | 2 +-
.../server/files/NewDirectoryButton.tsx | 2 +-
.../server/files/RenameFileModal.tsx | 2 +-
.../server/files/SelectFileCheckbox.tsx | 2 +-
.../server/network/AllocationRow.tsx | 2 +-
.../components/server/startup/VariableBox.tsx | 2 +-
.../components/server/users/PermissionRow.tsx | 2 +-
resources/scripts/i18n.ts | 2 +-
resources/scripts/index.tsx | 8 -
resources/scripts/lib/formatters.spec.ts | 1 +
resources/scripts/lib/helpers.spec.ts | 1 +
resources/scripts/lib/objects.spec.ts | 1 +
resources/scripts/lib/strings.spec.ts | 1 +
resources/views/templates/wrapper.blade.php | 6 +-
tsconfig.json | 2 +-
vite.config.ts | 61 +
webpack.config.js | 156 -
yarn.lock | 5879 ++++-------------
69 files changed, 1342 insertions(+), 5122 deletions(-)
rename .github/workflows/{build.yaml => ui.yaml} (84%)
delete mode 100644 app/Services/Helpers/AssetHashService.php
delete mode 100644 babel.config.js
delete mode 100644 jest.config.js
create mode 100644 vite.config.ts
delete mode 100644 webpack.config.js
diff --git a/.eslintrc.js b/.eslintrc.js
index e129753f2f..964c32b6f5 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -29,7 +29,6 @@ module.exports = {
'eslint:recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
- 'plugin:jest-dom/recommended',
],
rules: {
eqeqeq: 'error',
diff --git a/.github/workflows/build.yaml b/.github/workflows/ui.yaml
similarity index 84%
rename from .github/workflows/build.yaml
rename to .github/workflows/ui.yaml
index 3021c6799a..5b5cd9be96 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/ui.yaml
@@ -1,4 +1,4 @@
-name: Build
+name: UI
on:
push:
@@ -10,7 +10,7 @@ on:
jobs:
ui:
- name: UI
+ name: Build & Test
runs-on: ubuntu-latest
strategy:
fail-fast: false
@@ -30,4 +30,7 @@ jobs:
run: yarn install --frozen-lockfile
- name: Build
- run: yarn build:production
+ run: yarn build
+
+ - name: Tests
+ run: yarn test
diff --git a/.gitignore b/.gitignore
index 8a0a2ef56f..d406df5048 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@
/storage/*.key
/storage/clockwork/*
/vendor
+/coverage
*.DS_Store*
.env
.env.backup
diff --git a/app/Http/ViewComposers/AssetComposer.php b/app/Http/ViewComposers/AssetComposer.php
index 2a47096fb6..5ce287f940 100644
--- a/app/Http/ViewComposers/AssetComposer.php
+++ b/app/Http/ViewComposers/AssetComposer.php
@@ -3,23 +3,15 @@
namespace App\Http\ViewComposers;
use Illuminate\View\View;
-use App\Services\Helpers\AssetHashService;
class AssetComposer
{
- /**
- * AssetComposer constructor.
- */
- public function __construct(private AssetHashService $assetHashService)
- {
- }
/**
* Provide access to the asset service in the views.
*/
public function compose(View $view): void
{
- $view->with('asset', $this->assetHashService);
$view->with('siteConfiguration', [
'name' => config('app.name', 'Panel'),
'locale' => config('app.locale') ?? 'en',
diff --git a/app/Services/Helpers/AssetHashService.php b/app/Services/Helpers/AssetHashService.php
deleted file mode 100644
index f94c32f3ba..0000000000
--- a/app/Services/Helpers/AssetHashService.php
+++ /dev/null
@@ -1,117 +0,0 @@
-filesystem = $filesystem->createLocalDriver(['root' => public_path()]);
- }
-
- /**
- * Modify a URL to append the asset hash.
- */
- public function url(string $resource): string
- {
- $file = last(explode('/', $resource));
- $data = Arr::get($this->manifest(), $file) ?? $file;
-
- return str_replace($file, Arr::get($data, 'src') ?? $file, $resource);
- }
-
- /**
- * Return the data integrity hash for a resource.
- */
- public function integrity(string $resource): string
- {
- $file = last(explode('/', $resource));
- $data = array_get($this->manifest(), $file, $file);
-
- return Arr::get($data, 'integrity') ?? '';
- }
-
- /**
- * Return a built CSS import using the provided URL.
- */
- public function css(string $resource): string
- {
- $attributes = [
- 'href' => $this->url($resource),
- 'rel' => 'stylesheet preload',
- 'as' => 'style',
- 'crossorigin' => 'anonymous',
- 'referrerpolicy' => 'no-referrer',
- ];
-
- if (config('panel.assets.use_hash')) {
- $attributes['integrity'] = $this->integrity($resource);
- }
-
- $output = ' $value) {
- $output .= " $key=\"$value\"";
- }
-
- return $output . '>';
- }
-
- /**
- * Return a built JS import using the provided URL.
- */
- public function js(string $resource): string
- {
- $attributes = [
- 'src' => $this->url($resource),
- 'crossorigin' => 'anonymous',
- ];
-
- if (config('panel.assets.use_hash')) {
- $attributes['integrity'] = $this->integrity($resource);
- }
-
- $output = '';
- }
-
- /**
- * Get the asset manifest and store it in the cache for quicker lookups.
- */
- protected function manifest(): array
- {
- if (static::$manifest === null) {
- self::$manifest = json_decode(
- $this->filesystem->get(self::MANIFEST_PATH),
- true
- );
- }
-
- $manifest = static::$manifest;
- if ($manifest === null) {
- throw new ManifestDoesNotExistException();
- }
-
- return $manifest;
- }
-}
diff --git a/babel.config.js b/babel.config.js
deleted file mode 100644
index 808bb186f9..0000000000
--- a/babel.config.js
+++ /dev/null
@@ -1,34 +0,0 @@
-module.exports = function (api) {
- let targets = {};
- const plugins = [
- 'babel-plugin-macros',
- 'styled-components',
- 'react-hot-loader/babel',
- '@babel/transform-runtime',
- '@babel/transform-react-jsx',
- '@babel/proposal-class-properties',
- '@babel/proposal-object-rest-spread',
- '@babel/proposal-optional-chaining',
- '@babel/proposal-nullish-coalescing-operator',
- '@babel/syntax-dynamic-import',
- ];
-
- if (api.env('test')) {
- targets = { node: 'current' };
- plugins.push('@babel/transform-modules-commonjs');
- }
-
- return {
- plugins,
- presets: [
- '@babel/typescript',
- ['@babel/env', {
- modules: false,
- useBuiltIns: 'entry',
- corejs: 3,
- targets,
- }],
- '@babel/react',
- ]
- };
-};
diff --git a/jest.config.js b/jest.config.js
deleted file mode 100644
index abb02f3860..0000000000
--- a/jest.config.js
+++ /dev/null
@@ -1,28 +0,0 @@
-const { pathsToModuleNameMapper } = require('ts-jest');
-const { compilerOptions } = require('./tsconfig');
-
-/** @type {import('ts-jest').InitialOptionsTsJest} */
-module.exports = {
- preset: 'ts-jest',
- globals: {
- 'ts-jest': {
- isolatedModules: true,
- },
- },
- moduleFileExtensions: ['js', 'ts', 'tsx', 'd.ts', 'json', 'node'],
- moduleNameMapper: {
- '\\.(jpe?g|png|gif|svg)$': '/resources/scripts/__mocks__/file.ts',
- '\\.(s?css|less)$': 'identity-obj-proxy',
- ...pathsToModuleNameMapper(compilerOptions.paths, {
- prefix: '/',
- }),
- },
- setupFilesAfterEnv: [
- '/resources/scripts/setup-tests.ts',
- ],
- transform: {
- '.*\\.[t|j]sx$': 'babel-jest',
- '.*\\.ts$': 'ts-jest',
- },
- testPathIgnorePatterns: ['/node_modules/'],
-};
diff --git a/package.json b/package.json
index ebb3266be3..0a4894e091 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,15 @@
"engines": {
"node": ">=18"
},
+ "scripts": {
+ "build": "vite build",
+ "clean": "rimraf public/build",
+ "coverage": "vitest run --coverage",
+ "dev": "vite",
+ "lint": "eslint ./resources/scripts/**/*.{ts,tsx} --ext .ts,.tsx",
+ "test": "vitest run",
+ "test:ui": "vitest --ui"
+ },
"dependencies": {
"@floating-ui/react-dom-interactions": "^0.6.6",
"@fortawesome/fontawesome-svg-core": "^1.2.32",
@@ -10,7 +19,6 @@
"@fortawesome/react-fontawesome": "^0.1.11",
"@headlessui/react": "^1.6.4",
"@heroicons/react": "^1.0.6",
- "@hot-loader/react-dom": "^16.14.0",
"@preact/signals-react": "^1.2.1",
"@tailwindcss/forms": "^0.5.2",
"@tailwindcss/line-clamp": "^0.4.0",
@@ -33,9 +41,8 @@
"qrcode.react": "^1.0.1",
"react": "^16.14.0",
"react-chartjs-2": "^4.2.0",
- "react-dom": "npm:@hot-loader/react-dom",
+ "react-dom": "^16.14.0",
"react-fast-compare": "^3.2.0",
- "react-hot-loader": "^4.12.21",
"react-i18next": "^11.2.1",
"react-router-dom": "^5.1.2",
"react-transition-group": "^4.4.1",
@@ -69,14 +76,12 @@
"@babel/preset-typescript": "^7.12.1",
"@babel/runtime": "^7.12.1",
"@testing-library/dom": "^8.14.0",
- "@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "12.1.5",
"@testing-library/user-event": "^14.2.1",
"@types/codemirror": "^0.0.98",
"@types/debounce": "^1.2.0",
"@types/events": "^3.0.0",
- "@types/jest": "^28.1.3",
- "@types/node": "^14.11.10",
+ "@types/node": "^20.14.11",
"@types/qrcode.react": "^1.0.1",
"@types/react": "^16.14.0",
"@types/react-copy-to-clipboard": "^4.3.0",
@@ -86,11 +91,15 @@
"@types/react-router-dom": "^5.1.3",
"@types/react-transition-group": "^4.4.0",
"@types/styled-components": "^5.1.7",
+ "@types/tailwindcss": "^3.1.0",
"@types/uuid": "^3.4.5",
"@types/webpack-env": "^1.15.2",
"@types/yup": "^0.29.3",
"@typescript-eslint/eslint-plugin": "^5.29.0",
"@typescript-eslint/parser": "^5.29.0",
+ "@vitejs/plugin-react": "^4.3.1",
+ "@vitest/coverage-v8": "^2.0.3",
+ "@vitest/ui": "^2.0.3",
"autoprefixer": "^10.4.7",
"babel-jest": "^28.1.1",
"babel-loader": "^8.2.5",
@@ -99,14 +108,14 @@
"css-loader": "^5.2.7",
"eslint": "^8.18.0",
"eslint-config-prettier": "^8.5.0",
- "eslint-plugin-jest-dom": "^4.0.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"fork-ts-checker-webpack-plugin": "^6.2.10",
- "identity-obj-proxy": "^3.0.0",
- "jest": "^28.1.1",
+ "happy-dom": "^14.12.3",
+ "laravel-vite-plugin": "0.8",
+ "pathe": "^1.1.2",
"postcss": "^8.4.35",
"postcss-import": "^14.1.0",
"postcss-loader": "^4.0.0",
@@ -114,30 +123,18 @@
"postcss-preset-env": "^7.7.1",
"prettier": "^2.7.1",
"redux-devtools-extension": "^2.13.8",
+ "rimraf": "3.0.2",
"source-map-loader": "^1.1.3",
"style-loader": "^2.0.0",
"svg-url-loader": "^7.1.1",
"terser-webpack-plugin": "^4.2.3",
"ts-essentials": "^9.1.2",
- "ts-jest": "^28.0.5",
"twin.macro": "^2.8.2",
"typescript": "^4.7.3",
- "webpack": "^4.47.0",
- "webpack-assets-manifest": "^3.1.1",
- "webpack-bundle-analyzer": "^3.8.0",
- "webpack-cli": "^3.3.12",
- "webpack-dev-server": "^3.11.0",
+ "vite": "^5.3.4",
+ "vitest": "^2.0.3",
"yarn-deduplicate": "^1.1.1"
},
- "scripts": {
- "clean": "cd public/assets && find . \\( -name \"*.js\" -o -name \"*.map\" \\) -type f -delete",
- "test": "jest",
- "lint": "eslint ./resources/scripts/**/*.{ts,tsx} --ext .ts,.tsx",
- "watch": "cross-env NODE_ENV=development ./node_modules/.bin/webpack --watch --progress",
- "build": "cross-env NODE_ENV=development ./node_modules/.bin/webpack --progress",
- "build:production": "yarn run clean && cross-env NODE_ENV=production ./node_modules/.bin/webpack --mode production",
- "serve": "yarn run clean && cross-env WEBPACK_PUBLIC_PATH=/webpack@hmr/ NODE_ENV=development webpack-dev-server --host 0.0.0.0 --port 8080 --public https://panel.test --hot"
- },
"browserslist": [
"> 0.5%",
"last 2 versions",
diff --git a/resources/scripts/TransitionRouter.tsx b/resources/scripts/TransitionRouter.tsx
index 040097eaa8..97f122433f 100644
--- a/resources/scripts/TransitionRouter.tsx
+++ b/resources/scripts/TransitionRouter.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { Route } from 'react-router';
import { SwitchTransition } from 'react-transition-group';
import Fade from '@/components/elements/Fade';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import tw from 'twin.macro';
const StyledSwitchTransition = styled(SwitchTransition)`
diff --git a/resources/scripts/api/definitions/helpers.ts b/resources/scripts/api/definitions/helpers.ts
index eeb933f5a4..53baf2997e 100644
--- a/resources/scripts/api/definitions/helpers.ts
+++ b/resources/scripts/api/definitions/helpers.ts
@@ -5,7 +5,7 @@ import {
getPaginationSet,
PaginatedResult,
} from '@/api/http';
-import { Model } from '@definitions/index';
+import type { Model } from '@definitions/index';
type TransformerFunc = (callback: FractalResponseData) => T;
diff --git a/resources/scripts/api/definitions/user/models.d.ts b/resources/scripts/api/definitions/user/models.d.ts
index a5b40ca678..619b57e080 100644
--- a/resources/scripts/api/definitions/user/models.d.ts
+++ b/resources/scripts/api/definitions/user/models.d.ts
@@ -1,4 +1,4 @@
-import { Model, UUID } from '@/api/definitions';
+import type { Model, UUID } from '@/api/definitions';
import { SubuserPermission } from '@/state/server/subusers';
interface User extends Model {
diff --git a/resources/scripts/api/definitions/user/transformers.ts b/resources/scripts/api/definitions/user/transformers.ts
index 1fa62d3f9a..89fc8ee916 100644
--- a/resources/scripts/api/definitions/user/transformers.ts
+++ b/resources/scripts/api/definitions/user/transformers.ts
@@ -1,4 +1,4 @@
-import * as Models from '@definitions/user/models';
+import type * as Models from '@definitions/user/models';
import { FractalResponseData } from '@/api/http';
import { transform } from '@definitions/helpers';
diff --git a/resources/scripts/api/server/backups/createServerBackup.ts b/resources/scripts/api/server/backups/createServerBackup.ts
index 3167b5b46f..e104473db5 100644
--- a/resources/scripts/api/server/backups/createServerBackup.ts
+++ b/resources/scripts/api/server/backups/createServerBackup.ts
@@ -1,5 +1,5 @@
import http from '@/api/http';
-import { ServerBackup } from '@/api/server/types';
+import type { ServerBackup } from '@/api/server/types';
import { rawDataToServerBackup } from '@/api/transformers';
interface RequestParameters {
diff --git a/resources/scripts/api/server/getServer.ts b/resources/scripts/api/server/getServer.ts
index ff0abc026a..8c3ce047b3 100644
--- a/resources/scripts/api/server/getServer.ts
+++ b/resources/scripts/api/server/getServer.ts
@@ -1,6 +1,6 @@
import http, { FractalResponseData, FractalResponseList } from '@/api/http';
import { rawDataToServerAllocation, rawDataToServerEggVariable } from '@/api/transformers';
-import { ServerEggVariable, ServerStatus } from '@/api/server/types';
+import type { ServerEggVariable, ServerStatus } from '@/api/server/types';
export interface Allocation {
id: number;
diff --git a/resources/scripts/api/server/updateStartupVariable.ts b/resources/scripts/api/server/updateStartupVariable.ts
index 5102172822..a4d7e490fa 100644
--- a/resources/scripts/api/server/updateStartupVariable.ts
+++ b/resources/scripts/api/server/updateStartupVariable.ts
@@ -1,5 +1,5 @@
import http from '@/api/http';
-import { ServerEggVariable } from '@/api/server/types';
+import type { ServerEggVariable } from '@/api/server/types';
import { rawDataToServerEggVariable } from '@/api/transformers';
export default async (uuid: string, key: string, value: string): Promise<[ServerEggVariable, string]> => {
diff --git a/resources/scripts/api/swr/getServerBackups.ts b/resources/scripts/api/swr/getServerBackups.ts
index dbc7f5d989..28fcf8f135 100644
--- a/resources/scripts/api/swr/getServerBackups.ts
+++ b/resources/scripts/api/swr/getServerBackups.ts
@@ -1,6 +1,6 @@
import useSWR from 'swr';
import http, { getPaginationSet, PaginatedResult } from '@/api/http';
-import { ServerBackup } from '@/api/server/types';
+import type { ServerBackup } from '@/api/server/types';
import { rawDataToServerBackup } from '@/api/transformers';
import { ServerContext } from '@/state/server';
import { createContext, useContext } from 'react';
diff --git a/resources/scripts/api/swr/getServerStartup.ts b/resources/scripts/api/swr/getServerStartup.ts
index efecefe08d..9adc73cbc8 100644
--- a/resources/scripts/api/swr/getServerStartup.ts
+++ b/resources/scripts/api/swr/getServerStartup.ts
@@ -1,7 +1,7 @@
import useSWR, { ConfigInterface } from 'swr';
import http, { FractalResponseList } from '@/api/http';
import { rawDataToServerEggVariable } from '@/api/transformers';
-import { ServerEggVariable } from '@/api/server/types';
+import type { ServerEggVariable } from '@/api/server/types';
interface Response {
invocation: string;
diff --git a/resources/scripts/api/transformers.ts b/resources/scripts/api/transformers.ts
index 72d04c8469..dfd7375f59 100644
--- a/resources/scripts/api/transformers.ts
+++ b/resources/scripts/api/transformers.ts
@@ -1,7 +1,7 @@
import { Allocation } from '@/api/server/getServer';
import { FractalResponseData } from '@/api/http';
import { FileObject } from '@/api/server/files/loadDirectory';
-import { ServerBackup, ServerEggVariable } from '@/api/server/types';
+import type { ServerBackup, ServerEggVariable } from '@/api/server/types';
export const rawDataToServerAllocation = (data: FractalResponseData): Allocation => ({
id: data.attributes.id,
diff --git a/resources/scripts/assets/css/GlobalStylesheet.ts b/resources/scripts/assets/css/GlobalStylesheet.ts
index 7f520be458..4ae89abc4b 100644
--- a/resources/scripts/assets/css/GlobalStylesheet.ts
+++ b/resources/scripts/assets/css/GlobalStylesheet.ts
@@ -1,5 +1,5 @@
import tw from 'twin.macro';
-import { createGlobalStyle } from 'styled-components/macro';
+import { createGlobalStyle } from 'styled-components';
export default createGlobalStyle`
body {
diff --git a/resources/scripts/components/App.tsx b/resources/scripts/components/App.tsx
index 881ff4c013..472937d28d 100644
--- a/resources/scripts/components/App.tsx
+++ b/resources/scripts/components/App.tsx
@@ -1,5 +1,4 @@
import React, { lazy } from 'react';
-import { hot } from 'react-hot-loader/root';
import { Route, Router, Switch } from 'react-router-dom';
import { StoreProvider } from 'easy-peasy';
import { store } from '@/state';
@@ -92,4 +91,4 @@ const App = () => {
);
};
-export default hot(App);
+export default App;
diff --git a/resources/scripts/components/MessageBox.tsx b/resources/scripts/components/MessageBox.tsx
index 57a5cacb5b..e771365e19 100644
--- a/resources/scripts/components/MessageBox.tsx
+++ b/resources/scripts/components/MessageBox.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
import tw, { TwStyle } from 'twin.macro';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
export type FlashMessageType = 'success' | 'info' | 'warning' | 'error';
diff --git a/resources/scripts/components/NavigationBar.tsx b/resources/scripts/components/NavigationBar.tsx
index f784ddfff6..eee91c37f4 100644
--- a/resources/scripts/components/NavigationBar.tsx
+++ b/resources/scripts/components/NavigationBar.tsx
@@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next';
import { ApplicationStore } from '@/state';
import SearchContainer from '@/components/dashboard/search/SearchContainer';
import tw, { theme } from 'twin.macro';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import http from '@/api/http';
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
import Tooltip from '@/components/elements/tooltip/Tooltip';
diff --git a/resources/scripts/components/auth/LoginFormContainer.tsx b/resources/scripts/components/auth/LoginFormContainer.tsx
index 4e4db201e7..ce8995d243 100644
--- a/resources/scripts/components/auth/LoginFormContainer.tsx
+++ b/resources/scripts/components/auth/LoginFormContainer.tsx
@@ -1,6 +1,6 @@
import React, { forwardRef } from 'react';
import { Form } from 'formik';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import { breakpoint } from '@/theme';
import FlashMessageRender from '@/components/FlashMessageRender';
import tw from 'twin.macro';
diff --git a/resources/scripts/components/dashboard/AccountOverviewContainer.tsx b/resources/scripts/components/dashboard/AccountOverviewContainer.tsx
index 7ccf646138..1e89db49de 100644
--- a/resources/scripts/components/dashboard/AccountOverviewContainer.tsx
+++ b/resources/scripts/components/dashboard/AccountOverviewContainer.tsx
@@ -6,7 +6,7 @@ import ConfigureTwoFactorForm from '@/components/dashboard/forms/ConfigureTwoFac
import PageContentBlock from '@/components/elements/PageContentBlock';
import tw from 'twin.macro';
import { breakpoint } from '@/theme';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import MessageBox from '@/components/MessageBox';
import { useLocation } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
diff --git a/resources/scripts/components/dashboard/ServerRow.tsx b/resources/scripts/components/dashboard/ServerRow.tsx
index 08637bfc2a..c3839d7dd8 100644
--- a/resources/scripts/components/dashboard/ServerRow.tsx
+++ b/resources/scripts/components/dashboard/ServerRow.tsx
@@ -8,7 +8,7 @@ import { bytesToString, ip, mbToBytes } from '@/lib/formatters';
import tw from 'twin.macro';
import GreyRowBox from '@/components/elements/GreyRowBox';
import Spinner from '@/components/elements/Spinner';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import isEqual from 'react-fast-compare';
// Determines if the current value is in an alarm threshold so we can show it in red rather
diff --git a/resources/scripts/components/dashboard/forms/CreateApiKeyForm.tsx b/resources/scripts/components/dashboard/forms/CreateApiKeyForm.tsx
index 9c273044cb..570a53a6c4 100644
--- a/resources/scripts/components/dashboard/forms/CreateApiKeyForm.tsx
+++ b/resources/scripts/components/dashboard/forms/CreateApiKeyForm.tsx
@@ -11,7 +11,7 @@ import { ApiKey } from '@/api/account/getApiKeys';
import tw from 'twin.macro';
import Button from '@/components/elements/Button';
import Input, { Textarea } from '@/components/elements/Input';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import ApiKeyModal from '@/components/dashboard/ApiKeyModal';
interface Values {
diff --git a/resources/scripts/components/dashboard/search/SearchModal.tsx b/resources/scripts/components/dashboard/search/SearchModal.tsx
index c6512b8e7b..1715d28b9e 100644
--- a/resources/scripts/components/dashboard/search/SearchModal.tsx
+++ b/resources/scripts/components/dashboard/search/SearchModal.tsx
@@ -11,7 +11,7 @@ import getServers from '@/api/getServers';
import { Server } from '@/api/server/getServer';
import { ApplicationStore } from '@/state';
import { Link } from 'react-router-dom';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import tw from 'twin.macro';
import Input from '@/components/elements/Input';
import { ip } from '@/lib/formatters';
diff --git a/resources/scripts/components/dashboard/ssh/CreateSSHKeyForm.tsx b/resources/scripts/components/dashboard/ssh/CreateSSHKeyForm.tsx
index 4b4f39cbdf..7d69c3d491 100644
--- a/resources/scripts/components/dashboard/ssh/CreateSSHKeyForm.tsx
+++ b/resources/scripts/components/dashboard/ssh/CreateSSHKeyForm.tsx
@@ -6,7 +6,7 @@ import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
import tw from 'twin.macro';
import Button from '@/components/elements/Button';
import Input, { Textarea } from '@/components/elements/Input';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import { useFlashKey } from '@/plugins/useFlash';
import { createSSHKey, useSSHKeys } from '@/api/account/ssh-keys';
diff --git a/resources/scripts/components/elements/Button.tsx b/resources/scripts/components/elements/Button.tsx
index e02f00ff15..c58467415d 100644
--- a/resources/scripts/components/elements/Button.tsx
+++ b/resources/scripts/components/elements/Button.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import styled, { css } from 'styled-components/macro';
+import styled, { css } from 'styled-components';
import tw from 'twin.macro';
import Spinner from '@/components/elements/Spinner';
diff --git a/resources/scripts/components/elements/CodemirrorEditor.tsx b/resources/scripts/components/elements/CodemirrorEditor.tsx
index 99a7b5e852..3862a603e7 100644
--- a/resources/scripts/components/elements/CodemirrorEditor.tsx
+++ b/resources/scripts/components/elements/CodemirrorEditor.tsx
@@ -1,6 +1,6 @@
import React, { useCallback, useEffect, useState } from 'react';
import CodeMirror from 'codemirror';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import tw from 'twin.macro';
import modes from '@/modes';
diff --git a/resources/scripts/components/elements/ContentContainer.tsx b/resources/scripts/components/elements/ContentContainer.tsx
index 799f512d22..0ce40c416b 100644
--- a/resources/scripts/components/elements/ContentContainer.tsx
+++ b/resources/scripts/components/elements/ContentContainer.tsx
@@ -1,4 +1,4 @@
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import { breakpoint } from '@/theme';
import tw from 'twin.macro';
diff --git a/resources/scripts/components/elements/DropdownMenu.tsx b/resources/scripts/components/elements/DropdownMenu.tsx
index 0c5361a8c8..bc13a9b69d 100644
--- a/resources/scripts/components/elements/DropdownMenu.tsx
+++ b/resources/scripts/components/elements/DropdownMenu.tsx
@@ -1,5 +1,5 @@
import React, { createRef } from 'react';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import tw from 'twin.macro';
import Fade from '@/components/elements/Fade';
diff --git a/resources/scripts/components/elements/Fade.tsx b/resources/scripts/components/elements/Fade.tsx
index 41bcf0be75..c9239b06fd 100644
--- a/resources/scripts/components/elements/Fade.tsx
+++ b/resources/scripts/components/elements/Fade.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import tw from 'twin.macro';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import CSSTransition, { CSSTransitionProps } from 'react-transition-group/CSSTransition';
interface Props extends Omit {
diff --git a/resources/scripts/components/elements/GreyRowBox.tsx b/resources/scripts/components/elements/GreyRowBox.tsx
index e5a7f96859..34e221db05 100644
--- a/resources/scripts/components/elements/GreyRowBox.tsx
+++ b/resources/scripts/components/elements/GreyRowBox.tsx
@@ -1,4 +1,4 @@
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import tw from 'twin.macro';
export default styled.div<{ $hoverable?: boolean }>`
diff --git a/resources/scripts/components/elements/Input.tsx b/resources/scripts/components/elements/Input.tsx
index 677a5014d8..5ddda3dc0b 100644
--- a/resources/scripts/components/elements/Input.tsx
+++ b/resources/scripts/components/elements/Input.tsx
@@ -1,4 +1,4 @@
-import styled, { css } from 'styled-components/macro';
+import styled, { css } from 'styled-components';
import tw from 'twin.macro';
export interface Props {
diff --git a/resources/scripts/components/elements/InputSpinner.tsx b/resources/scripts/components/elements/InputSpinner.tsx
index 2ed77b433b..eb3b63e359 100644
--- a/resources/scripts/components/elements/InputSpinner.tsx
+++ b/resources/scripts/components/elements/InputSpinner.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import Spinner from '@/components/elements/Spinner';
import Fade from '@/components/elements/Fade';
import tw from 'twin.macro';
-import styled, { css } from 'styled-components/macro';
+import styled, { css } from 'styled-components';
import Select from '@/components/elements/Select';
const Container = styled.div<{ visible?: boolean }>`
diff --git a/resources/scripts/components/elements/Label.tsx b/resources/scripts/components/elements/Label.tsx
index 704e8324b5..6399289832 100644
--- a/resources/scripts/components/elements/Label.tsx
+++ b/resources/scripts/components/elements/Label.tsx
@@ -1,4 +1,4 @@
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import tw from 'twin.macro';
const Label = styled.label<{ isLight?: boolean }>`
diff --git a/resources/scripts/components/elements/Modal.tsx b/resources/scripts/components/elements/Modal.tsx
index d4f6dfece0..247bacb90f 100644
--- a/resources/scripts/components/elements/Modal.tsx
+++ b/resources/scripts/components/elements/Modal.tsx
@@ -1,7 +1,7 @@
import React, { useEffect, useMemo, useRef, useState } from 'react';
import Spinner from '@/components/elements/Spinner';
import tw from 'twin.macro';
-import styled, { css } from 'styled-components/macro';
+import styled, { css } from 'styled-components';
import { breakpoint } from '@/theme';
import Fade from '@/components/elements/Fade';
import { createPortal } from 'react-dom';
diff --git a/resources/scripts/components/elements/Pagination.tsx b/resources/scripts/components/elements/Pagination.tsx
index 7a2951f778..6491a8bd8d 100644
--- a/resources/scripts/components/elements/Pagination.tsx
+++ b/resources/scripts/components/elements/Pagination.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { PaginatedResult } from '@/api/http';
import tw from 'twin.macro';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import Button from '@/components/elements/Button';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faAngleDoubleLeft, faAngleDoubleRight } from '@fortawesome/free-solid-svg-icons';
diff --git a/resources/scripts/components/elements/ProgressBar.tsx b/resources/scripts/components/elements/ProgressBar.tsx
index c94ae80f3d..061e827c33 100644
--- a/resources/scripts/components/elements/ProgressBar.tsx
+++ b/resources/scripts/components/elements/ProgressBar.tsx
@@ -1,5 +1,5 @@
import React, { useEffect, useRef, useState } from 'react';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import { useStoreActions, useStoreState } from 'easy-peasy';
import { randomInt } from '@/helpers';
import { CSSTransition } from 'react-transition-group';
diff --git a/resources/scripts/components/elements/ScreenBlock.tsx b/resources/scripts/components/elements/ScreenBlock.tsx
index 0b57e92c6d..acff80c8b0 100644
--- a/resources/scripts/components/elements/ScreenBlock.tsx
+++ b/resources/scripts/components/elements/ScreenBlock.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import PageContentBlock from '@/components/elements/PageContentBlock';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faArrowLeft, faSyncAlt } from '@fortawesome/free-solid-svg-icons';
-import styled, { keyframes } from 'styled-components/macro';
+import styled, { keyframes } from 'styled-components';
import tw from 'twin.macro';
import Button from '@/components/elements/Button';
import NotFoundSvg from '@/assets/images/not_found.svg';
diff --git a/resources/scripts/components/elements/Select.tsx b/resources/scripts/components/elements/Select.tsx
index fc50f252d4..dfeb3e5a40 100644
--- a/resources/scripts/components/elements/Select.tsx
+++ b/resources/scripts/components/elements/Select.tsx
@@ -1,4 +1,4 @@
-import styled, { css } from 'styled-components/macro';
+import styled, { css } from 'styled-components';
import tw from 'twin.macro';
interface Props {
diff --git a/resources/scripts/components/elements/Spinner.tsx b/resources/scripts/components/elements/Spinner.tsx
index 48de135d31..5c86a89ea3 100644
--- a/resources/scripts/components/elements/Spinner.tsx
+++ b/resources/scripts/components/elements/Spinner.tsx
@@ -1,5 +1,5 @@
import React, { Suspense } from 'react';
-import styled, { css, keyframes } from 'styled-components/macro';
+import styled, { css, keyframes } from 'styled-components';
import tw from 'twin.macro';
import ErrorBoundary from '@/components/elements/ErrorBoundary';
diff --git a/resources/scripts/components/elements/SubNavigation.tsx b/resources/scripts/components/elements/SubNavigation.tsx
index 9a25b80b07..c28ae7ba31 100644
--- a/resources/scripts/components/elements/SubNavigation.tsx
+++ b/resources/scripts/components/elements/SubNavigation.tsx
@@ -1,4 +1,4 @@
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import tw, { theme } from 'twin.macro';
const SubNavigation = styled.div`
diff --git a/resources/scripts/components/elements/Switch.tsx b/resources/scripts/components/elements/Switch.tsx
index 45c7384749..841c3b7806 100644
--- a/resources/scripts/components/elements/Switch.tsx
+++ b/resources/scripts/components/elements/Switch.tsx
@@ -1,5 +1,5 @@
import React, { useMemo } from 'react';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import { v4 } from 'uuid';
import tw from 'twin.macro';
import Label from '@/components/elements/Label';
diff --git a/resources/scripts/components/elements/dialog/context.ts b/resources/scripts/components/elements/dialog/context.ts
index b9a0f09805..c779dc6631 100644
--- a/resources/scripts/components/elements/dialog/context.ts
+++ b/resources/scripts/components/elements/dialog/context.ts
@@ -1,5 +1,5 @@
import React from 'react';
-import { DialogContextType, DialogWrapperContextType } from './types';
+import type { DialogContextType, DialogWrapperContextType } from './types';
export const DialogContext = React.createContext({
setIcon: () => null,
diff --git a/resources/scripts/components/server/backups/BackupContextMenu.tsx b/resources/scripts/components/server/backups/BackupContextMenu.tsx
index 43c8b35754..3b1cde409b 100644
--- a/resources/scripts/components/server/backups/BackupContextMenu.tsx
+++ b/resources/scripts/components/server/backups/BackupContextMenu.tsx
@@ -16,7 +16,7 @@ import deleteBackup from '@/api/server/backups/deleteBackup';
import Can from '@/components/elements/Can';
import tw from 'twin.macro';
import getServerBackups from '@/api/swr/getServerBackups';
-import { ServerBackup } from '@/api/server/types';
+import type { ServerBackup } from '@/api/server/types';
import { ServerContext } from '@/state/server';
import Input from '@/components/elements/Input';
import { restoreServerBackup } from '@/api/server/backups';
diff --git a/resources/scripts/components/server/backups/BackupRow.tsx b/resources/scripts/components/server/backups/BackupRow.tsx
index f59f472bee..b2de2ee6eb 100644
--- a/resources/scripts/components/server/backups/BackupRow.tsx
+++ b/resources/scripts/components/server/backups/BackupRow.tsx
@@ -10,7 +10,7 @@ import BackupContextMenu from '@/components/server/backups/BackupContextMenu';
import tw from 'twin.macro';
import GreyRowBox from '@/components/elements/GreyRowBox';
import getServerBackups from '@/api/swr/getServerBackups';
-import { ServerBackup } from '@/api/server/types';
+import type { ServerBackup } from '@/api/server/types';
import { SocketEvent } from '@/components/server/events';
interface Props {
diff --git a/resources/scripts/components/server/files/FileDropdownMenu.tsx b/resources/scripts/components/server/files/FileDropdownMenu.tsx
index bcf3ab8706..63b1a13df3 100644
--- a/resources/scripts/components/server/files/FileDropdownMenu.tsx
+++ b/resources/scripts/components/server/files/FileDropdownMenu.tsx
@@ -14,7 +14,7 @@ import {
} from '@fortawesome/free-solid-svg-icons';
import RenameFileModal from '@/components/server/files/RenameFileModal';
import { ServerContext } from '@/state/server';
-import { join } from 'path';
+import { join } from 'pathe';
import deleteFiles from '@/api/server/files/deleteFiles';
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
import copyFile from '@/api/server/files/copyFile';
@@ -25,7 +25,7 @@ import tw from 'twin.macro';
import { FileObject } from '@/api/server/files/loadDirectory';
import useFileManagerSwr from '@/plugins/useFileManagerSwr';
import DropdownMenu from '@/components/elements/DropdownMenu';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import useEventListener from '@/plugins/useEventListener';
import compressFiles from '@/api/server/files/compressFiles';
import decompressFiles from '@/api/server/files/decompressFiles';
diff --git a/resources/scripts/components/server/files/FileEditContainer.tsx b/resources/scripts/components/server/files/FileEditContainer.tsx
index 83a3dde666..b51ede87b9 100644
--- a/resources/scripts/components/server/files/FileEditContainer.tsx
+++ b/resources/scripts/components/server/files/FileEditContainer.tsx
@@ -18,7 +18,7 @@ import useFlash from '@/plugins/useFlash';
import { ServerContext } from '@/state/server';
import ErrorBoundary from '@/components/elements/ErrorBoundary';
import { encodePathSegments, hashToPath } from '@/helpers';
-import { dirname } from 'path';
+import { dirname } from 'pathe';
import CodemirrorEditor from '@/components/elements/CodemirrorEditor';
export default () => {
diff --git a/resources/scripts/components/server/files/FileNameModal.tsx b/resources/scripts/components/server/files/FileNameModal.tsx
index 04781babec..3d0fb16862 100644
--- a/resources/scripts/components/server/files/FileNameModal.tsx
+++ b/resources/scripts/components/server/files/FileNameModal.tsx
@@ -4,7 +4,7 @@ import { Form, Formik, FormikHelpers } from 'formik';
import { object, string } from 'yup';
import Field from '@/components/elements/Field';
import { ServerContext } from '@/state/server';
-import { join } from 'path';
+import { join } from 'pathe';
import tw from 'twin.macro';
import Button from '@/components/elements/Button';
diff --git a/resources/scripts/components/server/files/FileObjectRow.tsx b/resources/scripts/components/server/files/FileObjectRow.tsx
index 5c7c9347a2..58c42cff1a 100644
--- a/resources/scripts/components/server/files/FileObjectRow.tsx
+++ b/resources/scripts/components/server/files/FileObjectRow.tsx
@@ -11,7 +11,7 @@ import tw from 'twin.macro';
import isEqual from 'react-fast-compare';
import SelectFileCheckbox from '@/components/server/files/SelectFileCheckbox';
import { usePermissions } from '@/plugins/usePermissions';
-import { join } from 'path';
+import { join } from 'pathe';
import { bytesToString } from '@/lib/formatters';
import styles from './style.module.css';
diff --git a/resources/scripts/components/server/files/NewDirectoryButton.tsx b/resources/scripts/components/server/files/NewDirectoryButton.tsx
index ff74357cf4..f7531a3689 100644
--- a/resources/scripts/components/server/files/NewDirectoryButton.tsx
+++ b/resources/scripts/components/server/files/NewDirectoryButton.tsx
@@ -2,7 +2,7 @@ import React, { useContext, useEffect, useState } from 'react';
import { ServerContext } from '@/state/server';
import { Form, Formik, FormikHelpers } from 'formik';
import Field from '@/components/elements/Field';
-import { join } from 'path';
+import { join } from 'pathe';
import { object, string } from 'yup';
import createDirectory from '@/api/server/files/createDirectory';
import tw from 'twin.macro';
diff --git a/resources/scripts/components/server/files/RenameFileModal.tsx b/resources/scripts/components/server/files/RenameFileModal.tsx
index 4f675338e1..08c99183be 100644
--- a/resources/scripts/components/server/files/RenameFileModal.tsx
+++ b/resources/scripts/components/server/files/RenameFileModal.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import Modal, { RequiredModalProps } from '@/components/elements/Modal';
import { Form, Formik, FormikHelpers } from 'formik';
import Field from '@/components/elements/Field';
-import { join } from 'path';
+import { join } from 'pathe';
import renameFiles from '@/api/server/files/renameFiles';
import { ServerContext } from '@/state/server';
import tw from 'twin.macro';
diff --git a/resources/scripts/components/server/files/SelectFileCheckbox.tsx b/resources/scripts/components/server/files/SelectFileCheckbox.tsx
index 1708fd4132..7cb78c56a4 100644
--- a/resources/scripts/components/server/files/SelectFileCheckbox.tsx
+++ b/resources/scripts/components/server/files/SelectFileCheckbox.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import tw from 'twin.macro';
import { ServerContext } from '@/state/server';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import Input from '@/components/elements/Input';
export const FileActionCheckbox = styled(Input)`
diff --git a/resources/scripts/components/server/network/AllocationRow.tsx b/resources/scripts/components/server/network/AllocationRow.tsx
index e68bc3359f..d8b38762a2 100644
--- a/resources/scripts/components/server/network/AllocationRow.tsx
+++ b/resources/scripts/components/server/network/AllocationRow.tsx
@@ -9,7 +9,7 @@ import Can from '@/components/elements/Can';
import { Button } from '@/components/elements/button/index';
import GreyRowBox from '@/components/elements/GreyRowBox';
import { Allocation } from '@/api/server/getServer';
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import { debounce } from 'debounce';
import setServerAllocationNotes from '@/api/server/network/setServerAllocationNotes';
import { useFlashKey } from '@/plugins/useFlash';
diff --git a/resources/scripts/components/server/startup/VariableBox.tsx b/resources/scripts/components/server/startup/VariableBox.tsx
index cffadd8dd7..cb0d210623 100644
--- a/resources/scripts/components/server/startup/VariableBox.tsx
+++ b/resources/scripts/components/server/startup/VariableBox.tsx
@@ -1,5 +1,5 @@
import React, { memo, useState } from 'react';
-import { ServerEggVariable } from '@/api/server/types';
+import type { ServerEggVariable } from '@/api/server/types';
import TitledGreyBox from '@/components/elements/TitledGreyBox';
import { usePermissions } from '@/plugins/usePermissions';
import InputSpinner from '@/components/elements/InputSpinner';
diff --git a/resources/scripts/components/server/users/PermissionRow.tsx b/resources/scripts/components/server/users/PermissionRow.tsx
index 6fdd22fe85..8055a01698 100644
--- a/resources/scripts/components/server/users/PermissionRow.tsx
+++ b/resources/scripts/components/server/users/PermissionRow.tsx
@@ -1,4 +1,4 @@
-import styled from 'styled-components/macro';
+import styled from 'styled-components';
import tw from 'twin.macro';
import Checkbox from '@/components/elements/Checkbox';
import React from 'react';
diff --git a/resources/scripts/i18n.ts b/resources/scripts/i18n.ts
index c36879eab3..2cb6565583 100644
--- a/resources/scripts/i18n.ts
+++ b/resources/scripts/i18n.ts
@@ -6,7 +6,7 @@ import I18NextMultiloadBackendAdapter from 'i18next-multiload-backend-adapter';
// If we're using HMR use a unique hash per page reload so that we're always
// doing cache busting. Otherwise just use the builder provided hash value in
// the URL to allow cache busting to occur whenever the front-end is rebuilt.
-const hash = module.hot ? Date.now().toString(16) : process.env.WEBPACK_BUILD_HASH;
+const hash = Date.now().toString(16);
i18n.use(I18NextMultiloadBackendAdapter)
.use(initReactI18next)
diff --git a/resources/scripts/index.tsx b/resources/scripts/index.tsx
index 2aade24755..cc18105514 100644
--- a/resources/scripts/index.tsx
+++ b/resources/scripts/index.tsx
@@ -1,16 +1,8 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from '@/components/App';
-import { setConfig } from 'react-hot-loader';
// Enable language support.
import './i18n';
-// Prevents page reloads while making component changes which
-// also avoids triggering constant loading indicators all over
-// the place in development.
-//
-// @see https://github.com/gaearon/react-hot-loader#hook-support
-setConfig({ reloadHooks: false });
-
ReactDOM.render(, document.getElementById('app'));
diff --git a/resources/scripts/lib/formatters.spec.ts b/resources/scripts/lib/formatters.spec.ts
index c03008971b..67604f940e 100644
--- a/resources/scripts/lib/formatters.spec.ts
+++ b/resources/scripts/lib/formatters.spec.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
import { bytesToString, ip, mbToBytes } from '@/lib/formatters';
describe('@/lib/formatters.ts', function () {
diff --git a/resources/scripts/lib/helpers.spec.ts b/resources/scripts/lib/helpers.spec.ts
index 6d18e7e3df..c719c60fb8 100644
--- a/resources/scripts/lib/helpers.spec.ts
+++ b/resources/scripts/lib/helpers.spec.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
import { hexToRgba } from '@/lib/helpers';
describe('@/lib/helpers.ts', function () {
diff --git a/resources/scripts/lib/objects.spec.ts b/resources/scripts/lib/objects.spec.ts
index 330b6e954f..ce4f9c4940 100644
--- a/resources/scripts/lib/objects.spec.ts
+++ b/resources/scripts/lib/objects.spec.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
import { isObject } from '@/lib/objects';
describe('@/lib/objects.ts', function () {
diff --git a/resources/scripts/lib/strings.spec.ts b/resources/scripts/lib/strings.spec.ts
index 8875ce2174..86b42b1838 100644
--- a/resources/scripts/lib/strings.spec.ts
+++ b/resources/scripts/lib/strings.spec.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
import { capitalize } from '@/lib/strings';
describe('@/lib/strings.ts', function () {
diff --git a/resources/views/templates/wrapper.blade.php b/resources/views/templates/wrapper.blade.php
index aba562c479..8a232f884a 100644
--- a/resources/views/templates/wrapper.blade.php
+++ b/resources/views/templates/wrapper.blade.php
@@ -34,6 +34,9 @@
@yield('assets')
@include('layouts.scripts')
+
+ @viteReactRefresh
+ @vite('resources/scripts/index.tsx')
@section('content')
@@ -41,8 +44,5 @@
@yield('container')
@yield('below-container')
@show
- @section('scripts')
- {!! $asset->js('main.js') !!}
- @show