Qiita 初投稿です。
変更履歴
2022/08/29: モックサーバ化の設定間違ってたので修正しました。前のままだとうまく動きませんでした。
Nitro って何?
Nuxt3 で採用されているサーバサイドのエンジンだよ。
Nuxt3 におけるサーバサイドAPIを生成したりするよ。
とっても早いし、ビルド結果も軽い。
ググってもでてこないんだけど・・
unjs nitro
でググれば一発
触って見るところ
Nuxt3 の nuxt.config.ts
で nitro オプションを少し触ってみるよ
import { defineNuxtConfig } from "nuxt";
// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
srcDir: 'src',
nitro: {
// これ!
}
});
型情報どうなってるの?
Nuxt3 公式のリファレンスによると・・
https://v3.nuxtjs.org/api/configuration/nuxt.config#nitro
・・・・あ、Nitro の公式リファレンスに誘導されてる。
つまり、設定値はここを見れば良さそう。
https://nitro.unjs.io/config/
vscode だったら、 nuxt.config.ts
の nitro
のところを右クリックすれば型の実装に参照できて、
追ってみるとだいたいこんな感じの型情報にたどり着くよ。
interface NitroConfig extends DeepPartial<NitroOptions> {
extends?: string | string[] | NitroPreset;
}
interface NitroOptions {
_config: NitroConfig;
preset: string;
logLevel: LogLevel;
runtimeConfig: {
app: {
baseURL: string;
};
nitro: {
/** @deprecated Use top-level routes option! */
routes: NitroRoutesOptions;
};
[key: string]: any;
};
rootDir: string;
srcDir: string;
scanDirs: string[];
buildDir: string;
output: {
dir: string;
serverDir: string;
publicDir: string;
};
storage: StorageMounts;
// ... 中略
}
ここ に書いてある内容とほぼ同じ構成になっているっぽいのがわかる。
実際の値を確認するには・・?
Nuxt の lifecycle hooks を使ったら表示できた。
import type { NitroConfig } from "nitropack";
export default defineNuxtConfig({
hooks: {
'nitro:build:before': (c: NitroConfig) => {
console.dir(c, { depth: undefined })
}
}
ほぼ未設定だと、下のような値が表示された。
{
rootDir: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app',
srcDir: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/src/server',
dev: true,
preset: 'nitro-dev',
buildDir: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/.nuxt',
scanDirs: [ '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/src/server' ],
renderer: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/core/runtime/nitro/renderer',
errorHandler: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/core/runtime/nitro/error',
nodeModulesDirs: [
'/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules',
'/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules',
'/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/node_modules'
],
handlers: [],
devHandlers: [],
baseURL: '/',
virtual: {},
runtimeConfig: {
public: {},
app: { baseURL: '/', buildAssetsDir: '/_nuxt/', cdnURL: '' },
nitro: { envPrefix: 'NUXT_' }
},
typescript: { generateTsConfig: false },
publicAssets: [
{
dir: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/.nuxt/dist/client'
}
],
prerender: { crawlLinks: false, routes: [] },
sourcemap: true,
externals: { inline: [ 'nuxt/dist', 'nuxt3/dist' ] },
alias: {
'vue/compiler-sfc': 'vue/compiler-sfc',
'vue/server-renderer': 'vue/server-renderer',
vue: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/vue/dist/vue.cjs.js',
'estree-walker': 'unenv/runtime/mock/proxy',
'@babel/parser': 'unenv/runtime/mock/proxy',
'@vue/compiler-core': 'unenv/runtime/mock/proxy',
'@vue/compiler-dom': 'unenv/runtime/mock/proxy',
'@vue/compiler-ssr': 'unenv/runtime/mock/proxy',
'@vue/devtools-api': 'unenv/runtime/mock/proxy-cjs',
'#paths': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/core/runtime/nitro/paths',
'~~': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app',
'@@': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app',
'~': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/src',
'@': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/src',
assets: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/src/assets',
public: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/src/public',
'#app': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/app',
'vue-demi': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/app/compat/vue-demi',
'@vue/composition-api': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/app/compat/capi',
'#head': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/head/runtime',
'#imports': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/.nuxt/imports'
},
replace: {
'process.env.NUXT_NO_SSR': false,
'process.dev': true,
__VUE_PROD_DEVTOOLS__: false
},
rollupConfig: {
plugins: [
{
name: 'nuxt:import-protection',
enforce: 'pre',
resolveId: [Function: resolveId]
}
]
}
}
Nuxt3 の設定がなんとなく nitro の設定に反映されてるっぽいのはわかる。
例えば、 Nuxt の設定側で alias を追加してみると、 nitro の設定側にも alias が反映されてる。
export default defineNuxtConfig({
alias: {
'$': '/<rootDir>/test'
}
server/api
のパスを変えてみる
server/api
のパスを変えるには、 nitro の srcDir と scanDir をそれぞれ 変更後のパスにする必要がある。
しかし、 以下のように設定すると、 Nuxt 側の設定が上書きしてしまうので、うまくいかない。
export default defineNuxtConfig({
nitro: {
srcDir: resolve(__dirname, './hoge/server'),
scanDirs: [resolve(__dirname, './hoge/server')]
}
そこで、以下のように変えてみる
export default defineNuxtConfig({
hooks: {
'nitro:config': (config: NitroConfig) => {
const mockServerDir = resolve(__dirname, './hoge/server')
config.srcDir = mockServerDir
config.scanDirs = [mockServerDir]
}
}
この設定で、 API サーバのパスが /hoge/server/api
に変わる。
srcDir は何となく、 nitro の API を構成するソースのディレクトリっぽいのはわかるが、
scanDirs は、公式のリファレンスによると、設定されているディレクトリをルートとして APIサーバを構築してくれるっぽい
応用例
例えば、 server/api
を使ってテスト時はモックデータを返すようにすると、安直に作ると↓のようになる
import mock from 'sample.json'
export default defineEventHandler<Hoge>(async (event) => {
if (isTestMode()) {
return mock
} else {
const response = await $fetch('http://hogehoge.com/api')
return response.data
}
})
しかし、この方法では以下の理由でNGかと思う。
- 本番で TestMode かどうかの分岐があるのが不安. うっかり Test になってないか・・
- ビルドした際に、 .output 以下にテスト用のコードが含まれる
通常の Server API と、 テスト用のモックデータを返す Server API を作って、
環境変数かなにかを使って切り替えれると良さそうだ
export default defineNuxtConfig({
hooks: {
'nitro:config': (config: NitroConfig) => {
if (isTestMode()) {
const mockServerDir = resolve(__dirname, './test/server')
config.srcDir = mockServerDir
config.scanDirs = [mockServerDir]
}
}
}
まとめ
まだ nitro の全オプションを触れていないけれど、オプションの触り方、確認の仕方が今回確認できた。
基本的には、 Nuxt3 側が用意する設定値をそのまま使えば大して困ることはないけれど、
例えばテスト時とか、全体の実装が複雑になってきたときに、
どうしても設定していく必要性はでてくるので、
試行錯誤の仕方だけでもそこそこ理解できたので良かったかな、と思う。