我正在使用 Nuxt3 和 Dexie Cloud 编写一个应用程序,并使用 PM2 部署到我的 LAN 上的开发 Ubuntu 网络服务器。一切都很好,直到我决定添加另一个部署(我将其视为“生产”)来模仿最终用户的设置。我无法只删除其中的数据库和表,因此我准备在单独的数据库上运行它。
我计划将实例化中的数据库名称更改为变量(
new Dexie(bdVar)
),并且db.cloud.configure
中的url也相同。
这就是事情爆发的地方......原因......我从哪里获得这些变量的值?
.env
并不像我想象的那样工作(节点、运行时等)。 Nuxt 的 runtimceConfig
...好吧,我仍在努力解决这个问题。
让我概述一下我所拥有的:
// db/index.js
import { Dexie } from 'dexie'
import { dexieCloud } from 'dexie-cloud-addon'
export const db = new Dexie(dexieDb***, {addons: [dexieCloud]})
db.version(1).stores({
// table definitions
})
db.cloud.configure({
databaseUrl: dexieDbUrl***,
requireAuth: true
})
*** means it works fine when string provided
然后我还有一些其他数据库文件,每个文件都有相关的查询/事务
// db/items.dexie.js
import { db } from '~/db/index.js'
export const fetchItems = async (realmId) => {
const result = await db.items.where('realmId').equals(realmId).sortBy('last_update')
return result
}
...
然后我有我的 Pinia 商店,物品商店,缩短了,例如
// stores/items.js
import { fetchItems } from '~/db/items.dexie.js'
export const useItemStore = defineStore('items', () => {
let items = ref([])
const getItems = async () => {
if (items.value.length === 0) items.value = await fetchItems(currentSpace.value.realmId)
return items
}
...
return {
items,
getItems,
...
}
})
一个简单的页面示例:
// pages/items.vue
<script setup>
const { items } = storeToRefs(useItemStore())
onMounted(async () => {
if (items.value.length < 1) items.value = await useItemStore().getItems()
})
</script>
<template>
<div v-for="item in items" :key="item.id">
{{ item.name }}
</div>
</template>
我尝试在 nuxt.conf.ts 中添加runtimeConfig:
export default defineNuxtConfig({
runtimeConfig: {
dexieDb: '', // .env entry: NUXT_DEXIE_DB
dexieDbUrl: '', // .env entry: NUXT_DEXIE_DB_URL
},
})
下一个逻辑步骤(当然是在我的脑海中)是现在访问 db/index.js 中的runtimeConfig:
// db/index.js
import ...
const runtime = useRuntimeConfig()
export const db = new Dexie(runtime.dexieDb, {addons: [dexieCloud]})
...
500 错误确实清楚地说明了这是行不通的:
A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function.
这就是我目前陷入困境的地方。如何使 Dexie 数据库可用,同时使用根据环境而具有不同值的变量,同时使用“插件、Nuxt 钩子、Nuxt 中间件或 Vue 设置函数”?
注意:我需要作为变量获得的一些信息是敏感的。
我带着这个问题上床睡觉。醒来时有一个“解决方案”。尽管可能有更优雅的方法,但这就是我想出的:
首先,我将
db/index.js
移至插件中
// plugins/dexie.js
import { Dexie } from 'dexie'
import { dexieCloud } from 'dexie-cloud-addon'
export default defineNuxtPlugin(nuxtApp => {
const runtimeConfig = useRuntimeConfig()
const db = new Dexie(runtimeConfig.public.dexieDb, {addons: [dexieCloud]})
db.version(1).stores({
// table definitions
})
db.cloud.configure({
databaseUrl: runtimeConfig.public.dexieDbUrl,
requireAuth: true
})
nuxtApp.db = db
})
将变量移至
public runtimeConfig
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
public: {
dexieDb: '', // env var NUXT_PUBLIC_DEXIE_DB
dexieDbUrl: '', // env var NUXT_PUBLIC_DEXIE_DB_URL
},
},
...
})
然后我更改了数据库方法以期望对数据库的引用
// db/items.dexie.js
export const fetchItems = async (db, realmId) => {
return await db.items.where('realmId').equals(realmId).sortBy('last_update')
}
...
在商店中,我从 NuxtApp 获取数据库,并将其传递
// stores/items.js
import { fetchItems } from '~/db/items.dexie.js'
export const useItemStore = defineStore('items', () => {
const { db } = useNuxtApp()
let items = ref([])
const getItems = async () => {
if (items.value.length === 0) items.value = await fetchItems(db, currentSpace.value.realmId)
return items
}
...
return {
items,
getItems,
...
}
})
这在开发中效果很好!它使用项目根目录中的
.env
。
对于“生产”,我需要更新
ecosystem.config.cjs
,添加环境变量(我正在使用PM2)
module.exports = {
apps: [{
name: 'InstanceName',
port: '3005',
exec_mode: 'cluster',
instances: '2',
script: './.output/server/index.mjs',
env: {
'NUXT_PUBLIC_DEXIE_DB': 'home-db',
'NUXT_PUBLIC_DEXIE_DB_URL': 'https://xxxxxxxxx.dexie.cloud'
},
}]
}
现在我有我的本地开发人员,以及我的 LAN Web 服务器上的两个实例:一个“开发人员”(使用与本地相同的数据库,因此我可以删除和更新。并随心所欲地乱搞)和一个“生产” (使用单独的数据库,就像在实际生产中一样。
我希望这可以帮助那些陷入这个困境的人......