【问题标题】:Architecture for plugins with combined frontend/backend functionality (Vue and Express)具有组合前端/后端功能(Vue 和 Express)的插件架构
【发布时间】:2024-05-18 04:30:02
【问题描述】:

我有一个带有 Vue CLI 生成的前端应用程序和一个 Express 后端应用程序的存储库。该 repo 设置为标准 Vue CLI 应用程序,具有*后端 src 文件夹。 Express 应用定义了一些 JSON API 并提供已编译的 Vue 应用的静态文件。

我想为它构建一个插件系统:插件创建新的 API 端点,但可以选择创建 .vue 单文件组件以在前端使用。这些 SFC 将通过 Vue 路由器中动态生成的路由公开。最终,插件将位于专用的 NPM 包中。

我遇到的问题是如何从前端 src 树之外的位置正确导入这些 .vue 组件。目前我正在这样做:

// vue.config.js

// generated dynamically with fs.readDirSync
process.env.VUE_APP_PLUGINS = JSON.stringify([{
  name: 'my-plugin',
  component: '/path/to/src-backend/plugins/my-plugin/my-plugin.vue'
}];
// router.js

JSON.parse(process.env.VUE_APP_PLUGINS).forEach(plugin => {
  routes.push({
    name: plugin.name,
    path: `/plugins/${plugin.name}`,
    component: import(plugin.component)
  });
});

我在导入调用时遇到前端错误:Uncaught (in promise) Error: Cannot find module '/full/path/to/my-plugin.vue'。这是有道理的,因为浏览器无法从我的文件系统中读取。

我还尝试在 vue.config.js 中创建别名,并使用更短的别名模块路径,如下所示:

// vue.config.js

module.exports = {
  // [...]
  configureWebpack: {
    resolve: {
      alias: {
        '@plugins': path.resolve(__dirname, 'src-backend/plugins')
      },
      extensions: ['vue', 'js', 'json']
    }
  }
}

可能有一种方法可以解决这种依赖关系解决问题,但我也质疑我的架构是否是最好的方法。谢谢你的建议。

【问题讨论】:

    标签: vue.js express vue-component vue-cli


    【解决方案1】:

    我发现了动态导入失败的问题。 Webpack 引擎对传递给import() 的表达式非常讲究。它必须能够推断出有关起始路径和理想文件名的信息。这是解决方案:

    // vue.config.js
    
    // generated dynamically with fs.readDirSync
    process.env.VUE_APP_PLUGINS = JSON.stringify([{
      name: 'my-plugin',
      component: 'my-plugin-component'
    }];
    
    moduel.exports = {
      // ...
    
      // setup alias for cleaner path in frontend import
      configureWebpack: {
        resolve: {
          alias: {
            '@plugins': path.resolve(__dirname, 'src-backend/plugins')
          }
        }
      }
    }
    
    // Vue router.js
    
    JSON.parse(process.env.VUE_APP_PLUGINS).forEach(comp => {
      routes.push({
        path: `/plugins/${comp.name}/${comp.component}`,
        name: `${comp.name}-${comp.component}`,
        component: () => import('@plugins/' + comp.name + '/components/' + comp.component + '.vue')
      });
    });
    

    在字符串文字中包含@plugins/ 非常重要,包含.vue 也是如此,我认为这可以防止它在前端预加载我不想要的仅后端js 文件。

    当我过渡到 NPM 模块时,我仍然担心这个插件架构,但它现在可以工作。

    【讨论】:

      最近更新 更多