Jan 26, 2025
2 min read
Nuxt3,
Cloudflare,

记录 Nuxt 3 在 Cloudflare Pages 上的那些‘坑’

小心一些,你或者也会碰到

最近在使用 Nuxt3 开发一些有趣的个人项目,使用赛博菩萨 cloudflare pages 来部署项目。其中碰到一些比较无语的坑,记录一下。

cloudflare pages 的 nodejs 问题

虽然 cloudflare 号称赛博菩萨,但是菩萨也不可能全都掏出来给你。

事实上,cloudflare pages 上的 node 应该不是完整的版本,并且版本是固定的,没得选择。因此有一些 js 库是没办法使用的。一个比较明显的例子就是 cloudflare 的 r2 兼容aws s3 协议,需要使用 aws sdk 来操作,但是在cloudflare pages 上,我们无法使用 aws-sdk-js ,否则我们会得到一个叫 t is not a function 莫名其妙的错误,这个错误在本地开发时是没问题的,但是无法打包。

原因是 aws-sdk-js 的依赖@aws-sdk/s3-request-presigner包使用@smithy包,而@smithy包是需要node:fs模块的,很明显,cloudflare node 不提供node:fs。作为替代,cloudflare pages 贴心地推荐了一个很原始的 sdk:aws4fetch

其实还会碰到很多类似的问题,这时候就需要想一下,是不是 cloudflare node 不支持?

有些路由明明开发模式没问题,一上线就404?

我们都知道,如果项目中有一些静态文件需要访问,可以把它放在 public 目录下。因为按约定俗成,框架一般都会设计成路由未定义会去找对应文件或者文件不存在去对应路由定义。

最近刚好碰到一个奇怪的问题,就是放在 public 下的静态文件,有一部分地址可以正常访问,但是另一部分地址直接返回 404 not found。而在开发模式下,则所有地址都能正常访问。

打开控制台,发现报了一个[nuxt] error caught during app initialization Wa: Page not found: /content/xxxx 的错误。这明显处理逻辑跑到了应用内部,但是我这是静态文件页面呀。

按上一个经验,肯定又是和cloudflare pages 有关。先看看部署上有没有关于静态文件的说明。

通过查看 cloudflare pages 的部署信息,函数那一块发现。cloudflare pages 是有自己的调用路由的。调用路由确定何时执行 Functions 脚本。此文件是根据 /functions 目录中的文件生成的。

functions 的路由功用需要自己编写函数来实现。但是,在 nuxt 框架中并没有相关的配置,甚至没有相关的文档。

_routes.json

还有一个办法是,创建一个_routes.json文件来控制何时调用函数。它应该放置在项目的输出目录中。

刚好部署详情中,函数那一项列出的调用路由内容就是_routes.json

{
	"version": 1,
	"include": [
	    "/*"
	  ],
	  "exclude": [
	    "/_nuxt/*",
	    "/_robots.txt",
	    "/favicon.ico",
	    "/images/pvz.jpg",
	    "/js/jquery.js",
	    "/content"
	    //...
  ]
}

通过错误对比,终于发现了问题所在: 404 not found 的页面地址不在exclude 列表中

这个问题非常的隐蔽,_routes.json 文件中只生成了部分静态文件排除,未生成的部分即 404 not found 的页面 全部被当成应用路由来处理了。因此才报出了[nuxt] error caught during app initialization Wa: Page not found: /content/xxxx 的错误。

剩下的问题就很简单了,想办法自己控制这个_routes.json 内容生成即可。

很遗憾,Nuxt3 里没有这部分的文档,也没有提到这部分的任何内容。

因为Nuxt3的后端是 nitro,所以我们只能在 nitro 上看看关于 cloudflare pages 的内容。

Nitro 表示会自动生成一个_routes.json文件,该文件控制哪些路由由文件提供以及哪些由 Worker 脚本提供。可以使用配置选项cloudflare.pages.routes覆盖自动生成的路由文件。

那我们直接在nuxt.config.ts里配置就好了:

export default defineNuxtConfig({
	nitro: {  
    modules: [nitroPublic()],  
    preset: 'cloudflare_pages',  
    prerender: {  
        autoSubfolderIndex: false  
    },  
    cloudflare:{  
        pages: {  
            routes: {  
                "version": 1,  
                "include": [  
                    "/*"  
                ],  
                "exclude": [  
                    "/_nuxt/*",  
                    "/_robots.txt",  
                    "/favicon.ico",  
                    "/fonts/FUTRSTI.TTF",  
                    "/images/bg.jpg",  
                    "/images/logo.jpg",  
                    "/js/jquery.js",  
                    "/js/jquery.mobile-1.4.5.min.js",  
                    "/content/*"  
                ]  
            }  
        }  
    }  
},

})

谈谈 Nuxt 3 这个框架

Nuxt3 给我的感觉是,大问题没有,小问题一堆。 比如它的启动很慢,服务器部分也很慢。 比如它的错误调试信息,大多数是没有帮助的。 比如一些奇怪的路由行为,有时候能预期工作,又时候又不正常。

在 vue 生态上,与 nextjs 类比的我所知道的只有 nuxt。

最近看到了一个叫 https://github.com/tuono-labs/tuono 的框架,就是nextjs 后端部分使用rust 实现的ssr full-stack 框架。不知道会不会有人出一个vue 版本的。