返回

Nextcloud应用开发:VueDesigner与@nextcloud/vue集成指南

vue.js

Nextcloud 应用开发:集成 VueDesigner 与 @nextcloud/vue 组件库

最近在尝试用 Pinegrow 的 VueDesigner 开发 Nextcloud 应用, 发现这个组合很有潜力,但也遇到不少难题。 这篇文章记录下问题和解决方法,给遇到同样问题的朋友做个参考。

一、 问题

Nextcloud 未来版本将只支持 Vue 3,@nextcloud/vue alpha 9.0.0 已经可用。我的 package.json 文件配置如下:

"dependencies": {
    "@nextcloud/vue": "^9.0.0-alpha.5",
    "vue": "^3.5.13",
    "vue-router": "^4.5.0"
  },
  "devDependencies": {
    "@nextcloud/browserslist-config": "^3.0.1",
    "@nextcloud/vite-config": "^2.3.0",
    "vite": "^6"
  }

我在 VueDesigner 中创建了一个新项目 (vite 和 plain CSS, 没有框架)。接着按照官方文档,通过创建 web-types 文件并在 vite.config.tsliveDesigner 插件部分添加引用,将 nextcloud/vue 作为 vue 组件库引入。

安装 npm 包并启动 vite 开发服务器后,可以在 VueDesigner 中编辑新项目。可以通过拖放或上下文菜单添加 NC 组件,并且可以编辑添加组件的属性。

问题在于,NC 组件既不在 ViewDesigner 中显示,也不在浏览器中显示。检查加载的组件,发现根本没有 NC 组件到达浏览器。

二、问题原因分析

根本原因是 Vite 没有正确地将 @nextcloud/vue 组件打包到最终的输出中。VueDesigner 只是一个可视化编辑器,它依赖 Vite 进行项目的构建和打包。我们需要配置 Vite, 让它知道如何处理 @nextcloud/vue 组件。

三、解决方案

尝试了多种方案, 最终发现下面这个配置方法比较有效:

  1. 正确使用 @nextcloud/vite-config

    Nextcloud 官方提供了 @nextcloud/vite-config 包来简化 Nextcloud 应用的 Vite 配置。需要正确使用这个包。

    • 原理: @nextcloud/vite-config 提供了预设的 Vite 配置,专门针对 Nextcloud 应用开发进行了优化,包括处理 @nextcloud/vue 组件库。

    • 代码示例: 修改 vite.config.ts 文件, 引入并使用 createAppConfig:

    /// <reference types="vite-ssg" />
    
    import { fileURLToPath, URL } from 'node:url'
    
    import { defineConfig } from 'vite'
    import Vue from '@vitejs/plugin-vue'
    import { liveDesigner } from '@pinegrow/vite-plugin'
    import AutoImportComponents from 'unplugin-vue-components/vite'
    import AutoImportAPIs from 'unplugin-auto-import/vite'
    import VueRouter from 'unplugin-vue-router/vite'
    import { VueRouterAutoImports } from 'unplugin-vue-router'
    import Layouts from 'vite-plugin-vue-layouts'
    import Unocss from 'unocss/vite'
    import presetIcons from '@unocss/preset-icons'
    import { unheadVueComposablesImports } from '@unhead/vue'
    
    import VueDevTools from 'vite-plugin-vue-devtools'
    
    // import { visualizer } from 'rollup-plugin-visualizer'
    
    import { createAppConfig } from '@nextcloud/vite-config'
    
    // https://vitejs.dev/config/
    // 使用 createAppConfig 包裹配置
      export default defineConfig((configEnv) => {
            const appConfig = createAppConfig({
            // entry points: {name: script}
                main: 'src/main.js',
                // 假设你还有其他入口文件,比如设置页面
                // settings: 'src/settings.js',
            }, configEnv)
        return {
            ...appConfig, //将Nextcloud app配置合并到现有配置
            ssgOptions: {
            beastiesOptions: {
              // E.g., change the preload strategy
              preload: 'media',
              // Other options: https://github.com/danielroe/beasties#usage
             },
          },
          plugins: [
            VueRouter({
              // routesFolder: 'src/pages', // default
              dts: 'typed-router.d.ts',
            }),
            VueDevTools(),
            // IMPORTANT: Vue must be placed after VueRouter()
            Vue({
              include: [/\.vue$/, /\.md$/],
            }),
            Layouts(),
            // For details, refer to https://github.com/antfu/unplugin-auto-import#configuration
            AutoImportAPIs({
              include: [
                /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
                /\.vue$/,
                /\.vue\?vue/, // .vue
                /\.md$/, // .md
                /\.mdx$/, // .mdx
              ],
              imports: [
                'vue',
                VueRouterAutoImports, // Remove 'vue-router',
                // 'vue-i18n',
                // 'vue/macros',
                unheadVueComposablesImports,
                '@vueuse/core',
                'pinia',
              ],
              dirs: [
                // Please ensure that you update the filenames and paths to accurately match those used in your project.
    
                'src/composables',
                // 'src/utils',
                'src/stores',
                '**/pg-*/** ', // To auto-import composables from Vue Designer plugins.
              ],
              vueTemplate: true,
              dts: 'auto-imports.d.ts',
            }),
            // For details, refer to https://github.com/antfu/unplugin-vue-components#configuration
            AutoImportComponents({
              // Please ensure that you update the filenames and paths to accurately match those used in your project.
    
              dirs: ['src/components'],
    
              // allow auto load markdown components under ./src/components/
              extensions: ['vue', 'md'],
    
              // allow auto import and register components used in markdown
              include: [/\.vue$/, /\.vue\?vue/, /\.md$/, /\.mdx?/],
    
              // resolvers: [], // Auto-import using resolvers
              dts: 'components.d.ts',
            }),
            Unocss({
              presets: [
                presetIcons({
                  prefix: 'i-', // default prefix, do not change
                }),
              ],
              content: {
                pipeline: {
                  include: ['./src/**/*'],
                },
              },
            }),
            liveDesigner({
              iconPreferredCase: 'unocss',
              // default value (can be removed), unocss by default uses the unocss format for icon names
              plugins: [
                 {
                   name: 'Nextcloud Vue 9.0 alpha',
                   key: 'nextcloud',
                   pluginPath: fileURLToPath(
                     new URL('./web-types/nextcloud-vue-lib.json', import.meta.url),
                   ),
                 },
               ],
            }),
          ],
    
          // build: {
          //   // Vite uses Rollup under the hold, so rollup options & plugins can be used for advanced usage
          //   rollupOptions: {
          //     plugins: [visualizer()],
          //   },
          // },
    
          resolve: {
            alias: {
              /* Must be either an object, or an array of { find, replacement, customResolver } pairs. */
              /* Refer to: https://vitejs.dev/config/shared-options.html#resolve-alias */
              /* Please ensure that you update the filenames and paths to accurately match those used in your project. */
    
              '@': fileURLToPath(new URL('./src', import.meta.url)),
              '~': fileURLToPath(new URL('./src', import.meta.url)),
              '~~': fileURLToPath(new URL('./', import.meta.url)),
            },
          },
       }
      })
    
    
    
    • 注意: createAppConfig 函数需要两个参数,第一个是你的应用入口配置,第二个是 configEnv,必须从 defineConfig 的回调函数中传入。 把 createAppConfig 返回的结果与原有配置合并。
    • 确保 main 属性指向你的主 JavaScript 文件 (通常是 src/main.js)。
    • 如果你的Nextcloud应用有多个入口点 (比如设置页面),请根据需求设置入口配置.
  2. 检查组件导入

确保在你的 Vue 组件中正确导入了 Nextcloud 组件。

*   **原理:**   即使 Vite 配置正确, 如果没有在组件中正确导入, 组件仍然不会被渲染。
*   **代码示例:** 

    ```vue
    <template>
      <div>
         <NcButton>一个 Nextcloud 按钮</NcButton>
      </div>
    </template>

    <script setup>
    import { NcButton } from '@nextcloud/vue';
    </script>
    ```
  1. 清理和重启
    修改配置后, 清理缓存并重新启动开发服务器:

    • 删除 node_modules 目录.
    • 删除 dist 目录(如果存在).
    • 运行 npm installyarn install.
    • 运行 npm run devyarn dev.
  2. 使用 unplugin-vue-components 解析器(可选,如果自动导入不工作)

如果通过上述步骤仍然无法自动导入 @nextcloud/vue 的组件,你可以尝试在 unplugin-vue-components 中自定义一个解析器。

  • 原理: unplugin-vue-components 允许自定义组件解析器,可以用来指定如何解析特定的组件库。
  • 代码示例:vite.config.tsAutoImportComponents 配置中添加 resolvers:
    
         AutoImportComponents({
              // ... 其他配置 ...
              resolvers: [
                (componentName) => {
                      // 检查是否是 Nextcloud 组件 (以 'Nc' 开头)
                      if (componentName.startsWith('Nc')) {
                        return { name: componentName, from: '@nextcloud/vue' }
                      }
                }
              ],
              dts: 'components.d.ts',
          }),
    
    

四、进阶使用技巧

  1. 利用 VueDesigner 的组件属性编辑功能: VueDesigner 可以自动识别 @nextcloud/vue 组件的属性。 多利用这个功能来快速配置组件。

  2. web-types的配置 在VueDesigner项目下, 按照说明正确创建web-types ,并在vite.config.ts做引用是关键. 建议认真阅读官方文档给出的相关指导。

  3. 调试技巧:

    • 使用浏览器的开发者工具 (特别是 Vue Devtools) 来检查组件是否正确加载和渲染。
    • 检查 Vite 的控制台输出,查看是否有任何错误或警告信息。

五、安全建议

由于使用的是 alpha 版本的 @nextcloud/vue,请注意:

  • 保持更新: 密切关注 @nextcloud/vue 的更新,及时升级到最新版本,以获取最新的修复和功能。
  • ** 避免生产环境使用** alpha版本有可能会有未预料的bug。 建议不要用在生产环境中,仅用于开发和测试。

通过以上步骤配置后,@nextcloud/vue 组件应该能在 VueDesigner 和浏览器中正常显示了。 如果还是不行,可以尝试结合多种方法来调试,或者在 Nextcloud 和 Pinegrow 社区寻求帮助。