mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-27 13:29:15 +07:00
✨ feat: upgrade to Next 16 (#9851)
* upgrade next 16 * try to fix * try to fix * upgrade * fix sitemap build * try to fix build * try to fix build with next 16 * fix docker permission * 🔒 fix(ci): fix code injection vulnerability and permissions in docker workflow - Add pull-requests: write permission to allow PR comments - Fix code injection vulnerability by using env variables instead of direct interpolation - Prevent potential security risks from malicious branch names in pull_request_target events 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * 🔧 chore(ci): change desktop pr build to use pull_request_target - Change from pull_request to pull_request_target to access secrets and write permissions - Update permissions from read-all to specific write permissions for contents and pull-requests - This allows PR builds to create releases and comment on PRs from forks 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * add comment * fix on --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
5
.github/workflows/desktop-pr-build.yml
vendored
5
.github/workflows/desktop-pr-build.yml
vendored
@@ -2,6 +2,7 @@ name: Desktop PR Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
types: [synchronize, labeled, unlabeled] # PR 更新或标签变化时触发
|
||||
|
||||
# 确保同一时间只运行一个相同的 workflow,取消正在进行的旧的运行
|
||||
@@ -10,7 +11,9 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
# Add default permissions
|
||||
permissions: read-all
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
PR_TAG_PREFIX: pr- # PR 构建版本的前缀标识
|
||||
|
||||
12
.github/workflows/docker.yml
vendored
12
.github/workflows/docker.yml
vendored
@@ -1,12 +1,14 @@
|
||||
name: Publish Docker Image
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [published]
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
types: [synchronize, labeled, unlabeled]
|
||||
|
||||
concurrency:
|
||||
@@ -52,9 +54,10 @@ jobs:
|
||||
- name: Generate PR metadata
|
||||
if: github.event_name == 'pull_request'
|
||||
id: pr_meta
|
||||
env:
|
||||
BRANCH_NAME: ${{ github.head_ref }}
|
||||
run: |
|
||||
branch_name="${{ github.head_ref }}"
|
||||
sanitized_branch=$(echo "${branch_name}" | sed -E 's/[^a-zA-Z0-9_.-]+/-/g')
|
||||
sanitized_branch=$(echo "${BRANCH_NAME}" | sed -E 's/[^a-zA-Z0-9_.-]+/-/g')
|
||||
echo "pr_tag=${sanitized_branch}-$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Docker meta
|
||||
@@ -131,9 +134,10 @@ jobs:
|
||||
- name: Generate PR metadata
|
||||
if: github.event_name == 'pull_request'
|
||||
id: pr_meta
|
||||
env:
|
||||
BRANCH_NAME: ${{ github.head_ref }}
|
||||
run: |
|
||||
branch_name="${{ github.head_ref }}"
|
||||
sanitized_branch=$(echo "${branch_name}" | sed -E 's/[^a-zA-Z0-9_.-]+/-/g')
|
||||
sanitized_branch=$(echo "${BRANCH_NAME}" | sed -E 's/[^a-zA-Z0-9_.-]+/-/g')
|
||||
echo "pr_tag=${sanitized_branch}-$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Docker meta
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// copy from https://github.com/kirill-konshin/next-electron-rsc
|
||||
import { serialize as serializeCookie } from 'cookie';
|
||||
import { type Protocol, type Session, protocol } from 'electron';
|
||||
import { type Protocol, type Session } from 'electron';
|
||||
import type { NextConfig } from 'next';
|
||||
import type NextNodeServer from 'next/dist/server/next-server';
|
||||
import assert from 'node:assert';
|
||||
@@ -202,6 +202,11 @@ export function createHandler({
|
||||
|
||||
if (!isDev) {
|
||||
logger.info('Initializing Next.js app for production');
|
||||
|
||||
// https://github.com/lobehub/lobe-chat/pull/9851
|
||||
// @ts-expect-error
|
||||
// noinspection JSConstantReassignment
|
||||
process.env.NODE_ENV = 'production';
|
||||
const next = require(resolve.sync('next', { basedir: standaloneDir }));
|
||||
|
||||
// @see https://github.com/vercel/next.js/issues/64031#issuecomment-2078708340
|
||||
@@ -209,10 +214,7 @@ export function createHandler({
|
||||
.config as NextConfig;
|
||||
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(config);
|
||||
|
||||
app = next({
|
||||
dev: false,
|
||||
dir: standaloneDir,
|
||||
}) as NextNodeServer;
|
||||
app = next({ dir: standaloneDir }) as NextNodeServer;
|
||||
|
||||
handler = app.getRequestHandler();
|
||||
preparePromise = app.prepare();
|
||||
|
||||
@@ -28,9 +28,6 @@ const nextConfig: NextConfig = {
|
||||
emotion: true,
|
||||
},
|
||||
compress: isProd,
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
experimental: {
|
||||
optimizePackageImports: [
|
||||
'emoji-mart',
|
||||
@@ -46,6 +43,7 @@ const nextConfig: NextConfig = {
|
||||
// so we need to disable it
|
||||
// refs: https://github.com/lobehub/lobe-chat/pull/7430
|
||||
serverMinification: false,
|
||||
turbopackFileSystemCacheForDev: true,
|
||||
webVitalsAttribution: ['CLS', 'LCP'],
|
||||
webpackBuildWorker: true,
|
||||
webpackMemoryOptimizations: true,
|
||||
@@ -273,6 +271,7 @@ const nextConfig: NextConfig = {
|
||||
// when external packages in dev mode with turbopack, this config will lead to bundle error
|
||||
serverExternalPackages: isProd ? ['@electric-sql/pglite', "pdfkit"] : ["pdfkit"],
|
||||
transpilePackages: ['pdfjs-dist', 'mermaid'],
|
||||
turbopack: {},
|
||||
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
|
||||
38
package.json
38
package.json
@@ -31,14 +31,14 @@
|
||||
],
|
||||
"scripts": {
|
||||
"prebuild": "tsx scripts/prebuild.mts && npm run lint",
|
||||
"build": "cross-env NODE_OPTIONS=--max-old-space-size=6144 next build",
|
||||
"build": "cross-env NODE_OPTIONS=--max-old-space-size=6144 next build --webpack",
|
||||
"postbuild": "npm run build-sitemap && npm run build-migrate-db",
|
||||
"build-migrate-db": "bun run db:migrate",
|
||||
"build-sitemap": "tsx ./scripts/buildSitemapIndex/index.ts",
|
||||
"build:analyze": "NODE_OPTIONS=--max-old-space-size=6144 ANALYZE=true next build",
|
||||
"build:docker": "npm run prebuild && NODE_OPTIONS=--max-old-space-size=6144 DOCKER=true next build && npm run build-sitemap",
|
||||
"build:analyze": "NODE_OPTIONS=--max-old-space-size=6144 ANALYZE=true next build --webpack",
|
||||
"build:docker": "npm run prebuild && NODE_OPTIONS=--max-old-space-size=6144 DOCKER=true next build --webpack && npm run build-sitemap",
|
||||
"prebuild:electron": "cross-env NEXT_PUBLIC_IS_DESKTOP_APP=1 tsx scripts/prebuild.mts",
|
||||
"build:electron": "cross-env NODE_OPTIONS=--max-old-space-size=6144 NEXT_PUBLIC_IS_DESKTOP_APP=1 NEXT_PUBLIC_SERVICE_MODE=server next build",
|
||||
"build:electron": "cross-env NODE_OPTIONS=--max-old-space-size=6144 NEXT_PUBLIC_IS_DESKTOP_APP=1 NEXT_PUBLIC_SERVICE_MODE=server next build --webpack",
|
||||
"clean:node_modules": "bash -lc 'set -e; echo \"Removing all node_modules...\"; rm -rf node_modules; pnpm -r exec rm -rf node_modules; rm -rf apps/desktop/node_modules; echo \"All node_modules removed.\"'",
|
||||
"db:generate": "drizzle-kit generate && npm run db:generate-client && npm run workflow:dbml",
|
||||
"db:generate-client": "tsx ./scripts/migrateClientDB/compile-migrations.ts",
|
||||
@@ -50,9 +50,9 @@
|
||||
"desktop:build-local": "npm run desktop:build-next && npm run desktop:prepare-dist && npm run build-local --prefix=./apps/desktop",
|
||||
"desktop:build-next": "npm run build:electron",
|
||||
"desktop:prepare-dist": "tsx scripts/electronWorkflow/moveNextStandalone.ts",
|
||||
"dev": "next dev --turbopack -p 3010",
|
||||
"dev:desktop": "next dev --turbopack -p 3015",
|
||||
"dev:mobile": "next dev --turbopack -p 3018",
|
||||
"dev": "next dev -p 3010",
|
||||
"dev:desktop": "next dev -p 3015",
|
||||
"dev:mobile": "next dev -p 3018",
|
||||
"docs:i18n": "lobe-i18n md && npm run lint:md && npm run lint:mdx && prettier -c --write locales/**/*",
|
||||
"docs:seo": "lobe-seo && npm run lint:mdx",
|
||||
"e2e": "cd e2e && npm run test:smoke",
|
||||
@@ -123,9 +123,6 @@
|
||||
"eslint --fix"
|
||||
]
|
||||
},
|
||||
"overrides": {
|
||||
"mdast-util-gfm-autolink-literal": "2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^5.6.1",
|
||||
"@ant-design/pro-components": "^2.8.10",
|
||||
@@ -174,7 +171,7 @@
|
||||
"@lobehub/ui": "^2.13.2",
|
||||
"@modelcontextprotocol/sdk": "^1.20.0",
|
||||
"@neondatabase/serverless": "^1.0.2",
|
||||
"@next/third-parties": "^15.5.4",
|
||||
"@next/third-parties": "^16.0.1",
|
||||
"@opentelemetry/exporter-jaeger": "^2.1.0",
|
||||
"@opentelemetry/winston-transport": "^0.18.0",
|
||||
"@react-pdf/renderer": "^4.3.0",
|
||||
@@ -235,7 +232,7 @@
|
||||
"model-bank": "workspace:*",
|
||||
"modern-screenshot": "^4.6.6",
|
||||
"nanoid": "^5.1.6",
|
||||
"next": "~15.3.5",
|
||||
"next": "^16.0.1",
|
||||
"next-auth": "5.0.0-beta.30",
|
||||
"next-mdx-remote": "^5.0.0",
|
||||
"nextjs-toploader": "^3.9.17",
|
||||
@@ -261,9 +258,9 @@
|
||||
"pwa-install-handler": "^2.6.3",
|
||||
"query-string": "^9.3.1",
|
||||
"random-words": "^2.0.1",
|
||||
"react": "^19.2.0",
|
||||
"react": "19.2.0",
|
||||
"react-confetti": "^6.4.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"react-dom": "19.2.0",
|
||||
"react-fast-marquee": "^1.6.5",
|
||||
"react-hotkeys-hook": "^5.1.0",
|
||||
"react-i18next": "^15.7.4",
|
||||
@@ -313,8 +310,8 @@
|
||||
"@lobehub/lint": "^1.26.2",
|
||||
"@lobehub/market-types": "^1.11.4",
|
||||
"@lobehub/seo-cli": "^1.7.0",
|
||||
"@next/bundle-analyzer": "^15.5.4",
|
||||
"@next/eslint-plugin-next": "^15.5.4",
|
||||
"@next/bundle-analyzer": "^16.0.1",
|
||||
"@next/eslint-plugin-next": "^15.5.6",
|
||||
"@peculiar/webcrypto": "^1.5.0",
|
||||
"@playwright/test": "^1.49.1",
|
||||
"@prettier/sync": "^0.6.1",
|
||||
@@ -335,8 +332,8 @@
|
||||
"@types/oidc-provider": "^9.5.0",
|
||||
"@types/pdfkit": "^0.17.3",
|
||||
"@types/pg": "^8.15.5",
|
||||
"@types/react": "^19.2.2",
|
||||
"@types/react-dom": "^19.2.1",
|
||||
"@types/react": "19.2.2",
|
||||
"@types/react-dom": "19.2.2",
|
||||
"@types/rtl-detect": "^1.0.3",
|
||||
"@types/semver": "^7.7.1",
|
||||
"@types/systemjs": "^6.15.3",
|
||||
@@ -399,9 +396,6 @@
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"@vercel/speed-insights"
|
||||
],
|
||||
"overrides": {
|
||||
"mdast-util-gfm-autolink-literal": "2.0.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,5 +3,8 @@
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts"
|
||||
"types": "src/index.ts",
|
||||
"peerDependencies": {
|
||||
"react": "^19"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"@napi-rs/canvas": "^0.1.70",
|
||||
"@xmldom/xmldom": "^0.9.8",
|
||||
"concat-stream": "^2.0.0",
|
||||
"debug": "^4.3.4",
|
||||
"mammoth": "^1.8.0",
|
||||
"officeparser": "5.1.1",
|
||||
"pdfjs-dist": "4.10.38",
|
||||
|
||||
@@ -18,7 +18,7 @@ export const GET = async (request: NextRequest) => {
|
||||
return NextResponse.json('tag query parameter is required', { status: 400 });
|
||||
}
|
||||
|
||||
revalidateTag(tag);
|
||||
revalidateTag(tag, 'max');
|
||||
|
||||
return Response.json({ now: Date.now(), revalidated: true });
|
||||
};
|
||||
|
||||
@@ -73,6 +73,7 @@ export const generateViewport = async (props: DynamicLayoutProps): ResolvingView
|
||||
|
||||
return {
|
||||
...dynamicScale,
|
||||
colorScheme: null,
|
||||
initialScale: 1,
|
||||
minimumScale: 1,
|
||||
themeColor: [
|
||||
|
||||
@@ -47,7 +47,13 @@ export function parsePaginatedId(id: string): { page?: number; type: SitemapType
|
||||
return { type: id as SitemapType };
|
||||
}
|
||||
|
||||
export default async function sitemap({ id }: { id: string }): Promise<MetadataRoute.Sitemap> {
|
||||
export default async function sitemap({
|
||||
id: idPromise,
|
||||
}: {
|
||||
id: string;
|
||||
}): Promise<MetadataRoute.Sitemap> {
|
||||
const id = await idPromise;
|
||||
|
||||
const { type, page } = parsePaginatedId(id);
|
||||
const sitemapModule = new Sitemap();
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"jsx": "react-jsx",
|
||||
"incremental": true,
|
||||
"baseUrl": ".",
|
||||
"types": ["vitest/globals", "@serwist/next/typings"],
|
||||
@@ -41,5 +41,12 @@
|
||||
".temp",
|
||||
"e2e"
|
||||
],
|
||||
"include": ["**/*.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "next-env.d.ts"]
|
||||
"include": [
|
||||
"**/*.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
"next-env.d.ts",
|
||||
".next/dev/types/**/*.ts"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user