fix: upgrade Next.js and refresh Docker runtime
This commit is contained in:
7 files changed
+358
-288
No files matched your search
@@ -0,0 +1,7 @@
|
|||||||
|
.git
|
||||||
|
.next
|
||||||
|
node_modules
|
||||||
|
.idea
|
||||||
|
.env*
|
||||||
|
npm-debug.log*
|
||||||
|
*.tsbuildinfo
|
||||||
+4
-4
@@ -3,9 +3,9 @@
|
|||||||
# ============================================
|
# ============================================
|
||||||
|
|
||||||
# IMPORTANT: Node.js Version Maintenance
|
# IMPORTANT: Node.js Version Maintenance
|
||||||
# This Dockerfile uses Node.js 24.13.0-slim, which was the latest LTS version at the time of writing.
|
# This Dockerfile uses Node.js 24.22.1-slim, which was the latest LTS version at the time of writing.
|
||||||
# To ensure security and compatibility, regularly update the NODE_VERSION ARG to the latest LTS version.
|
# To ensure security and compatibility, regularly update the NODE_VERSION ARG to the latest LTS version.
|
||||||
ARG NODE_VERSION=24.13.0-slim
|
ARG NODE_VERSION=24.22.1-slim
|
||||||
|
|
||||||
FROM node:${NODE_VERSION} AS dependencies
|
FROM node:${NODE_VERSION} AS dependencies
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ FROM node:${NODE_VERSION} AS dependencies
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy package-related files first to leverage Docker's caching mechanism
|
# Copy package-related files first to leverage Docker's caching mechanism
|
||||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
|
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* pnpm-workspace.yaml* .npmrc* ./
|
||||||
|
|
||||||
# Install project dependencies with frozen lockfile for reproducible builds
|
# Install project dependencies with frozen lockfile for reproducible builds
|
||||||
RUN --mount=type=cache,target=/root/.npm \
|
RUN --mount=type=cache,target=/root/.npm \
|
||||||
@@ -109,4 +109,4 @@ USER node
|
|||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
# Start Next.js standalone server
|
# Start Next.js standalone server
|
||||||
CMD ["node", "server.js"]
|
CMD ["node", "server.js"]
|
||||||
+8
-15
@@ -1,16 +1,9 @@
|
|||||||
import { dirname } from "path";
|
import { defineConfig, globalIgnores } from "eslint/config";
|
||||||
import { fileURLToPath } from "url";
|
import nextVitals from "eslint-config-next/core-web-vitals";
|
||||||
import { FlatCompat } from "@eslint/eslintrc";
|
import nextTs from "eslint-config-next/typescript";
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
export default defineConfig([
|
||||||
const __dirname = dirname(__filename);
|
...nextVitals,
|
||||||
|
...nextTs,
|
||||||
const compat = new FlatCompat({
|
globalIgnores([".next/**", "out/**", "build/**", "next-env.d.ts"]),
|
||||||
baseDirectory: __dirname,
|
]);
|
||||||
});
|
|
||||||
|
|
||||||
const eslintConfig = [
|
|
||||||
...compat.extends("next/core-web-vitals", "next/typescript"),
|
|
||||||
];
|
|
||||||
|
|
||||||
export default eslintConfig;
|
|
||||||
+4
-5
@@ -1,12 +1,11 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
/* config options here */
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
// ... rest of the configuration.
|
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
|
outputFileTracingIncludes: {
|
||||||
|
"/api/posts": ["./posts/**/*"],
|
||||||
|
"/posts/*": ["./posts/**/*"],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
Generated
+307
-236
File diff suppressed because it is too large.
Load diff
+3
-4
@@ -6,26 +6,25 @@
|
|||||||
"dev": "next dev --turbopack",
|
"dev": "next dev --turbopack",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint"
|
"lint": "eslint ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cookies-next": "^6.0.0",
|
"cookies-next": "^6.0.0",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"lucide-react": "^0.511.0",
|
"lucide-react": "^0.511.0",
|
||||||
"next": "16.2.4",
|
"next": "16.4.2",
|
||||||
"react": "19.2.5",
|
"react": "19.2.5",
|
||||||
"react-audio-player": "^0.17.0",
|
"react-audio-player": "^0.17.0",
|
||||||
"react-dom": "19.2.5",
|
"react-dom": "19.2.5",
|
||||||
"react-markdown": "^10.1.0"
|
"react-markdown": "^10.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3",
|
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "19.2.14",
|
"@types/react": "19.2.14",
|
||||||
"@types/react-dom": "19.2.3",
|
"@types/react-dom": "19.2.3",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "16.2.4",
|
"eslint-config-next": "16.4.2",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,21 +2,22 @@
|
|||||||
|
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import ReactAudioPlayer from "react-audio-player";
|
import ReactAudioPlayer from "react-audio-player";
|
||||||
import {useEffect, useState} from "react";
|
import {useEffect, useRef} from "react";
|
||||||
import { getCookie, setCookie } from "cookies-next";
|
import { getCookie, setCookie } from "cookies-next";
|
||||||
|
|
||||||
export default function RecordBox() {
|
export default function RecordBox() {
|
||||||
let player: ReactAudioPlayer | null = null;
|
const player = useRef<ReactAudioPlayer>(null);
|
||||||
let notes: HTMLImageElement | null = null;
|
const notes = useRef<HTMLImageElement>(null);
|
||||||
|
const shouldAutoPlay = useRef(true);
|
||||||
const [firstSong, setFirstSong] = useState<string | undefined>();
|
|
||||||
const [shouldAutoPlay, setShouldAutoPlay] = useState<boolean>(true);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setFirstSong(randomSong());
|
|
||||||
// Get autoplay preference from cookie
|
|
||||||
const autoplayCookie = getCookie('jukebox-autoplay');
|
const autoplayCookie = getCookie('jukebox-autoplay');
|
||||||
setShouldAutoPlay(autoplayCookie === 'true' || autoplayCookie === undefined);
|
shouldAutoPlay.current = autoplayCookie === 'true' || autoplayCookie === undefined;
|
||||||
|
const audio = player.current?.audioEl.current;
|
||||||
|
if (audio) {
|
||||||
|
audio.autoplay = shouldAutoPlay.current;
|
||||||
|
audio.src = randomSong();
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
@@ -24,38 +25,38 @@ export default function RecordBox() {
|
|||||||
className="hidden bottom-23 right-0 fixed z-50 pb-2 pr-2"
|
className="hidden bottom-23 right-0 fixed z-50 pb-2 pr-2"
|
||||||
alt={"It's Playing"} width={100} height={100} src={"/musical_notes_final.gif"}
|
alt={"It's Playing"} width={100} height={100} src={"/musical_notes_final.gif"}
|
||||||
unoptimized={true}
|
unoptimized={true}
|
||||||
ref={(ref) => { notes = ref; }}
|
ref={notes}
|
||||||
/>
|
/>
|
||||||
<button>
|
<button>
|
||||||
<Image className="bottom-0 right-0 fixed z-50 pb-2 pr-2 cursor-pointer"
|
<Image className="bottom-0 right-0 fixed z-50 pb-2 pr-2 cursor-pointer"
|
||||||
src={"/record_player.svg"} width={100} height={100} alt={"Player"}
|
src={"/record_player.svg"} width={100} height={100} alt={"Player"}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (player != null && notes != null) {
|
const audio = player.current?.audioEl.current;
|
||||||
if (player.audioEl.current.paused) {
|
if (audio && notes.current) {
|
||||||
player.audioEl.current.play().then();
|
if (audio.paused) {
|
||||||
notes.className = "bottom-23 right-0 fixed z-50 pb-2 pr-2";
|
audio.play().then();
|
||||||
|
notes.current.className = "bottom-23 right-0 fixed z-50 pb-2 pr-2";
|
||||||
// Save preference for autoplay ON
|
// Save preference for autoplay ON
|
||||||
setCookie('jukebox-autoplay', 'true');
|
setCookie('jukebox-autoplay', 'true');
|
||||||
setShouldAutoPlay(true);
|
shouldAutoPlay.current = true;
|
||||||
} else {
|
} else {
|
||||||
player.audioEl.current.pause();
|
audio.pause();
|
||||||
notes.className = "hidden bottom-23 right-0 fixed z-50 pb-2 pr-2";
|
notes.current.className = "hidden bottom-23 right-0 fixed z-50 pb-2 pr-2";
|
||||||
// Save preference for autoplay OFF
|
// Save preference for autoplay OFF
|
||||||
setCookie('jukebox-autoplay', 'false');
|
setCookie('jukebox-autoplay', 'false');
|
||||||
setShouldAutoPlay(false);
|
shouldAutoPlay.current = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<ReactAudioPlayer
|
<ReactAudioPlayer
|
||||||
autoPlay={shouldAutoPlay} controls={false} className=""
|
controls={false} className=""
|
||||||
volume={0.2}
|
volume={0.2}
|
||||||
ref={(element) => { player = element; }}
|
ref={player}
|
||||||
src={firstSong}
|
onPlay={() => {started(player.current, notes.current)}}
|
||||||
onPlay={() => {started(player, notes)}}
|
onEnded={() => {ended(player.current, notes.current, shouldAutoPlay.current)}}
|
||||||
onEnded={() => {ended(player, notes, shouldAutoPlay)}}
|
onPause={() => {stopped(player.current, notes.current)}}
|
||||||
onPause={() => {stopped(player, notes)}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user