Nuxt3 使用@nuxt/content 构建时 SQLite 报错问题及解决方案
在使用 Nuxt3 和 @nuxt/content 模块进行项目构建时,经常会遇到与 SQLite 相关的编译问题,特别是在云服务或 CI/CD 环境中。本文将详细介绍这些问题的原因和解决方案。
问题背景
@nuxt/content 模块默认使用 better-sqlite3 作为存储引擎,而 better-sqlite3 需要在安装过程中编译原生代码。这在某些环境中可能会导致各种编译错误,尤其是在云服务提供商的构建环境中。
常见错误场景
1. 阿里云函数应用运算构建流水线 node-headers 下载失败
在阿里云函数计算的构建环境中,由于网络限制,无法下载 Node.js 头文件,导致编译失败:
本地测试发现 https://nodejs.org/download/release/v22.11.0/node-v22.11.0-headers.tar.gz 是可以正常访问的,但在云环境中由于网络限制无法下载。
npm error code 1
npm error path /kaniko/tmp/workspace/nuxt3/node_modules/better-sqlite3
npm error command failed
npm error command sh -c prebuild-install || node-gyp rebuild --release
npm error prebuild-install warn install /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /kaniko/tmp/workspace/nuxt3/node_modules/better-sqlite3/build/Release/better_sqlite3.node)
npm error gyp info it worked if it ends with ok
npm error gyp info using node-gyp@10.2.0
npm error gyp info using node@22.11.0 | linux | x64
npm error gyp info find Python using Python version 3.9.20 found at "/usr/local/envs/py39/bin/python3"
npm error gyp http GET https://nodejs.org/download/release/v22.11.0/node-v22.11.0-headers.tar.gz
npm error gyp http fetch GET https://nodejs.org/download/release/v22.11.0/node-v22.11.0-headers.tar.gz attempt 1 failed with ETIMEDOUT
npm error gyp WARN install got an error, rolling back install
npm error gyp ERR! configure error
npm error gyp ERR! stack FetchError: request to https://nodejs.org/download/release/v22.11.0/node-v22.11.0-headers.tar.gz failed, reason:
npm error gyp ERR! stack at ClientRequest.<anonymous> (/usr/local/versions/node/v22.11.0/lib/node_modules/npm/node_modules/node-gyp/node_modules/minipass-fetch/lib/index.js:130:14)
npm error gyp ERR! stack at ClientRequest.emit (node:events:518:28)
npm error gyp ERR! stack at emitErrorEvent (node:_http_client:103:11)
npm error gyp ERR! stack at _destroy (node:_http_client:886:9)
npm error gyp ERR! stack at onSocketNT (node:_http_client:906:5)
npm error gyp ERR! stack at process.processTicksAndRejections (node:internal/process/task_queues:91:21)
npm error gyp ERR! System Linux 4.19.91-c8dfc93.al7.x86_64
npm error gyp ERR! command "/usr/local/versions/node/v22.11.0/bin/node" "/usr/local/versions/node/v22.11.0/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--release"
npm error gyp ERR! cwd /kaniko/tmp/workspace/nuxt3/node_modules/better-sqlite3
npm error gyp ERR! node -v v22.11.0
npm error gyp ERR! node-gyp -v v10.2.0
npm error gyp ERR! not ok
2. 更换 Node.js 版本后的编译错误
尝试更换 Node.js 版本后,虽然可以下载头文件,但仍然出现编译错误:
npm ERR! code 1
npm ERR! path /kaniko/tmp/workspace/nuxt3/node_modules/better-sqlite3
npm ERR! command failed
npm ERR! command sh -c prebuild-install || node-gyp rebuild --release
npm ERR! make: Entering directory '/kaniko/tmp/workspace/nuxt3/node_modules/better-sqlite3/build'
npm ERR! TOUCH ba23eeee118cd63e16015df367567cb043fed872.intermediate
npm ERR! ACTION deps_sqlite3_gyp_locate_sqlite3_target_copy_builtin_sqlite3 ba23eeee118cd63e16015df367567cb043fed872.intermediate
npm ERR! TOUCH Release/obj.target/deps/locate_sqlite3.stamp
npm ERR! CC(target) Release/obj.target/sqlite3/gen/sqlite3/sqlite3.o
npm ERR! rm -f Release/obj.target/deps/sqlite3.a Release/obj.target/deps/sqlite3.a.ar-file-list; mkdir -p `dirname Release/obj.target/deps/sqlite3.a`
npm ERR! ar crs Release/obj.target/deps/sqlite3.a @Release/obj.target/deps/sqlite3.a.ar-file-list
npm ERR! COPY Release/sqlite3.a
npm ERR! CXX(target) Release/obj.target/better_sqlite3/src/better_sqlite3.o
npm ERR! rm ba23eeee118cd63e16015df367567cb043fed872.intermediate
npm ERR! make: Leaving directory '/kaniko/tmp/workspace/nuxt3/node_modules/better-sqlite3/build'
npm ERR! prebuild-install warn install aborted
npm ERR! gyp info it worked if it ends with ok
npm ERR! gyp info using node-gyp@9.4.0
npm ERR! gyp info using node@20.8.1 | linux | x64
npm ERR! gyp info find Python using Python version 3.9.20 found at "/usr/local/envs/py39/bin/python3"
npm ERR! gyp http GET https://nodejs.org/download/release/v20.8.1/node-v20.8.1-headers.tar.gz
npm ERR! gyp http 200 https://nodejs.org/download/release/v20.8.1/node-v20.8.1-headers.tar.gz
npm ERR! gyp http GET https://nodejs.org/download/release/v20.8.1/SHASUMS256.txt
npm ERR! gyp http 200 https://nodejs.org/download/release/v20.8.1/SHASUMS256.txt
npm ERR! gyp info spawn /usr/local/envs/py39/bin/python3
npm ERR! gyp info spawn args [
npm ERR! gyp info spawn args '/usr/local/versions/node/v20.8.1/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py',
npm ERR! gyp info spawn args 'binding.gyp',
npm ERR! gyp info spawn args '-f',
npm ERR! gyp info spawn args 'make',
npm ERR! gyp info spawn args '-I',
npm ERR! gyp info spawn args '/kaniko/tmp/workspace/nuxt3/node_modules/better-sqlite3/build/config.gypi',
npm ERR! gyp info spawn args '-I',
npm ERR! gyp info spawn args '/usr/local/versions/node/v20.8.1/lib/node_modules/npm/node_modules/node-gyp/addon.gypi',
npm ERR! gyp info spawn args '-I',
npm ERR! gyp info spawn args '/root/.cache/node-gyp/20.8.1/include/node/common.gypi',
npm ERR! gyp info spawn args '-Dlibrary=shared_library',
npm ERR! gyp info spawn args '-Dvisibility=default',
npm ERR! gyp info spawn args '-Dnode_root_dir=/root/.cache/node-gyp/20.8.1',
npm ERR! gyp info spawn args '-Dnode_gyp_dir=/usr/local/versions/node/v20.8.1/lib/node_modules/npm/node_modules/node-gyp',
npm ERR! gyp info spawn args '-Dnode_lib_file=/root/.cache/node-gyp/20.8.1/<(target_arch)/node.lib',
npm ERR! gyp info spawn args '-Dmodule_root_dir=/kaniko/tmp/workspace/nuxt3/node_modules/better-sqlite3',
npm ERR! gyp info spawn args '-Dnode_engine=v8',
npm ERR! gyp info spawn args '--depth=.',
npm ERR! gyp info spawn args '--no-parallel',
npm ERR! gyp info spawn args '--generator-output',
npm ERR! gyp info spawn args 'build',
npm ERR! gyp info spawn args '-Goutput_dir=.'
npm ERR! gyp info spawn args ]
npm ERR! gyp info spawn make
npm ERR! gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
npm ERR! g++: error: unrecognized command line option ‘-std=c++20’; did you mean ‘-std=c++2a’?
npm ERR! make: *** [better_sqlite3.target.mk:125: Release/obj.target/better_sqlite3/src/better_sqlite3.o] Error 1
npm ERR! gyp ERR! build error
npm ERR! gyp ERR! stack Error: `make` failed with exit code: 2
npm ERR! gyp ERR! stack at ChildProcess.onExit (/usr/local/versions/node/v20.8.1/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:203:23)
npm ERR! gyp ERR! stack at ChildProcess.emit (node:events:514:28)
npm ERR! gyp ERR! stack at ChildProcess._handle.onexit (node:internal/child_process:294:12)
npm ERR! gyp ERR! System Linux 4.19.91-c8dfc93.al7.x86_64
npm ERR! gyp ERR! command "/usr/local/versions/node/v20.8.1/bin/node" "/usr/local/versions/node/v20.8.1/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--release"
npm ERR! gyp ERR! cwd /kaniko/tmp/workspace/nuxt3/node_modules/better-sqlite3
npm ERR! gyp ERR! node -v v20.8.1
npm ERR! gyp ERR! node-gyp -v v9.4.0
npm ERR! gyp ERR! not ok
这是因为云环境中的 g++ 编译器版本过低,不支持 C++20 标准。
尝试的解决方案
1. 设置环境变量跳过编译
尝试通过设置环境变量来跳过二进制文件的下载和编译:
export SQLITE_SKIP_BINARY_DOWNLOAD=1
export npm_config_build_from_source=false
但这种方法在实际测试中仍然无法解决问题。
2. 使用 postinstall 脚本创建虚拟模块
最终的解决方案是通过 postinstall 脚本创建一个虚拟的 better-sqlite3 模块,并配置 @nuxt/content 使用文件系统存储代替 SQLite:
- 在 package.json 中添加 postinstall 脚本:
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"start": "node .output/server/index.mjs",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare && node ./scripts/fix-sqlite.js"
}
- 创建 scripts/fix-sqlite.js 脚本:
import { existsSync, mkdirSync, writeFileSync } from 'fs';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
// 创建目录
const dir = `${__dirname}/../node_modules/.better-sqlite3`;
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true });
}
// 创建空的预编译文件,跳过编译
const dummyPath = `${dir}/better-sqlite3-dummy.node`;
if (!existsSync(dummyPath)) {
writeFileSync(dummyPath, '');
console.log('Created dummy better-sqlite3 binary to bypass compilation');
}
// 配置使用替代存储
const configPath = `${__dirname}/../.nuxt/content.config.mjs`;
if (existsSync(configPath)) {
const config = `
export default {
storage: {
fs: {
driver: 'fs'
}
}
};
`;
writeFileSync(configPath, config);
console.log('Configured content module to use filesystem storage');
}
解决方案原理
这个解决方案的核心思路是:
- 创建虚拟模块 :通过创建一个空的 .node 文件,欺骗 Node.js 认为原生模块已经编译完成
- 使用替代存储 :配置 @nuxt/content 使用文件系统存储( fs 驱动)而不是默认的 SQLite 存储
- 自动化处理 :通过 postinstall 钩子在每次安装依赖后自动执行修复脚本
适用场景
这个解决方案特别适用于以下场景:
- 云函数或无服务器环境部署
- CI/CD 管道中的自动构建
- 缺少编译工具链的环境
- 网络受限的环境
Trae AI
使用了 1 个参考
.nvmrc 文件是 Node Version Manager (nvm) 使用的配置文件,用于指定项目所需的 Node.js 版本。它的格式非常简单,只需要在文件中写入你想要使用的 Node.js 版本号即可。
以下是 .nvmrc 文件的几种常见格式:
- 指定确切版本:
20.9.0
- 指定主要版本(使用最新的该主版本):
20
- 使用 LTS 版本:
lts/*
- 使用最新版本:
stable
对于你的情况,我建议创建一个 .nvmrc 文件,内容为 20.9.0 或更高版本,以满足 @nuxt/vite-builder@3.16.0 的要求。
你可以在项目根目录创建这个文件:
e:\workspace\rabbit-utils\nuxt3\.nvmrc
文件内容只需要一行:
20.9.0
创建好这个文件后,如果你使用 nvm,可以在项目目录中运行 nvm use 命令,它会自动读取 .nvmrc 文件并切换到指定的 Node.js 版本。
user3492161486688
复制
删除
帮我将当前文章的内容丰富和润色一下
Trae AI
使用了 1 个参考
nuxt3build.md 132-132
Nuxt3 使用@nuxt/content 构建时 SQLite 报错问题及解决方案
在使用 Nuxt3 和 @nuxt/content 模块进行项目构建时,经常会遇到与 SQLite 相关的编译问题,特别是在云服务或 CI/CD 环境中。本文将详细介绍这些问题的原因和解决方案。
问题背景
@nuxt/content 模块默认使用 better-sqlite3 作为存储引擎,而 better-sqlite3 需要在安装过程中编译原生代码。这在某些环境中可能会导致各种编译错误,尤其是在云服务提供商的构建环境中。
常见错误场景
1. 阿里云函数应用运算构建流水线 node-headers 下载失败
在阿里云函数计算的构建环境中,由于网络限制,无法下载 Node.js 头文件,导致编译失败:
npm error code 1
npm error path /kaniko/tmp/workspace/nuxt3/node_modules/better-sqlite3
npm error command failed
npm error command sh -c prebuild-install || node-gyp rebuild --release
npm error prebuild-install warn install /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /kaniko/tmp/workspace/nuxt3/node_modules/better-sqlite3/build/Release/better_sqlite3.node)
npm error gyp info it worked if it ends with ok
npm error gyp info using node-gyp@10.2.0
npm error gyp info using node@22.11.0 | linux | x64
npm error gyp info find Python using Python version 3.9.20 found at "/usr/local/envs/py39/bin/python3"
npm error gyp http GET https://nodejs.org/download/release/v22.11.0/node-v22.11.0-headers.tar.gz
npm error gyp http fetch GET https://nodejs.org/download/release/v22.11.0/node-v22.11.0-headers.tar.gz attempt 1 failed with ETIMEDOUT
本地测试发现 https://nodejs.org/download/release/v22.11.0/node-v22.11.0-headers.tar.gz 是可以正常访问的,但在云环境中由于网络限制无法下载。
### 2. 更换 Node.js 版本后的编译错误
尝试更换 Node.js 版本后,虽然可以下载头文件,但仍然出现编译错误:
```log
npm ERR! g++: error: unrecognized command line option '-std=c++20'; did you mean '-std=c++2a'?
npm ERR! make: *** [better_sqlite3.target.mk:125: Release/obj.target/better_sqlite3/src/better_sqlite3.o] Error 1
这是因为云环境中的 g++ 编译器版本过低,不支持 C++20 标准。
## 尝试的解决方案
### 1. 设置环境变量跳过编译
尝试通过设置环境变量来跳过二进制文件的下载和编译:
```shell
export SQLITE_SKIP_BINARY_DOWNLOAD=1
export npm_config_build_from_source=false
但这种方法在实际测试中仍然无法解决问题。
2. 使用 postinstall 脚本创建虚拟模块
最终的解决方案是通过 postinstall 脚本创建一个虚拟的 better-sqlite3 模块,并配置 @nuxt/content 使用文件系统存储代替 SQLite:
- 在 package.json 中添加 postinstall 脚本:
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"start": "node .output/server/index.mjs",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare && node ./scripts/fix-sqlite.js"
}
2. 创建 scripts/fix-sqlite.js 脚本:
```js
import { existsSync, mkdirSync, writeFileSync } from 'fs';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
// 创建目录
const dir = `${__dirname}/../node_modules/.better-sqlite3`;
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true });
}
// 创建空的预编译文件,跳过编译
const dummyPath = `${dir}/better-sqlite3-dummy.node`;
if (!existsSync(dummyPath)) {
writeFileSync(dummyPath, '');
console.log('Created dummy better-sqlite3 binary to bypass compilation');
}
// 配置使用替代存储
const configPath = `${__dirname}/../.nuxt/content.config.mjs`;
if (existsSync(configPath)) {
const config = `
export default {
storage: {
fs: {
driver: 'fs'
}
}
};
`;
writeFileSync(configPath, config);
console.log('Configured content module to use filesystem storage');
}
解决方案原理
这个解决方案的核心思路是:
- 创建虚拟模块 :通过创建一个空的 .node 文件,欺骗 Node.js 认为原生模块已经编译完成
- 使用替代存储 :配置 @nuxt/content 使用文件系统存储( fs 驱动)而不是默认的 SQLite 存储
- 自动化处理 :通过 postinstall 钩子在每次安装依赖后自动执行修复脚本
适用场景
这个解决方案特别适用于以下场景:
- 云函数或无服务器环境部署
- CI/CD 管道中的自动构建
- 缺少编译工具链的环境
- 网络受限的环境
注意事项
- 使用文件系统存储可能会影响性能,尤其是在内容量大的情况下
- 这是一个变通解决方案,如果可能,最好是解决编译环境的问题
- 在生产环境中,可能需要考虑其他更稳定的存储方案
总结
通过创建虚拟模块和配置替代存储的方式,我们成功解决了 Nuxt3 和 @nuxt/content 在特定环境中的构建问题。这种方法不需要修改云环境的配置,也不需要安装额外的编译工具,是一种简单有效的解决方案。
对于需要在云环境中部署 Nuxt3 + @nuxt/content 项目的开发者来说,这个方法可以显著减少部署过程中的问题,提高构建成功率。
Nuxt3 使用@nuxt/content 构建时 SQLite 报错问题及解决方案
在使用 Nuxt3 和 @nuxt/content 模块进行项目构建时,经常会遇到与 SQLite 相关的编译问题,特别是在云服务或 CI/CD 环境中。本文将详细介绍这些问题的原因和解决方案。