Repository: ProvableHQ/sdk (language: rust)

Issue:
[Proposal] Improve HMR performance of aleo.tools
## 💥 Proposal

Improve https://aleo.tools compile time and hot module reload time.

Currently takes me over 3 seconds to compile and hot reload the aleo.tools dev environment but we should be able to get that down to ~100ms by doing the following:

- Switching to [Vite](https://vitejs.dev/) 
- Upgrading to React 18
- Integrating [SWC](https://swc.rs/)


Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index e30608f6d..f105cc27e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,6 @@ storage*/
 rust/src/.DS_Store
 rust/src/program/.DS_Store
 
+
+# Local Netlify folder
+.netlify
diff --git a/website/.eslintrc.cjs b/website/.eslintrc.cjs
new file mode 100644
index 000000000..ec601b2ce
--- /dev/null
+++ b/website/.eslintrc.cjs
@@ -0,0 +1,15 @@
+module.exports = {
+  env: { browser: true, es2020: true },
+  extends: [
+    'eslint:recommended',
+    'plugin:react/recommended',
+    'plugin:react/jsx-runtime',
+    'plugin:react-hooks/recommended',
+  ],
+  parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
+  settings: { react: { version: '18.2' } },
+  plugins: ['react-refresh'],
+  rules: {
+    'react-refresh/only-export-components': 'warn',
+  },
+}
diff --git a/website/.gitignore b/website/.gitignore
new file mode 100644
index 000000000..a547bf36d
--- /dev/null
+++ b/website/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/website/README.md b/website/README.md
index 6208f214b..b15263120 100644
--- a/website/README.md
+++ b/website/README.md
@@ -1,70 +1,31 @@
 # Aleo SDK Website
 
-This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
+This project was bootstrapped with [Vite](https://vitejs.dev/).
 
-## Available Scripts
-
-In the project directory, you can run:
-
-### `yarn start`
-
-Runs the app in the development mode.\
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
-
-The page will reload if you make edits.\
-You will also see any lint errors in the console.
-
-### `yarn test`
-
-Launches the test runner in the interactive watch mode.\
-See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
-
-### `yarn build`
-
-Builds the app for production to the `build` folder.\
-It correctly bundles React in production mode and optimizes the build for the best performance.
-
-The build is minified and the filenames include the hashes.\
-Your app is ready to be deployed!
-
-See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
+## Getting Started
 
-### `yarn eject`
+### Prerequisites
 
-**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
+- Follow [SDK Build Guide](https://github.com/AleoHQ/sdk#2-build-guide) to get Rust installed
+- Nodejs `18` or `20`. Install through [official website](https://nodejs.org/) or via a node manager like [NVM](https://github.com/creationix/nvm)
 
-If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
+```bash
+rustup component add rust-src --toolchain nightly-2023-05-24-aarch64-apple-darwin
+npm install
+npm run dev
+```
 
-Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
+Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
 
-You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
-
-## Learn More
-
-You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
-
-To learn React, check out the [React documentation](https://reactjs.org/).
-
-### Code Splitting
-
-This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
-
-### Analyzing the Bundle Size
-
-This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
-
-### Making a Progressive Web App
-
-This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
-
-### Advanced Configuration
+## Available Scripts
 
-This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
+In the project directory, you can run:
 
-### Deployment
+### `preview:netlify`
 
-This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
+Locally preview production build.
 
-### `yarn build` fails to minify
+### `npm run build`
 
-This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
+Builds the app for production to the `dist` folder.\
+It correctly bundles React in production mode and optimizes the build for the best performance.
\ No newline at end of file
diff --git a/website/index.html b/website/index.html
new file mode 100644
index 000000000..501269a33
--- /dev/null
+++ b/website/index.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8" />
+  <link rel="icon" href="public/favicon.ico" />
+  <meta name="viewport" content="width=device-width, initial-scale=1" />
+  <meta name="theme-color" content="#000000" />
+  <meta
+          name="description"
+          content="A Software Development Kit (SDK) for Zero-Knowledge Transactions"
+  />
+  <link rel="apple-touch-icon" href="public/logo129.png" />
+  <link rel="manifest" href="public/manifest.json" />
+  <title>Aleo SDK</title>
+</head>
+<body>
+<noscript>You need to enable JavaScript to run this app.</noscript>
+<div id="root"></div>
+<script type="module" src="/src/index.jsx"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/website/package.json b/website/package.json
index c7c843cb9..e90af05b5 100644
--- a/website/package.json
+++ b/website/package.json
@@ -2,6 +2,16 @@
   "name": "aleo-website",
   "version": "0.1.0",
   "private": true,
+  "type": "module",
+  "scripts": {
+    "preinstall": "cd ../wasm && export RUSTFLAGS='-C target-feature=+atomics,+bulk-memory,+mutable-globals -C link-arg=--max-memory=4294967296' && rustup run nightly-2023-05-24 wasm-pack build --release --target web --out-dir pkg-parallel -- --features \"parallel, browser\" --no-default-features -Z build-std=panic_abort,std",
+    "dev": "vite",
+    "build": "webpack --config webpack.config.js",
+    "build:vite": "vite build",
+    "lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0",
+    "preview": "vite preview",
+    "preview:netlify": "npm run build && netlify dev --dir=dist"
+  },
   "dependencies": {
     "@aleohq/ui": "^0.0.9",
     "@aleohq/wasm": "file:../wasm/pkg-parallel",
@@ -11,48 +21,30 @@
     "babel-loader": "^8.2.3",
     "copy-to-clipboard": "^3.3.1",
     "gh-pages": "^3.1.0",
-    "react": "^17.0.1",
-    "react-dom": "^17.0.1",
+    "react": "^18.2.0",
+    "react-dom": "^18.2.0",
     "web-vitals": "^0.2.4"
   },
   "devDependencies": {
     "@babel/core": "^7.17.2",
     "@babel/preset-env": "^7.16.11",
     "@babel/preset-react": "^7.16.7",
-    "@wasm-tool/wasm-pack-plugin": "^1.3.1",
+    "@types/react": "^18.0.37",
+    "@types/react-dom": "^18.0.11",
+    "@vitejs/plugin-react-swc": "^3.0.0",
     "copy-webpack-plugin": "^11.0.0",
     "css-loader": "^6.6.0",
+    "eslint": "^8.38.0",
+    "eslint-plugin-react": "^7.32.2",
+    "eslint-plugin-react-hooks": "^4.6.0",
+    "eslint-plugin-react-refresh": "^0.3.4",
     "html-webpack-plugin": "^5.5.0",
     "mini-css-extract-plugin": "^2.5.3",
+    "netlify-cli": "^15.7.0",
     "style-loader": "^3.3.1",
+    "vite": "^4.3.9",
     "webpack": "^5.76.0",
-    "webpack-cli": "^4.9.2",
-    "webpack-dev-server": "^4.7.4"
-  },
-  "scripts": {
-    "preinstall": "cd ../wasm && export RUSTFLAGS='-C target-feature=+atomics,+bulk-memory,+mutable-globals -C link-arg=--max-memory=4294967296' && rustup run nightly-2023-05-24 wasm-pack build --release --target web --out-dir pkg-parallel -- --features \"parallel, browser\" --no-default-features -Z build-std=panic_abort,std",
-    "start": "webpack-dev-server",
-    "build": "webpack --config webpack.config.js",
-    "predeploy": "yarn build",
-    "deploy": "gh-pages -d build",
-    "clean": "rm -rf nodeg_modules"
-  },
-  "eslintConfig": {
-    "extends": [
-      "react-app"
-    ]
-  },
-  "browserslist": {
-    "production": [
-      ">0.2%",
-      "not dead",
-      "not op_mini all"
-    ],
-    "development": [
-      "last 1 chrome version",
-      "last 1 firefox version",
-      "last 1 safari version"
-    ]
+    "webpack-cli": "^5.1.4"
   },
   "homepage": "https://aleo.tools"
 }
diff --git a/website/public/index.html b/website/public/index.html
deleted file mode 100644
index 15b749de3..000000000
--- a/website/public/index.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="utf-8" />
-    <link rel="icon" href="public/favicon.ico" />
-    <meta name="viewport" content="width=device-width, initial-scale=1" />
-    <meta name="theme-color" content="#000000" />
-    <meta
-      name="description"
-      content="A Software Development Kit (SDK) for Zero-Knowledge Transactions"
-    />
-    <link rel="apple-touch-icon" href="public/logo129.png" />
-    <!--
-      manifest.json provides metadata used when your web app is installed on a
-      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-    -->
-    <link rel="manifest" href="public/manifest.json" />
-    <!--
-      Notice the use of %PUBLIC_URL% in the tags above.
-      It will be replaced with the URL of the `public` folder during the build.
-      Only files inside the `public` folder can be referenced from the HTML.
-
-      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
-      work correctly both with client-side routing and a non-root public URL.
-      Learn how to configure a non-root public URL by running `npm run build`.
-    -->
-    <title>Aleo SDK</title>
-  </head>
-  <body>
-    <noscript>You need to enable JavaScript to run this app.</noscript>
-    <div id="root"></div>
-    <!--
-      This HTML file is a template.
-      If you open it directly in the browser, you will see an empty page.
-
-      You can add webfonts, meta tags, or analytics to this file.
-      The build step will place the bundled scripts into the <body> tag.
-
-      To begin the development, run `npm start` or `yarn start`.
-      To create a production bundle, use `npm run build` or `yarn build`.
-    -->
-  </body>
-</html>
diff --git a/website/src/App.js b/website/src/App.jsx
similarity index 100%
rename from website/src/App.js
rename to website/src/App.jsx
diff --git a/website/src/components/CopyButton.js b/website/src/components/CopyButton.jsx
similarity index 100%
rename from website/src/components/CopyButton.js
rename to website/src/components/CopyButton.jsx
diff --git a/website/src/components/InputForm.js b/website/src/components/InputForm.jsx
similarity index 100%
rename from website/src/components/InputForm.js
rename to website/src/components/InputForm.jsx
diff --git a/website/src/index.js b/website/src/index.jsx
similarity index 77%
rename from website/src/index.js
rename to website/src/index.jsx
index 4dcc3bea6..dbc4a17f0 100644
--- a/website/src/index.js
+++ b/website/src/index.jsx
@@ -1,15 +1,16 @@
 import React from 'react';
-import ReactDOM from 'react-dom';
 import './index.css';
 import App from './App';
+import { createRoot } from 'react-dom/client';
 
 import '@aleohq/ui/dist/bundle.css';
 
-ReactDOM.render(
-  <React.StrictMode>
-    <App />
-  </React.StrictMode>,
-  document.getElementById('root')
+const container = document.getElementById('root');
+const root = createRoot(container);
+root.render(
+    <React.StrictMode>
+        <App />
+    </React.StrictMode>
 );
 
 const reportWebVitals = onPerfEntry => {
diff --git a/website/src/tabs/account/AccountFromPrivateKey.js b/website/src/tabs/account/AccountFromPrivateKey.jsx
similarity index 100%
rename from website/src/tabs/account/AccountFromPrivateKey.js
rename to website/src/tabs/account/AccountFromPrivateKey.jsx
diff --git a/website/src/tabs/account/NewAccount.js b/website/src/tabs/account/NewAccount.jsx
similarity index 100%
rename from website/src/tabs/account/NewAccount.js
rename to website/src/tabs/account/NewAccount.jsx
diff --git a/website/src/tabs/account/SignMessage.js b/website/src/tabs/account/SignMessage.jsx
similarity index 100%
rename from website/src/tabs/account/SignMessage.js
rename to website/src/tabs/account/SignMessage.jsx
diff --git a/website/src/tabs/account/VerifyMessage.js b/website/src/tabs/account/VerifyMessage.jsx
similarity index 97%
rename from website/src/tabs/account/VerifyMessage.js
rename to website/src/tabs/account/VerifyMessage.jsx
index a048ffe04..17f01a260 100644
--- a/website/src/tabs/account/VerifyMessage.js
+++ b/website/src/tabs/account/VerifyMessage.jsx
@@ -55,9 +55,10 @@ export const VerifyMessage = () => {
     const layout = {labelCol: {span: 3}, wrapperCol: {span: 21}};
     useEffect(() => {
         if ( !didMount.current ) {
-            return didMount.current = true;
+            didMount.current = true;
+        } else {
+            attemptVerify()
         }
-        attemptVerify()
     }, [messageInput, signatureInput, inputAddress, verified]);
     if (aleo !== null) {
         const messageString = () => messageInput !== null ? messageInput.toString() : "";
diff --git a/website/src/tabs/advanced/DecryptAccount.js b/website/src/tabs/advanced/DecryptAccount.jsx
similarity index 100%
rename from website/src/tabs/advanced/DecryptAccount.js
rename to website/src/tabs/advanced/DecryptAccount.jsx
diff --git a/website/src/tabs/advanced/EncryptAccount.js b/website/src/tabs/advanced/EncryptAccount.jsx
similarity index 100%
rename from website/src/tabs/advanced/EncryptAccount.js
rename to website/src/tabs/advanced/EncryptAccount.jsx
diff --git a/website/src/tabs/develop/Deploy.js b/website/src/tabs/develop/Deploy.jsx
similarity index 98%
rename from website/src/tabs/develop/Deploy.js
rename to website/src/tabs/develop/Deploy.jsx
index 402e57162..2dd1276c1 100644
--- a/website/src/tabs/develop/Deploy.js
+++ b/website/src/tabs/develop/Deploy.jsx
@@ -18,7 +18,10 @@ export const Deploy = () => {
     const [transactionID, setTransactionID] = useState(null);
     const [worker, setWorker] = useState(null);
     function spawnWorker() {
-        let worker = new Worker("./worker.js");
+        let worker = new Worker(
+            new URL('../../workers/worker.js', import.meta.url),
+            {type: 'module'}
+        );
         worker.addEventListener("message", ev => {
             if (ev.data.type == 'DEPLOY_TRANSACTION_COMPLETED') {
                 let [deployTransaction, url] = ev.data.deployTransaction;
diff --git a/website/src/tabs/develop/Execute.js b/website/src/tabs/develop/Execute.jsx
similarity index 99%
rename from website/src/tabs/develop/Execute.js
rename to website/src/tabs/develop/Execute.jsx
index ec3eb4f34..5514f623a 100644
--- a/website/src/tabs/develop/Execute.js
+++ b/website/src/tabs/develop/Execute.jsx
@@ -49,7 +49,10 @@ export const Execute = () => {
     }
 
     function spawnWorker() {
-        let worker = new Worker("./worker.js");
+        let worker = new Worker(
+            new URL('../../workers/worker.js', import.meta.url),
+            {type: 'module'}
+        );
         worker.addEventListener("message", ev => {
             if (ev.data.type == 'OFFLINE_EXECUTION_COMPLETED') {
                 setLoading(false);
diff --git a/website/src/tabs/develop/Join.js b/website/src/tabs/develop/Join.jsx
similarity index 98%
rename from website/src/tabs/develop/Join.js
rename to website/src/tabs/develop/Join.jsx
index e6821495b..bbf05fa06 100644
--- a/website/src/tabs/develop/Join.js
+++ b/website/src/tabs/develop/Join.jsx
@@ -16,7 +16,10 @@ export const Join = () => {
     const [worker, setWorker] = useState(null);
 
     function spawnWorker() {
-        let worker = new Worker("./worker.js");
+        let worker = new Worker(
+            new URL('../../workers/worker.js', import.meta.url),
+            {type: 'module'}
+        );
         worker.addEventListener("message", ev => {
             if (ev.data.type == 'JOIN_TRANSACTION_COMPLETED') {
                 let [transaction, url] = ev.data.joinTransaction
diff --git a/website/src/tabs/develop/Split.js b/website/src/tabs/develop/Split.jsx
similarity index 98%
rename from website/src/tabs/develop/Split.js
rename to website/src/tabs/develop/Split.jsx
index 4f52de9f0..91eb1b47b 100644
--- a/website/src/tabs/develop/Split.js
+++ b/website/src/tabs/develop/Split.jsx
@@ -14,7 +14,10 @@ export const Split = () => {
     const [worker, setWorker] = useState(null);
 
     function spawnWorker() {
-        let worker = new Worker("./worker.js");
+        let worker = new Worker(
+            new URL('../../workers/worker.js', import.meta.url),
+            {type: 'module'}
+        );
         worker.addEventListener("message", ev => {
             if (ev.data.type == 'SPLIT_TRANSACTION_COMPLETED') {
                 let [transaction, url] = ev.data.splitTransaction;
diff --git a/website/src/tabs/develop/Transfer.js b/website/src/tabs/develop/Transfer.jsx
similarity index 98%
rename from website/src/tabs/develop/Transfer.js
rename to website/src/tabs/develop/Transfer.jsx
index 6f31b05a6..146dffd0c 100644
--- a/website/src/tabs/develop/Transfer.js
+++ b/website/src/tabs/develop/Transfer.jsx
@@ -18,7 +18,10 @@ export const Transfer = () => {
     const [provingKey, setProvingKey] = useState(null);
 
     function spawnWorker() {
-        let worker = new Worker("./worker.js");
+        let worker = new Worker(
+            new URL('../../workers/worker.js', import.meta.url),
+            {type: 'module'}
+        );
         worker.addEventListener("message", ev => {
             if (ev.data.type == 'TRANSFER_TRANSACTION_COMPLETED') {
                 let [transaction, url] = ev.data.transferTransaction
diff --git a/website/src/tabs/record/DecryptRecord.js b/website/src/tabs/record/DecryptRecord.jsx
similarity index 100%
rename from website/src/tabs/record/DecryptRecord.js
rename to website/src/tabs/record/DecryptRecord.jsx
diff --git a/website/src/tabs/rest/GetBlockByHash.js b/website/src/tabs/rest/GetBlockByHash.jsx
similarity index 100%
rename from website/src/tabs/rest/GetBlockByHash.js
rename to website/src/tabs/rest/GetBlockByHash.jsx
diff --git a/website/src/tabs/rest/GetBlockByHeight.js b/website/src/tabs/rest/GetBlockByHeight.jsx
similarity index 100%
rename from website/src/tabs/rest/GetBlockByHeight.js
rename to website/src/tabs/rest/GetBlockByHeight.jsx
diff --git a/website/src/tabs/rest/GetProgram.js b/website/src/tabs/rest/GetProgram.jsx
similarity index 100%
rename from website/src/tabs/rest/GetProgram.js
rename to website/src/tabs/rest/GetProgram.jsx
diff --git a/website/src/tabs/rest/GetTransaction.js b/website/src/tabs/rest/GetTransaction.jsx
similarity index 100%
rename from website/src/tabs/rest/GetTransaction.js
rename to website/src/tabs/rest/GetTransaction.jsx
diff --git a/website/src/workers/worker.js b/website/src/workers/worker.js
index d2098b87c..45ad00406 100644
--- a/website/src/workers/worker.js
+++ b/website/src/workers/worker.js
@@ -2,7 +2,7 @@ import init, * as aleo from '@aleohq/wasm';
 import { FEE_PROVER_URL, FEE_VERIFIER_URL, JOIN_PROVER_URL, JOIN_VERIFIER_URL, SPLIT_PROVER_URL, SPLIT_VERIFIER_URL,
     TRANSFER_PRIVATE_PROVER_URL, TRANSFER_PRIVATE_VERIFIER_URL, TRANSFER_PRIVATE_TO_PUBLIC_PROVER_URL,
 TRANSFER_PRIVATE_TO_PUBLIC_VERIFIER_URL, TRANSFER_PUBLIC_PROVER_URL, TRANSFER_PUBLIC_VERIFIER_URL,
-    TRANSFER_PUBLIC_TO_PRIVATE_PROVER_URL, TRANSFER_PUBLIC_TO_PRIVATE_VERIFIER_URL} from './keys';
+    TRANSFER_PUBLIC_TO_PRIVATE_PROVER_URL, TRANSFER_PUBLIC_TO_PRIVATE_VERIFIER_URL} from './keys.js';
 
 let feeProvingKey = null;
 let feeVerifyingKey = null;
diff --git a/website/vite.config.js b/website/vite.config.js
new file mode 100644
index 000000000..c2ccfc8f1
--- /dev/null
+++ b/website/vite.config.js
@@ -0,0 +1,26 @@
+import {defineConfig, searchForWorkspaceRoot} from 'vite'
+import react from '@vitejs/plugin-react-swc'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+  worker: {
+    format: "es"
+  },
+  plugins: [react()],
+  build: {
+    target: 'esnext',
+    sourcemap: true,
+  },
+  server: {
+    fs: {
+      allow: [
+        searchForWorkspaceRoot(process.cwd()),
+        '../wasm',
+      ],
+    },
+    headers: {
+      'Cross-Origin-Opener-Policy': 'same-origin',
+      'Cross-Origin-Embedder-Policy': 'require-corp'
+    },
+  },
+})
diff --git a/website/webpack.config.js b/website/webpack.config.js
index a24d9c8c7..380b78af2 100644
--- a/website/webpack.config.js
+++ b/website/webpack.config.js
@@ -1,16 +1,21 @@
-const path = require('path')
-const HtmlWebpackPlugin = require('html-webpack-plugin')
-const CopyPlugin = require("copy-webpack-plugin");
+import CopyPlugin from "copy-webpack-plugin";
+
+import HtmlWebpackPlugin from "html-webpack-plugin";
+
+import path from "path";
 
 const appConfig = {
     mode: 'production',
     entry: {
-        index: './src/index.js'
+        index: './src/index.jsx'
     },
     output: {
-        path: path.join(__dirname, '/dist'),
+        path: path.resolve('dist'),
         filename: '[name].bundle.js'
     },
+    resolve: {
+        extensions: [".js", ".wasm", ".jsx"]
+    },
     devServer: {
         port: 3000,
         headers: {
@@ -44,7 +49,7 @@ const appConfig = {
         }),
         new HtmlWebpackPlugin(
             {
-                template: './public/index.html'
+                template: './index.html'
             }),
     ],
     performance: {
@@ -62,22 +67,4 @@ const appConfig = {
     devtool: 'source-map',
 }
 
-const workerConfig = {
-    mode: 'production',
-    entry: "./src/workers/worker.js",
-    target: "webworker",
-    resolve: {
-        extensions: [".js", ".wasm"]
-    },
-    output: {
-        path: path.join(__dirname, '/dist'),
-        filename: "worker.js"
-    },
-    experiments: {
-        asyncWebAssembly: true,
-        topLevelAwait: true
-    },
-    devtool: 'source-map',
-};
-
-module.exports = [appConfig, workerConfig];
\ No newline at end of file
+export default [appConfig];
\ No newline at end of file


Test patch:
diff --git a/website/src/App.test.js b/website/src/App.test.jsx
similarity index 100%
rename from website/src/App.test.js
rename to website/src/App.test.jsx
diff --git a/website/src/tabs/rest/GetLatestBlock.js b/website/src/tabs/rest/GetLatestBlock.jsx
similarity index 100%
rename from website/src/tabs/rest/GetLatestBlock.js
rename to website/src/tabs/rest/GetLatestBlock.jsx
diff --git a/website/src/tabs/rest/GetLatestBlockHeight.js b/website/src/tabs/rest/GetLatestBlockHeight.jsx
similarity index 100%
rename from website/src/tabs/rest/GetLatestBlockHeight.js
rename to website/src/tabs/rest/GetLatestBlockHeight.jsx