🚀 快速安装

复制以下命令并运行,立即安装此 Skill:

npx skills add https://skills.sh/aradotso/trending-skills/vinext-vite-nextjs

💡 提示:需要 Node.js 和 NPM

vinext — 在 Vite 上运行 Next.js API,随处部署

技能来自 ara.so — Daily 2026 Skills 系列。

vinext 是一个 Vite 插件,它重新实现了 Next.js 的公共 API 接口(路由、SSR、RSC、next/* 导入、CLI),使得现有的 Next.js 应用能够在 Vite 而非 Next.js 编译器上运行。它的 API 覆盖率达到约 94%,同时支持 Pages Router 和 App Router,并且可以原生部署到 Cloudflare Workers,还通过可选的 Nitro 支持 AWS、Netlify、Vercel 等平台。

安装

新项目(从 Next.js 迁移)

# 一键自动迁移
npx vinext init

这将执行以下操作:

  1. 运行兼容性检查(vinext check
  2. vite@vitejs/plugin-react 安装为开发依赖项
  3. 为 App Router 安装 @vitejs/plugin-rscreact-server-dom-webpack
  4. package.json 中添加 "type": "module"
  5. 重命名 CJS 配置文件(例如 postcss.config.jspostcss.config.cjs
  6. 添加 dev:vinextbuild:vinext 脚本
  7. 生成一个最小化的 vite.config.ts

迁移是非破坏性的 —— Next.js 可以与 vinext 并存。

手动安装

npm install -D vinext vite @vitejs/plugin-react

# 仅 App Router 需要:
npm install -D @vitejs/plugin-rsc react-server-dom-webpack

更新 package.json 中的脚本:

{
  "scripts": {
    "dev": "vinext dev",
    "build": "vinext build",
    "start": "vinext start",
    "deploy": "vinext deploy"
  }
}

智能体技能(AI 辅助迁移)

npx skills add cloudflare/vinext
# 然后在你的 AI 工具中: "migrate this project to vinext"

CLI 参考

命令 描述
vinext dev 启动开发服务器,支持 HMR
vinext build 生产环境构建
vinext start 用于测试的本地生产服务器
vinext deploy 构建 + 部署到 Cloudflare Workers
vinext init 从 Next.js 自动迁移
vinext check 迁移前扫描兼容性问题
vinext lint 委托给 eslint 或 oxlint

CLI 选项

vinext dev -p 3001 -H 0.0.0.0
vinext deploy --preview
vinext deploy --env staging --name my-app
vinext deploy --skip-build --dry-run
vinext deploy --experimental-tpr
vinext init --port 3001 --skip-check --force

配置

vinext 会自动检测 app/pages/ 目录,并自动加载 next.config.js。基础使用无需 vite.config.ts

最小化 vite.config.ts

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { vinext } from 'vinext/vite'

export default defineConfig({
  plugins: [
    react(),
    vinext(),
  ],
})

App Router vite.config.ts

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import rsc from '@vitejs/plugin-rsc'
import { vinext } from 'vinext/vite'

export default defineConfig({
  plugins: [
    react(),
    rsc(),
    vinext(),
  ],
})

Cloudflare Workers 与绑定

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { vinext } from 'vinext/vite'
import { cloudflare } from '@cloudflare/vite-plugin'

export default defineConfig({
  plugins: [
    cloudflare(),
    react(),
    vinext(),
  ],
})

通过 Nitro 支持其他平台

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { vinext } from 'vinext/vite'
import nitro from 'vite-plugin-nitro'

export default defineConfig({
  plugins: [
    react(),
    vinext(),
    nitro({ preset: 'vercel' }), // 或 'netlify', 'aws-amplify', 'deno-deploy' 等
  ],
})

项目结构

vinext 使用与 Next.js 相同的目录约定 —— 无需更改:

my-app/
├── app/                  # App Router(自动检测)
│   ├── layout.tsx
│   ├── page.tsx
│   └── api/route.ts
├── pages/                # Pages Router(自动检测)
│   ├── index.tsx
│   └── api/hello.ts
├── public/               # 静态资源
├── next.config.js        # 自动加载
├── package.json
└── vite.config.ts        # 基础使用时可选

代码示例

Pages Router — SSR 页面

// pages/index.tsx
import type { GetServerSideProps, InferGetServerSidePropsType } from 'next'

type Props = { data: string }

export const getServerSideProps: GetServerSideProps<Props> = async (ctx) => {
  return { props: { data: '来自 SSR 的问候' } }
}

export default function Home({ data }: InferGetServerSidePropsType<typeof getServerSideProps>) {
  return <h1>{data}</h1>
}

Pages Router — 静态生成

// pages/posts/[id].tsx
import type { GetStaticPaths, GetStaticProps } from 'next'

export const getStaticPaths: GetStaticPaths = async () => {
  return {
    paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
    fallback: false,
  }
}

export const getStaticProps: GetStaticProps = async ({ params }) => {
  return { props: { id: params?.id } }
}

export default function Post({ id }: { id: string }) {
  return <p>帖子 {id}</p>
}

Pages Router — API 路由

// pages/api/hello.ts
import type { NextApiRequest, NextApiResponse } from 'next'

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  res.status(200).json({ message: '来自 vinext 的问候' })
}

App Router — 服务端组件

// app/page.tsx
export default async function Page() {
  const data = await fetch('https://api.example.com/data').then(r => r.json())
  return <main>{data.title}</main>
}

App Router — 路由处理器

// app/api/route.ts
import { NextRequest, NextResponse } from 'next/server'

export async function GET(request: NextRequest) {
  return NextResponse.json({ status: 'ok' })
}

export async function POST(request: NextRequest) {
  const body = await request.json()
  return NextResponse.json({ received: body })
}

App Router — 服务端操作

// app/actions.ts
'use server'

export async function submitForm(formData: FormData) {
  const name = formData.get('name')
  // 在此处编写服务端逻辑
  return { success: true, name }
}
// app/form.tsx
'use client'
import { submitForm } from './actions'

export function Form() {
  return (
    <form action={submitForm}>
      <input name="name" />
      <button type="submit">提交</button>
    </form>
  )
}

中间件

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }
  return NextResponse.next()
}

export const config = {
  matcher: ['/dashboard/:path*'],
}

Cloudflare Workers — 访问绑定

// app/api/kv/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { getCloudflareContext } from 'cloudflare:workers'

export async function GET(request: NextRequest) {
  const { env } = getCloudflareContext()
  const value = await env.MY_KV.get('key')
  return NextResponse.json({ value })
}

图片优化

// app/page.tsx
import Image from 'next/image'

export default function Page() {
  return (
    <Image
      src="/hero.png"
      alt="英雄图"
      width={800}
      height={400}
      priority
    />
  )
}

链接与导航

// app/nav.tsx
'use client'
import Link from 'next/link'
import { useRouter, usePathname } from 'next/navigation'

export function Nav() {
  const router = useRouter()
  const pathname = usePathname()

  return (
    <nav>
      <Link href="/">首页</Link>
      <Link href="/about">关于</Link>
      <button onClick={() => router.push('/dashboard')}>仪表盘</button>
    </nav>
  )
}

部署

Cloudflare Workers

# 身份验证(一次性)
wrangler login

# 部署
vinext deploy

# 部署到预览环境
vinext deploy --preview

# 部署到命名环境
vinext deploy --env production --name my-production-app

对于 CI/CD,请设置 CLOUDFLARE_API_TOKEN 环境变量,而不是使用 wrangler login

wrangler.toml(Cloudflare 配置)

name = "my-app"
compatibility_date = "2024-01-01"
compatibility_flags = ["nodejs_compat"]

[[kv_namespaces]]
binding = "MY_KV"
id = "your-kv-namespace-id"

[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "my-bucket"

通过 Nitro 部署到 Netlify / Vercel / AWS

npm install -D vite-plugin-nitro

# 然后在 vite.config.ts 中添加 nitro 插件并指定目标 preset
# nitro({ preset: 'netlify' })
# nitro({ preset: 'vercel' })
# nitro({ preset: 'aws-amplify' })

next.config.js 支持

vinext 会自动加载你现有的 next.config.js

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      { protocol: 'https', hostname: 'images.example.com' },
    ],
  },
  env: {
    MY_VAR: process.env.MY_VAR,
  },
  redirects: async () => [
    { source: '/old', destination: '/new', permanent: true },
  ],
  rewrites: async () => [
    { source: '/api/:path*', destination: 'https://backend.example.com/:path*' },
  ],
}

module.exports = nextConfig

兼容性检查

在迁移之前运行,以识别不支持的功能:

npx vinext check

这将扫描:

  • 不支持的 next.config.js 选项
  • 已弃用的 Pages Router API
  • 尚不支持的 Next.js 实验性功能
  • CJS 配置文件冲突

常见模式

环境变量

与 Next.js 相同 —— .env.env.local.env.production

# .env.local
NEXT_PUBLIC_API_URL=https://api.example.com
DATABASE_URL=$DATABASE_URL
// 客户端代码可访问(NEXT_PUBLIC_ 前缀)
const apiUrl = process.env.NEXT_PUBLIC_API_URL

// 仅服务端
const dbUrl = process.env.DATABASE_URL

TypeScript 路径别名

// tsconfig.json — 无需修改即可使用
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

Tailwind CSS

npm install -D tailwindcss postcss autoprefixer
# 将 postcss.config.js 重命名为 postcss.config.cjs(vinext init 会自动执行)
// postcss.config.cjs
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

故障排除

ESM 与 CJS 配置文件冲突

# vinext init 会自动处理,或手动重命名:
mv postcss.config.js postcss.config.cjs
mv tailwind.config.js tailwind.config.cjs

确保 package.json 中有 "type": "module"

vinext init 覆盖了现有的 vite.config.ts

vinext init --force

在初始化期间跳过兼容性检查

vinext init --skip-check

自定义端口

vinext dev -p 3001
vinext init --port 3001

部署时 wrangler 未认证

wrangler login
# 或设置环境变量:
export CLOUDFLARE_API_TOKEN=your_token_here

干运行部署以验证配置

vinext deploy --dry-run

App Router 多环境构建问题

App Router 构建会生成三个环境(RSC + SSR + 客户端)。如果遇到构建错误,请确保所有三个插件都已安装:

npm install -D @vitejs/plugin-rsc react-server-dom-webpack

并且你的 vite.config.ts 按正确顺序包含了 react()rsc() 插件。

支持的功能(约 94% 的 Next.js API)

  • ✅ Pages Router(SSR、SSG、ISR、API 路由)
  • ✅ App Router(RSC、服务端操作、路由处理器、布局、加载、错误边界)
  • ✅ 中间件
  • next/imagenext/linknext/routernext/navigationnext/head
  • next/fontnext/dynamic
  • next.config.js(重定向、重写、标头、环境变量、图片)
  • ✅ Cloudflare Workers 原生部署及绑定
  • ✅ 开发环境 HMR
  • ✅ TypeScript、Tailwind CSS、CSS Modules
  • ⚠️ Next.js 实验性功能 — 优先级较低
  • ❌ 未文档化的 Vercel 特定行为 — 有意不支持

📄 原始文档

完整文档(英文):

https://skills.sh/aradotso/trending-skills/vinext-vite-nextjs

💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。