Skip to content

Nuxt + Ionic 本地开发

nuxt-ionic-local-development

Nuxt 是一个基于 Vue 的强大框架,自带基于文件的路由系统、自动代码拆分、自动导入、良好的 TypeScript 支持等,而 Ionic 允许我们使用 Web 来构建现代、高质量的跨平台移动应用程序。有没有可能将二者结合起来做开发呢?

幸运的是,Nuxt 官方提供了 @nuxt/ionic 模块来集成 Ionic。遗憾的是,截止到 v0.13.1,Nuxt + Ionic 本地开发仍然是一个挑战,如果按照文档来做,大概率会遇到错误而无法继续推进。本文旨在记录复现本地开发错误并探索可行解决方案的过程。

复现本地开发错误

我们首先按照文档尝试本地开发。我的开发环境是 macos Sonoma 14.4.1、Node.js v20.11.0、PNPM v8.15.5。

参考 Nuxt Docs > Installation 创建一个新的 Nuxt 项目。

shell
pnpm dlx nuxi@latest init nuxt-ionic

.npmrc 中设置 shamefully-hoisttrue

shell
shamefully-hoist=true

参考 @nuxt/ionic Docs > Installation,安装 @nuxt/ionic 依赖、Android Studio 等,参考 React Native 中文网 > 搭建开发环境 配置相关环境并创建模拟器。

shell
pnpm install --force && pnpm install @nuxtjs/ionic -D

更新 nuxt.config.ts

typescript
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  devtools: { enabled: true },
  modules: ['@nuxtjs/ionic'], 
  ssr: false, 
});

再次安装依赖触发 postinstall 钩子,让 Nuxt 创建 Ionic 相关文件。

shell
pnpm install

参考 @nuxt/ionic Docs > Enabling Capacitor,启用 Capacitor

shell
pnpm add -g @ionic/cli
ionic config set -g npmClient pnpm
ionic integrations enable capacitor
ionic capacitor add ios
ionic capacitor add android

参考 @nuxt/ionic Docs > Routing,更新 app.vue

vue
<template>
  <ion-page>
    <ion-header>
      <ion-toolbar>
        <ion-title>Home</ion-title>
      </ion-toolbar>
    </ion-header>
    <ion-content class="ion-padding">Hello World</ion-content>
  </ion-page>
</template>

至此,这个项目已经初始化完毕,你可以通过 pnpm run dev -o 来启动项目,在浏览器中会看到如下页面。

nuxt-ionic-local-development-1

开发移动应用自然不能只是把项目运行到浏览器上,我们还需要把项目运行到模拟器或真机上,这里使用 Android 来做演示。参考 @nuxt/ionic Docs > Local Development,创建 ./scripts/android.sh 并写入以下内容。

shell
#!/bin/bash
LIP=$(ipconfig getifaddr en0)

echo "🍦 Starting local development to android device - ensure local dev server is running already"
echo "🏗️ Type checking and building for development..."
pnpm run build:dev
echo "🔃 Capacitor installation, podfile installation, sync and copy to app distribution folders..."
npx @ionic/cli capacitor sync android --no-build
echo "🏃 Select an Android device to run the build at local ip address ${LIP} on..."
eval "npx @ionic/cli capacitor run android --livereload-url=http://${LIP}:3000 --external --mode development"

更新 package.json 中的 scripts 字段。

json
{
  "scripts": {
    "android": "bash ./scripts/android.sh"
  }
}

🥰 让我们满怀期待地启动项目!

shell
pnpm run android

😱 结果狠狠地报错了!

nuxt-ionic-local-development-2

如果正在使用 Windows 系统,推荐使用安装 Git 时附带的 Git Bash。ipconfig getifaddr en0 命令可能会报错,而且报错信息可能与我提供的图例不一致,可以先跳过直接往下看,后面会移除该命令。

探索可行解决方案

😡 一气之下气了一下,气完之后让我们仔细看看错误到底怎么回事。第一个错误是 Missing script: build:dev,也就是说 build:dev 这个命令不存在。第二和第三个错误都是 Could not find the web assets directory: ./dist,也就是说 dist 目录不存在。

如果你相当熟悉 Nuxt,那么我相信你脑海中已经浮现出了答案,那就是通过 pnpm run generate 生成 dist 目录,让后续的流程正常跑通。如果你并不熟悉,那应该怎么办?最简单有效的办法是重新再过一遍 @nuxt/ionicIonic 文档。在 @nuxt/ionic Docs > Enabling Capacitor 中,大概步骤已经列写出来了。

nuxt-ionic-local-development-3

  1. 错误信息提示我们需要生成一个 dist 目录。@nuxt/ionic 文档中说我们可以使用 nuxi generate 或者 nuxi build 来生成,实际上只有 nuxi generate 会生成 dist 目录,所以我们需要使用 nuxi generate,也就是运行 pnpm run generate
  2. 我们需要运行 npx cap sync(也就是前面用到的 npx @ionic/cli capacitor sync) 同步 dist 目录。
  3. 我们需要运行 npx cap open ${platform}(也就是前面用到的 @ionic/cli capacitor run) 来打开对应平台(Android / iOS)的应用。

我们将 pnpm run build:dev 换成 pnpm run generate,然后再次尝试启动。

shell
#!/bin/bash
LIP=$(ipconfig getifaddr en0)

echo "🍦 Starting local development to android device - ensure local dev server is running already"
echo "🏗️ Type checking and building for development..."
pnpm run build:dev
pnpm run generate
echo "🔃 Capacitor installation, podfile installation, sync and copy to app distribution folders..."
npx @ionic/cli capacitor sync android --no-build
echo "🏃 Select an Android device to run the build at local ip address ${LIP} on..."
eval "npx @ionic/cli capacitor run android --livereload-url=http://${LIP}:3000 --external --mode development"

这一次在终端里没有报错了,但是在 Android 模拟器里报错了。

nuxt-ionic-local-development-4

这里说的是不能连接到 http://192.168.0.103:3000,但实际上我们根本不需要连接到这里,我们可以去掉相关部分,然后再次尝试启动。

shell
#!/bin/bash
LIP=$(ipconfig getifaddr en0) 

echo "🍦 Starting local development to android device - ensure local dev server is running already"
echo "🏗️ Type checking and building for development..."
pnpm run generate
echo "🔃 Capacitor installation, podfile installation, sync and copy to app distribution folders..."
npx @ionic/cli capacitor sync android --no-build
echo "🏃 Select an Android device to run the build at local ip address ${LIP} on..."
eval "npx @ionic/cli capacitor run android --livereload-url=http://${LIP}:3000 --external --mode development"
echo "🏃 Select an Android device to run the build at local on..."
npx @ionic/cli capacitor run android --external

这一步同时移除了 ipconfig getifaddr en0 命令的调用,后面步骤在各系统中执行结果应该一致。

这一次在终端里又出现了新的提示。它想要运行 vue-cli-service build 但是没找到 @vue/cli-service,询问我们要不要安装。

nuxt-ionic-local-development-5

但是我们已经有 dist 目录了,又何必再打包呢?我们添加 --no-build 参数跳过这个步骤,然后再次尝试启动。

shell
#!/bin/bash
echo "🍦 Starting local development to android device - ensure local dev server is running already"
echo "🏗️ Type checking and building for development..."
pnpm run generate
echo "🔃 Capacitor installation, podfile installation, sync and copy to app distribution folders..."
npx @ionic/cli capacitor sync android --no-build
echo "🏃 Select an Android device to run the build at local on..."
npx @ionic/cli capacitor run android --external
npx @ionic/cli capacitor run android --external --no-build

🎉 这次发现 Android 模拟器正常运行了!真的是可喜可贺!

nuxt-ionic-local-development-6

😔 遗憾的是,终端直接退出了,这也就意味着我们改代码之后,还需要手动运行 pnpm run android 才可以看到最新的代码效果。有没有什么办法改代码后自动运行呢?🤔

在没有头绪时,问问 AI 是不错的选择。我这里用的是 VSC 免费插件 Codeium

nuxt-ionic-local-development-7

我们可以逐个检查,结果第一个 nodemon 就非常不错,那我们就用它吧。事实上,nodemon 也是最匹配我们需求、应用最为广泛的包之一。

shell
pnpm install nodemon -D

我们需要监听的目录和文件类型比较多,在 package.json 的 scripts 字段中使用会非常长,所以这里使用配置文件 nodemon.json 来设置 nodemon。

json
{
  "ignore": [".git", "**/node_modules/"],
  "watch": [
    "./assets",
    "./components",
    "./composables",
    "./content",
    "./layouts",
    "./middleware",
    "./modules",
    "./pages",
    "./plugins",
    "./public",
    "./server",
    "./utils",
    "./.env",
    "./app.vue",
    "./app.config.ts",
    "./capacitor.config.json",
    "./error.vue",
    "./ionic.config.json",
    "./nuxt.config.ts",
    "./tsconfig.json"
  ],
  "ext": "json,js,jsx,ts,tsx,vue"
}

最后更新 package.json 中的 scripts 字段。

json
{
  "scripts": {
    "android": "nodemon --exec \"bash ./scripts/android.sh\""
  }
}

再次运行 pnpm run android 检查,结果又狠狠地报错了!😡

nuxt-ionic-local-development-8

这是因为当我们使用 nodemon 时,我们无法与终端交互,导致 npx @ionic/cli capacitor run android --external --no-build 这个命令没有指定对应的 target,进而导致报错。

我们可以运行 ionic capacitor run android --list 来获取到可选的设备,自动传递第一个设备的 ID,来解决这个报错。

shell
#!/bin/bash
target=$(ionic capacitor run android --list | awk 'NR>3 {print $NF; exit}') 

echo "🍦 Starting local development to android device - ensure local dev server is running already"
echo "🏗️ Type checking and building for development..."
pnpm run generate
echo "🔃 Capacitor installation, podfile installation, sync and copy to app distribution folders..."
npx @ionic/cli capacitor sync android --no-build
echo "🏃 Select an Android device to run the build at local on..."
npx @ionic/cli capacitor run android --external --no-build
eval "npx @ionic/cli capacitor run android --external --no-build --target=${target}"

如果正在使用 Windows 系统,需要先安装 awk 命令,比如使用 chocolatey 安装:choco install awk

再再次运行 pnpm run android 检查,现在一切正常了,修改代码后也能看到最新的代码效果了!🎉

以上提供的脚本内容做简单修改即可适配 iOS,此处不再赘述。最终 package.json 内容如下。

json
{
  "name": "nuxt-app",
  "private": true,
  "type": "module",
  "scripts": {
    "build": "nuxt build",
    "dev": "nuxt dev",
    "generate": "nuxt generate",
    "preview": "nuxt preview",
    "postinstall": "nuxt prepare",
    "android": "nodemon --exec \"bash ./scripts/android.sh\""
  },
  "dependencies": {
    "@capacitor/android": "5.7.4",
    "@capacitor/app": "5.0.7",
    "@capacitor/core": "5.7.4",
    "@capacitor/haptics": "5.0.7",
    "@capacitor/ios": "5.7.4",
    "@capacitor/keyboard": "5.0.8",
    "@capacitor/status-bar": "5.0.7",
    "nuxt": "^3.11.1",
    "vue": "^3.4.21",
    "vue-router": "^4.3.0"
  },
  "devDependencies": {
    "@capacitor/cli": "5.7.4",
    "@nuxtjs/ionic": "^0.13.1",
    "nodemon": "^3.1.0"
  }
}

小结

本文记录了将 Nuxt 和 Ionic 结合起来进行本地开发的过程,包括配置环境、创建项目、遇到问题、探索解决方案等。

Nuxt 和 Ionic 的结合使用在文档上可能存在一些不足,我们可以通过阅读、理解错误信息,结合官方文档、社区资源和 AI 辅助,来完善这部分使用。

希望本文能带给你一点启发和帮助!

Released under the MIT License.