diff --git a/client/package.json b/client/package.json index 1acdd43..7eaf34a 100644 --- a/client/package.json +++ b/client/package.json @@ -5,25 +5,27 @@ "description": "tech tools hosted on cloudflare worker", "main": "index.js", "scripts": { - "build": "npm run compilehbs && npm run transpilehbs && rm src/*-original.js", - "compilehbs": "handlebars -e hbs -f src/pages-original.js src/views/pages/ && handlebars -e hbs -p -f src/partials-original.js src/views/partials/", + "build": "webpack", "deploy": "wrangler deploy src/index.js", "prepare": "husky", - "start": "wrangler dev src/index.js", - "test": "echo \"Error: no test specified\" && exit 1", - "transpilehbs": "hbs-import-transpile src/pages-original.js > assets/pages.js && hbs-import-transpile src/partials-original.js > assets/partials.js" + "start": "wrangler dev src/index.js" }, - "type": "module", "author": "", "license": "ISC", "devDependencies": { - "hbs-import-transpile": "^1.0.4" + "@babel/core": "^7.24.8", + "@babel/preset-env": "^7.24.8", + "@babel/preset-react": "^7.24.7", + "babel-loader": "^9.1.3", + "webpack": "^5.93.0", + "webpack-cli": "^5.1.4" }, "dependencies": { + "@cloudflare/kv-asset-handler": "^0.3.4", "buffer": "^6.0.3", - "handlebars": "^4.7.8", - "hbs-async-render": "^1.0.1", "itty-router": "^2.6.6", + "react": "^18.3.1", + "react-dom": "^18.3.1", "serverless-cloudflare-workers": "^1.2.0" } } diff --git a/client/src/App.js b/client/src/App.js new file mode 100644 index 0000000..6b7e81f --- /dev/null +++ b/client/src/App.js @@ -0,0 +1,16 @@ +import React, { useState } from 'react'; + +function App() { + const [count, setCount] = useState(0); + + return ( +
+

Hello, Cloudflare Workers!

+

This is a basic React page deployed on Cloudflare Workers.

+

Count: {count}

+ +
+ ); +} + +export default App; diff --git a/client/src/index.js b/client/src/index.js index fda9fb6..735ecda 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -1,29 +1,56 @@ -import { Router } from 'itty-router' -import { base64Handler, postHandler, rootHandler } from './routers' -import { registerHBHelper } from './utils/hbsAsyncHelper.js' -import '../assets/pages.js'; -import '../assets/partials.js'; +import { Router } from 'itty-router'; +import { getAssetFromKV } from '@cloudflare/kv-asset-handler'; -// Register HB -registerHBHelper(); - -// Create a new router const router = Router(); -router.get("/", rootHandler); -router.get("/base64/:text", base64Handler); -router.post("/post", postHandler); -/** - * This is the last route we define, it will match anything that hasn't hit a route we've defined - * above, therefore it's useful as a 404 (and avoids us hitting worker exceptions, so make sure - * to include it!). -*/ -router.all("*", () => new Response("404, not found!", { status: 404 })); +// Serve the React app +router.get('/', async () => { + // const html = ReactDOMServer.renderToString(); + return new Response(` + + + + + React App on Cloudflare Workers + + + + +
+ + + + `, { + headers: { + 'Content-Type': 'text/html', + }, + }); +}); -/** - * This snippet ties our worker to the router we defined above, all incoming requests - * are passed to the router where your routes are called and the response is sent. -*/ -addEventListener('fetch', (e) => { - e.respondWith(router.handle(e.request)) +// Respond to fetch events with the router +addEventListener('fetch', event => { + // Pass the entire event object to handleAssetRequest function + event.respondWith(handleAssetRequest(event)); }); + +async function handleAssetRequest(event) { + // Extract the request from the event + const request = event.request; + + // Check if the request is for bundle.js + if (request.url.endsWith('/bundle.js') || request.url.endsWith('/favicon.ico')) { + // Serve the bundle.js file from KV storage + try { + // Pass the entire event object to getAssetFromKV + return await getAssetFromKV(event); + } catch (e) { + return new Response(`Bundle not found: ${e.message}`, { + status: 404, + statusText: 'Not Found', + }); + } + } + + // For any other requests, handle them with the router + return router.handle(request); +} diff --git a/client/src/main.js b/client/src/main.js new file mode 100644 index 0000000..3ee9c5d --- /dev/null +++ b/client/src/main.js @@ -0,0 +1,6 @@ +import App from './App'; +import { createRoot } from 'react-dom/client'; + +// Render your React component instead +const root = createRoot(document.getElementById('root')); +root.render(); diff --git a/client/webpack.config.js b/client/webpack.config.js new file mode 100644 index 0000000..1227552 --- /dev/null +++ b/client/webpack.config.js @@ -0,0 +1,24 @@ +const path = require('path'); + +module.exports = { + mode: 'production', + entry: './src/main.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist'), + }, + module: { + rules: [ + { + test: /\.js$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'], + }, + }, + }, + ], + }, +}; diff --git a/client/wrangler.toml b/client/wrangler.toml index 52d77b7..f0d3b68 100644 --- a/client/wrangler.toml +++ b/client/wrangler.toml @@ -2,11 +2,14 @@ name = "tech" account_id = "**********" workers_dev = true compatibility_date = "2024-07-11" +main = "index.js" + +[site] +bucket = "./dist" + +[build] +command = "npm run build" [route] pattern = "**********" custom_domain = true - -[build] -command="npm run build" -watch_dir="views/" \ No newline at end of file