浏览器云端写代码,远程开发 Next.js 应用的简易教程

浏览器云端写代码,远程开发 Next.js 应用的简易教程

本文简单记录我通过 code-server 在浏览器云端中运行 Next.js 15 项目的流程。

1. 准备工作

确保服务器已经安装并登录 1Panel。

借助 1Panel 的可视化面板,我们可以非常轻松地以 Docker 容器方式部署 code-server。


2. 新建 code-server 应用

2.1 记住以下信息

  • 默认端口号40031
  • 网页访问密码password
  • sudo密码password

2.2 访问 & 登录

  • 控制台开启 SSL 反向代理以确保 HTTPS 访问。

后端代理地址 http://127.0.0.1:40031 并通过域名访问,例如code.yourdomain.com。 至此,code-server 就通过 1Panel + Docker 成功跑起来了。


3. 环境准备命令

如果你的远程环境还没有 Node.js / npm / pnpm,可以先执行以下命令完成安装与升级:

bash 复制代码
# 切换到 root
su
# 修改 root 密码
sudo passwd root
bash 复制代码
apt-get update
apt-get install -y nodejs npm

node -v   # 确认 Node.js 版本

npm install -g pnpm
pnpm -v   # 确认 pnpm 已全局安装

安装完成后,就可以继续按照后文步骤在 code-server 中创建并运行 Next.js 项目了。

4. 使用create-next-app自动安装

你可以使用 create-next-app 脚手架工具来快速创建一个新的Next.js项目。这个工具会自动为你设置好一切。

示例:

npx create-next-app@latest my-next-app

在安装过程中,你会看到一些提示,按照提示选择相应的选项即可。

cd my-next-app && pnpm dev

默认启动端口为 3000


5. 修改 basePath 与静态资源前缀

按照官方文档,访问 https://<域名>/absproxy/<端口>,例如code.yourdomain.com/absproxy/3000

5.1. 按照以下规则调整代码

  1. 在 Next.js 层面设置 basePath :强制 Next.js 生成的所有路由都带上 /absproxy/3000
  2. 导出公共环境变量 NEXT_PUBLIC_BASE_PATH:在页面组件里拼接任何静态资源路径。
  3. 代码中统一使用 prefix :不论是 next/image 还是 <a href>,一律走 ${prefix}/xxx

5.2. .env.localnext.config.ts

首先在项目根目录创建 .env.local

bash 复制代码
NEXT_PUBLIC_BASE_PATH=/absproxy/3000

然后在 next.config.ts 中启用 basePath 并把该值同步到客户端环境变量,确保编译阶段即可读到:

ts 复制代码
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  /* config options here */
  basePath: "/absproxy/3000",
};

export default nextConfig;

⚠️ 注意:basePath 必须在构建时确定,因此每次修改都需要重新 next build(开发模式下会自动热重启)。


5.3. 页面示例:统一前缀的组件写法

下面是一个改造后的 src/app/page.tsx 示例。核心是读取环境变量 NEXT_PUBLIC_BASE_PATH,在所有 Image 及链接地址前拼接 prefix

tsx 复制代码
import Image from "next/image";

const prefix = process.env.NEXT_PUBLIC_BASE_PATH ?? "";

export default function Home() {
  return (
    <div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
      <main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
        <Image
          className="dark:invert"
          src={`${prefix}/next.svg`}
          alt="Next.js logo"
          width={180}
          height={38}
          priority
        />
        <ol className="font-mono list-inside list-decimal text-sm/6 text-center sm:text-left">
          <li className="mb-2 tracking-[-.01em]">
            Get started by editing{" "}
            <code className="bg-black/[.05] dark:bg-white/[.06] font-mono font-semibold px-1 py-0.5 rounded">
              src/app/page.tsx
            </code>
            .
          </li>
          <li className="tracking-[-.01em]">
            Save and see your changes instantly.
          </li>
        </ol>

        <div className="flex gap-4 items-center flex-col sm:flex-row">
          <a
            className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
            href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
            target="_blank"
            rel="noopener noreferrer"
          >
            <Image
              className="dark:invert"
              src={`${prefix}/vercel.svg`}
              alt="Vercel logomark"
              width={20}
              height={20}
            />
            Deploy now
          </a>
          <a
            className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
            href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
            target="_blank"
            rel="noopener noreferrer"
          >
            Read our docs
          </a>
        </div>
      </main>
      <footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
        <a
          className="flex items-center gap-2 hover:underline hover:underline-offset-4"
          href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          <Image
            aria-hidden
            src={`${prefix}/file.svg`}
            alt="File icon"
            width={16}
            height={16}
          />
          Learn
        </a>
        <a
          className="flex items-center gap-2 hover:underline hover:underline-offset-4"
          href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          <Image
            aria-hidden
            src={`${prefix}/window.svg`}
            alt="Window icon"
            width={16}
            height={16}
          />
          Examples
        </a>
        <a
          className="flex items-center gap-2 hover:underline hover:underline-offset-4"
          href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          <Image
            aria-hidden
            src={`${prefix}/globe.svg`}
            alt="Globe icon"
            width={16}
            height={16}
          />
          Go to nextjs.org →
        </a>
      </footer>
    </div>
  );
}

要点

  • process.env.NEXT_PUBLIC_BASE_PATH 在客户端可直接访问。
  • next/image、自定义 <img><link>fetch 等只要写绝对路径都记得加 prefix
  • 如果你有很多地方需要拼接,可以封装一个 util:
ts 复制代码
export const withBasePath = (path: string) =>
  `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}${path}`;

5.4. 常见坑点排查

问题 解决办法
仍然返回 404 检查 .env.local 是否被 Next.js 读取 (需重启 dev server)。
静态资源 MIME 错误 多半是访问到了根路径的 Cloudflare/反向代理,确认所有 URL 都用 prefix
SockJS / HMR 无法连接 记得设定 WDS_SOCKET_PATH=${PREFIX}/sockjs-node(参见 code-server 文档)。
生产环境刷新返回 404 部署时确保 basePath 与实际访问路径一致,例如 Nginx/Caddy 上也要匹配 /absproxy/3000.

6. 总结

  1. code-server 的 /absproxy 模式不会裁剪请求路径,因此 Next.js 必须显式知道自己挂在 /absproxy/3000
  2. basePath 解决路由与 next/link 问题,但 静态资源必须手动带前缀
  3. 借助 NEXT_PUBLIC_BASE_PATH 就能让组件层保持统一写法。
  4. 修改以上配置后,Next.js 开发体验与本地一致,再也不会看到 404/MIME 报错。

7. 参考链接

相关推荐
吴声子夜歌8 分钟前
ES6——Iterator和for...of循环详解
前端·javascript·es6
小李子呢021112 分钟前
前端八股3---ref和reactive
开发语言·前端·javascript
落魄江湖行16 分钟前
基础篇三 Nuxt4 组件进阶:插槽与事件传递
前端·nuxt4
kerli17 分钟前
Compose 组件:LazyColumn 核心参数与 key/contentType 详解
android·前端
好运的阿财17 分钟前
“锟斤拷”问题——程序中用powershell执行命令出现中文乱码的解决办法
linux·前端·人工智能·机器学习·架构·编辑器·vim
踩着两条虫29 分钟前
VTJ.PRO AI + 低代码实战:接入高德地图
前端·vue.js·ai编程
绝世唐门三哥29 分钟前
React性能优化:memo、useMemo和useCallback全解析
前端·react.js·memo
兔子零102432 分钟前
Claude Code 都把宠物养进终端了,我做了一个真正能长期玩的中文宠物游戏
前端·游戏·游戏开发
xiaotao13132 分钟前
Vite 与 Webpack 开发/打包时环境变量对比
前端·vue.js·webpack
摆烂工程师37 分钟前
教你如何查询 Codex 最新额度是多少,以及 ChatGPT Pro、Plus、Business 最新额度变化
前端·后端·ai编程