diff --git a/.fly/nginx/nginx.conf b/.fly/nginx/nginx.conf index e457fbf..8f61bbd 100644 --- a/.fly/nginx/nginx.conf +++ b/.fly/nginx/nginx.conf @@ -65,4 +65,3 @@ http { include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } - diff --git a/.fly/nginx/sites-available/default b/.fly/nginx/sites-available/default index 84ad5ab..0398316 100644 --- a/.fly/nginx/sites-available/default +++ b/.fly/nginx/sites-available/default @@ -57,6 +57,4 @@ deny all; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; -client_header_buffer_size 4k; -large_client_header_buffers 4 32k; } diff --git a/.fly/php/packages/8.4.txt b/.fly/php/packages/8.4.txt new file mode 100644 index 0000000..eb5bc85 --- /dev/null +++ b/.fly/php/packages/8.4.txt @@ -0,0 +1,16 @@ +php8.4-bcmath +php8.4-cli +php8.4-common +php8.4-curl +php8.4-gd +php8.4-intl +php8.4-mbstring +php8.4-mysql +php8.4-pgsql +php8.4-redis +php8.4-soap +php8.4-sqlite3 +php8.4-xml +php8.4-zip +php8.4-swoole +php8.4-fpm diff --git a/Dockerfile b/Dockerfile index 5bc96c9..876e6fe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,11 @@ # syntax = docker/dockerfile:experimental -ARG PHP_VERSION=8.2 -ARG NODE_VERSION=18 +ARG PHP_VERSION=8.4 +ARG NODE_VERSION=22.12 FROM ubuntu:22.04 as base LABEL fly_launch_runtime="laravel" -# PHP_VERSION needs to be repeated here -# See https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact +# Re-define PHP_VERSION after FROM ARG PHP_VERSION ENV DEBIAN_FRONTEND=noninteractive \ COMPOSER_ALLOW_SUPERUSER=1 \ @@ -32,11 +31,10 @@ COPY .fly/php/ondrej_ubuntu_php.gpg /etc/apt/trusted.gpg.d/ondrej_ubuntu_php.gpg ADD .fly/php/packages/${PHP_VERSION}.txt /tmp/php-packages.txt RUN apt-get update \ - && apt-get install -y --no-install-recommends gnupg2 ca-certificates git-core curl zip unzip \ - rsync vim-tiny htop sqlite3 nginx supervisor cron \ + && apt-get install -y --no-install-recommends gnupg2 ca-certificates git-core curl zip unzip rsync vim-tiny htop sqlite3 nginx supervisor cron \ && ln -sf /usr/bin/vim.tiny /etc/alternatives/vim \ && ln -sf /etc/alternatives/vim /usr/bin/vim \ - && echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu jammy main" > /etc/apt/sources.list.d/ondrej-ubuntu-php-focal.list \ + && echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu jammy main" > /etc/apt/sources.list.d/ondrej-ubuntu-php.list \ && apt-get update \ && apt-get -y --no-install-recommends install $(cat /tmp/php-packages.txt) \ && ln -sf /usr/sbin/php-fpm${PHP_VERSION} /usr/sbin/php-fpm \ @@ -44,7 +42,7 @@ RUN apt-get update \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* -# 2. Copy config files to proper locations +# 2. Copy config files COPY .fly/nginx/ /etc/nginx/ COPY .fly/fpm/ /etc/php/${PHP_VERSION}/fpm/ COPY .fly/supervisor/ /etc/supervisor/ @@ -52,7 +50,7 @@ COPY .fly/entrypoint.sh /entrypoint COPY .fly/start-nginx.sh /usr/local/bin/start-nginx RUN chmod 754 /usr/local/bin/start-nginx -# 3. Copy application code, skipping files based on .dockerignore +# 3. Copy application code COPY . /var/www/html WORKDIR /var/www/html @@ -63,50 +61,53 @@ RUN composer install --optimize-autoloader --no-dev \ && chown -R www-data:www-data /var/www/html \ && echo "MAILTO=\"\"\n* * * * * www-data /usr/bin/php /var/www/html/artisan schedule:run" > /etc/cron.d/laravel \ && sed -i='' '/->withMiddleware(function (Middleware \$middleware) {/a\ - \$middleware->trustProxies(at: "*");\ + $middleware->trustProxies(at: "*");\ ' bootstrap/app.php; \ if [ -d .fly ]; then cp .fly/entrypoint.sh /entrypoint; chmod +x /entrypoint; fi; +RUN rm -rf /etc/supervisor/conf.d/fpm.conf; \ + mv /etc/supervisor/octane-swoole.conf /etc/supervisor/conf.d/octane-swoole.conf; \ + rm /etc/nginx/sites-enabled/default; \ + ln -sf /etc/nginx/sites-available/default-octane /etc/nginx/sites-enabled/default; +############################################## +# Multi-stage build: Use Bun for JS packages # +############################################## +FROM oven/bun:latest as bun_build -# Install node in fly-laravel image -RUN cd ~ \ - && curl -sL https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh \ - && bash nodesource_setup.sh \ - && apt install nodejs \ - && cd /var/www/html +WORKDIR /app +COPY . . +COPY --from=base /var/www/html/vendor /app/vendor -# The snippet below already exists in the Dockerfile btw, -# In the multi-stage build set up: +# If vite.config.js exists, we run `bun run build`. +# If not, we run `bun run production`. +# We assume package.json scripts contain "build" or "production". +RUN bun install --no-cache RUN if [ -f "vite.config.ts" ]; then \ - ASSET_CMD="build"; \ + bun run build; \ else \ - ASSET_CMD="production"; \ - fi; \ - if [ -f "yarn.lock" ]; then \ - yarn install --frozen-lockfile; \ - yarn $ASSET_CMD; \ - elif [ -f "pnpm-lock.yaml" ]; then \ - corepack enable && corepack prepare pnpm@latest-8 --activate; \ - pnpm install --frozen-lockfile; \ - pnpm run $ASSET_CMD; \ - elif [ -f "package-lock.json" ]; then \ - npm ci --no-audit; \ - npm run $ASSET_CMD; \ - else \ - npm install; \ - npm run $ASSET_CMD; \ + bun run production; \ fi; -RUN chown -R www-data:www-data /var/www/html/public -# From our base container created above, we -# create our final image, adding in static -# assets that we generated above +################################# +# Final Image with Node.js only # +################################# FROM base -# 5. Setup Entrypoint -EXPOSE 8080 +# Install Node.js 22.x +RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ + apt-get update && \ + apt-get install -y nodejs && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +# Copy built assets from bun_build stage +COPY --from=bun_build /app/public /var/www/html/public-bun +RUN rsync -ar /var/www/html/public-bun/ /var/www/html/public/ \ + && rm -rf /var/www/html/public-bun \ + && chown -R www-data:www-data /var/www/html/public + +EXPOSE 8080 ENTRYPOINT ["/entrypoint"] diff --git a/bun.lockb b/bun.lockb index 991ec58..e68e72f 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 8f88fd4..4845261 100644 --- a/package.json +++ b/package.json @@ -11,42 +11,43 @@ "icons:build": "tsx ./scripts/build_icons" }, "dependencies": { - "@mantine/core": "^7.14.0", - "@mantine/hooks": "^7.14.0", "@inertiajs/react": "^1.2.0", + "@mantine/core": "^7.14.3", + "@mantine/hooks": "^7.14.3", + "axios": "^1.7.9", "clsx": "^2.1.1", - "react": "^18.3.1", - "axios": "^1.7.7", - "react-compiler-runtime": "^19.0.0-beta-a7bf2bd-20241110", - "react-dom": "^18.3.1", + "react": "^19.0.0", + "react-compiler-runtime": "^19.0.0-beta-df7b47d-20241124", + "react-dom": "^19.0.0", "sonner": "^1.7.0", - "tailwind-merge": "^2.5.4" + "tailwind-merge": "^2.5.5" }, "devDependencies": { "@adonisjs/eslint-config": "^1.3.0", - "@types/node": "^22.9.0", - "@types/react": "^18.3.12", - "@types/react-dom": "^18.3.1", - "@vitejs/plugin-react": "^4.3.3", + "@types/node": "^22.10.1", + "@types/react": "^18.3.14", + "@types/react-dom": "^18.3.2", + "@vitejs/plugin-react": "^4.3.4", "autoprefixer": "^10.4.20", - "babel-plugin-react-compiler": "^19.0.0-beta-a7bf2bd-20241110", + "babel-plugin-react-compiler": "^19.0.0-beta-df7b47d-20241124", "eslint": "8.57.0", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.37.2", - "eslint-plugin-react-compiler": "^19.0.0-beta-a7bf2bd-20241110", - "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-compiler": "^19.0.0-beta-df7b47d-20241124", + "eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-tailwindcss": "^3.17.5", - "laravel-vite-plugin": "^1.0.5", + "laravel-vite-plugin": "^1.1.1", "node-html-parser": "^6.1.13", "postcss": "^8.4.49", - "prettier": "^3.3.3", + "prettier": "^3.4.2", "prettier-plugin-organize-imports": "^4.1.0", - "prettier-plugin-tailwindcss": "^0.6.8", - "tailwindcss": "^3.4.14", + "prettier-plugin-tailwindcss": "^0.6.9", + "tailwindcss": "^3.4.16", + "taze": "^0.18.0", "tsx": "^4.19.2", - "typescript": "^5.6.3", - "vite": "^5.4.11", + "typescript": "^5.7.2", + "vite": "^6.0.3", "vite-plugin-watch": "^0.3.1" } } diff --git a/resources/routes/ziggy.js b/resources/routes/ziggy.js index ba1447c..8cbb364 100644 --- a/resources/routes/ziggy.js +++ b/resources/routes/ziggy.js @@ -1,79 +1,5 @@ -/* eslint-disable no-undef */ -const Ziggy = { - url: 'http://localhost', - port: null, - defaults: {}, - routes: { - 'debugbar.openhandler': { uri: '_debugbar/open', methods: ['GET', 'HEAD'] }, - 'debugbar.clockwork': { - uri: '_debugbar/clockwork/{id}', - methods: ['GET', 'HEAD'], - parameters: ['id'], - }, - 'debugbar.assets.css': { - uri: '_debugbar/assets/stylesheets', - methods: ['GET', 'HEAD'], - }, - 'debugbar.assets.js': { - uri: '_debugbar/assets/javascript', - methods: ['GET', 'HEAD'], - }, - 'debugbar.cache.delete': { - uri: '_debugbar/cache/{key}/{tags?}', - methods: ['DELETE'], - parameters: ['key', 'tags'], - }, - 'debugbar.queries.explain': { - uri: '_debugbar/queries/explain', - methods: ['POST'], - }, - 'sanctum.csrf-cookie': { - uri: 'sanctum/csrf-cookie', - methods: ['GET', 'HEAD'], - }, - 'resend.webhook': { uri: 'resend/webhook', methods: ['POST'] }, - 'execute-laravel-error-solution': { - uri: '__execute-laravel-error-solution', - methods: ['POST'], - }, - 'welcome': { uri: '/', methods: ['GET', 'HEAD'] }, - 'dashboard': { uri: 'dashboard', methods: ['GET', 'HEAD'] }, - 'user.profile': { uri: 'user/profile', methods: ['GET', 'HEAD'] }, - 'profile.update': { uri: 'profile', methods: ['PATCH'] }, - 'profile.destroy': { uri: 'profile', methods: ['DELETE'] }, - 'user.settings': { uri: 'user/settings', methods: ['GET', 'HEAD'] }, - 'register': { uri: 'register', methods: ['GET', 'HEAD'] }, - 'login': { uri: 'login', methods: ['GET', 'HEAD'] }, - 'password.request': { uri: 'forgot-password', methods: ['GET', 'HEAD'] }, - 'password.email': { uri: 'forgot-password', methods: ['POST'] }, - 'password.reset': { - uri: 'reset-password/{token}', - methods: ['GET', 'HEAD'], - parameters: ['token'], - }, - 'password.store': { uri: 'reset-password', methods: ['POST'] }, - 'verification.notice': { uri: 'verify-email', methods: ['GET', 'HEAD'] }, - 'verification.verify': { - uri: 'verify-email/{id}/{hash}', - methods: ['GET', 'HEAD'], - parameters: ['id', 'hash'], - }, - 'verification.send': { - uri: 'email/verification-notification', - methods: ['POST'], - }, - 'password.confirm': { uri: 'confirm-password', methods: ['GET', 'HEAD'] }, - 'password.update': { uri: 'password', methods: ['PUT'] }, - 'logout': { uri: 'logout', methods: ['POST'] }, - 'storage.local': { - uri: 'storage/{path}', - methods: ['GET', 'HEAD'], - wheres: { path: '.*' }, - parameters: ['path'], - }, - }, -} +const Ziggy = {"url":"http:\/\/localhost","port":null,"defaults":{},"routes":{"debugbar.openhandler":{"uri":"_debugbar\/open","methods":["GET","HEAD"]},"debugbar.clockwork":{"uri":"_debugbar\/clockwork\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"debugbar.assets.css":{"uri":"_debugbar\/assets\/stylesheets","methods":["GET","HEAD"]},"debugbar.assets.js":{"uri":"_debugbar\/assets\/javascript","methods":["GET","HEAD"]},"debugbar.cache.delete":{"uri":"_debugbar\/cache\/{key}\/{tags?}","methods":["DELETE"],"parameters":["key","tags"]},"debugbar.queries.explain":{"uri":"_debugbar\/queries\/explain","methods":["POST"]},"sanctum.csrf-cookie":{"uri":"sanctum\/csrf-cookie","methods":["GET","HEAD"]},"resend.webhook":{"uri":"resend\/webhook","methods":["POST"]},"execute-laravel-error-solution":{"uri":"__execute-laravel-error-solution","methods":["POST"]},"welcome":{"uri":"\/","methods":["GET","HEAD"]},"dashboard":{"uri":"dashboard","methods":["GET","HEAD"]},"user.profile":{"uri":"user\/profile","methods":["GET","HEAD"]},"profile.update":{"uri":"profile","methods":["PATCH"]},"profile.destroy":{"uri":"profile","methods":["DELETE"]},"user.settings":{"uri":"user\/settings","methods":["GET","HEAD"]},"register":{"uri":"register","methods":["GET","HEAD"]},"login":{"uri":"login","methods":["GET","HEAD"]},"password.request":{"uri":"forgot-password","methods":["GET","HEAD"]},"password.email":{"uri":"forgot-password","methods":["POST"]},"password.reset":{"uri":"reset-password\/{token}","methods":["GET","HEAD"],"parameters":["token"]},"password.store":{"uri":"reset-password","methods":["POST"]},"verification.notice":{"uri":"verify-email","methods":["GET","HEAD"]},"verification.verify":{"uri":"verify-email\/{id}\/{hash}","methods":["GET","HEAD"],"parameters":["id","hash"]},"verification.send":{"uri":"email\/verification-notification","methods":["POST"]},"password.confirm":{"uri":"confirm-password","methods":["GET","HEAD"]},"password.update":{"uri":"password","methods":["PUT"]},"logout":{"uri":"logout","methods":["POST"]},"storage.local":{"uri":"storage\/{path}","methods":["GET","HEAD"],"wheres":{"path":".*"},"parameters":["path"]}}}; if (typeof window !== 'undefined' && typeof window.Ziggy !== 'undefined') { - Object.assign(Ziggy.routes, window.Ziggy.routes) + Object.assign(Ziggy.routes, window.Ziggy.routes); } -export { Ziggy } +export { Ziggy }; diff --git a/taze.config.ts b/taze.config.ts new file mode 100644 index 0000000..67b14c4 --- /dev/null +++ b/taze.config.ts @@ -0,0 +1,5 @@ +import { defineConfig } from 'taze' + +export default defineConfig({ + ignorePaths: ['vendor', 'node_modules'], +})