Open11

Nuxt2をNuxt/Bridge対応したかった

ushironokoushironoko

とりあえず公式ドキュメントを読むと以下を順にやればよさそう
https://v3.nuxtjs.org/getting-started/bridge/

rm -rf yarn.lock
  • nuxt @nuxt/typescript-build を手動で消す
yarn add nuxt-edge@latest

yarn add --dev @nuxt/bridge@npm:@nuxt/bridge-edge typescript

npx nuxi prepare
  • npx nuxi prepare で型定義生成後、プロジェクトに応じて nuxt.d.tsnuxt-shims.d.ts を作る
  • nuxt.config.js(ts) で defineNuxtConfig
    • import { defineNuxtConfig } from '@nuxt/bridge';
    • export default defineNuxtConfig({...})
    • 型周りが変わっているものがあるので注意
  • buildModules から @nuxtjs/composition-api/module を削除
    • そのままにすると消せって警告がでてビルドが通らない
    • ドキュメントには Remove @nuxtjs/composition-api: Bridge provides a Nuxt 3 compatible composition-api layer and help to remove dependency とあるが代わりに useContext などを得る手段が見当たらないのでそのままにした
    • nuxt-edge@nuxt/bridge からexportされていない
    • コミュニティで聞いたら To aid in migration, the import paths remain unchanged from nuxtjs/composition-api って返ってきた
    • defineNuxtPlugin などは @nuxt/bridge/dist/runtime/app からインポートできる(後述)
  • config,plugins のesm化
    • ネイティブesm化したためcjsなどの記法がサポートされなくなった
    • plugins でもともと Vue.use しかしていないものは末尾に export default {} を足す
  • .gitignore に .output を追加
ushironokoushironoko

@nuxtjs/composition-api から defineNuxtPlugin をとっている場合は @nuxt/bridge からとるように修正する必要がある

真実は後述

ushironokoushironoko

#appから読めるらしい
https://github.com/nuxt/framework/issues/832

nuxt-edgeに対応した型を使うには以下を一回は叩いている必要がある

npx nuxi prepare

実行すると nuxt.d.ts がプロジェクトルートに生成される。
中身は利用しているmoduleとnuxt-edge本体の型定義がトリプルスラッシュディレクティブで定義されている。

nitroの型を.nuxtからとっている部分があるためパスに注意。

/// <reference path=".nuxt/nitro.d.ts" />
/// <reference path=".nuxt/auto-imports.d.ts" />

既存の nuxt.d.ts がある場合そちらを nuxt-shims.d.ts とかにして別ファイルで管理する。

ushironokoushironoko

#app からのimportはなんか動かないので直接することにした
この場合@nuxt/bridgeをdevDependenciesからdependenciesに移動させる必要がある

import { defineNuxtPlugin } from '@nuxt/bridge/dist/runtime';
ushironokoushironoko

Nuxt2のinjectを使っている部分はuseStateに置き換える必要があるっぽい

import Vue from 'vue';
import { useState, defineNuxtPlugin } from '@nuxt/bridge/dist/runtime';

export default defineNuxtPlugin((): void => {
  useState('notify', () => Vue.prototype.$notify);
});

@nuxtjs/composition-apiのdefineNuxtPluginと違って引数にcontextやinjectは入ってこない。代わりにuseStateにキーとコールバックを渡して登録する。

https://v3.nuxtjs.org/docs/usage/state

詳細はここら辺
https://github.com/nuxt/framework/issues/533

ushironokoushironoko

Vuexも現状だと動かない
内部のヘルパー関数で typeof を使用しているところがなぜか死んでいる。

https://github.com/nuxt/framework/issues/867

とりあえず自分で適当にパッチを当てれば通る。

node_modules/vuex/dist/vuex.common.js

function isObject (obj) {
  // return obj !== null && typeof obj === 'object'
  return true
}

function unifyObjectStyle (type, payload, options) {
  if (isObject(type) && type.type) {
    options = payload;
    payload = type;
    type = type.type;
  }

  if ((process.env.NODE_ENV !== 'production')) {
    // assert(typeof type === 'string', ("expects string as the type, but found " + (typeof type) + "."));
  }

  return { type: type, payload: payload, options: options }
}
ushironokoushironoko

defineNuxtPlugin 内で context などを参照したい場合代わりに useNuxtApp を使う。旧APIから取れたものは legacyNuxt というプロパティに入っている。

import {
  defineNuxtPlugin,
  useNuxtApp,
  useState,
} from '@nuxt/bridge/dist/runtime';

export default defineNuxtPlugin(() => {
  const { legacyNuxt } = useNuxtApp();
  const { context } = legacyNuxt;
  const { app, store, redirect, env, route } = context;
  ...
});