如何将整个 Vue 应用程序捆绑为单个 UMD 模块

Posted

技术标签:

【中文标题】如何将整个 Vue 应用程序捆绑为单个 UMD 模块【英文标题】:How can I bundle an entire Vue app as a single UMD module 【发布时间】:2020-08-31 11:27:39 【问题描述】:

我想使用 vue-cli-service 将带有样式和所有内容的 vue 应用程序捆绑到单个 UMD javascript 模块中,以便我可以通过我的组件分发服务器将其导入 另一个 Vue 应用程序。我可以使用服务器上的一个组件来执行此操作,但我不知道如何捆绑整个应用程序并将其远程加载到单独的应用程序中。我以这篇文章为指导https://markus.oberlehner.net/blog/distributed-vue-applications-loading-components-via-http/

这是我要导入它的地方:

  
path: '/games',
component: GamesHome,
children: [
  
    path: 'fun',
    component: () =>
      externalComponent(
        'http://localhost:8200/game/Game.cd590421a6d6835e7ae2.umd.min.js'
      ),
    name: 'Fun Game'
  
] 

所以基本上我如何创建一个 Vue 应用程序,然后将它完全与 CSS 捆绑在一起,并且全部使用 vue-cli-service

【问题讨论】:

【参考方案1】:

这是我从开始使用 VueJS 的第一天起就一直在尝试解决的问题。如果客户端JS框架不能解决这个问题,我不会考虑它。

我最近在这方面做了一个 PoC,并且能够在另一个 VueJS 应用程序中使用一个 VueJS 应用程序作为模块。就我而言,我有一套 VueJs 应用程序,其中每个应用程序都在其自己的专用 docker 容器中运行。这些应用程序具有许多在所有应用程序中通用的功能。所以我决定将这个通用代码(页面布局、css 框架等)移动到一个单独的 VueJS 应用程序中,并将所有现有的 VueJS 应用程序作为这个全局应用程序中的模块来使用。我称这种基于微应用的架构是为了将其与基于微前端的架构区分开来,因为它不使用多个客户端 JS 框架,也不需要另一个框架来实现这一点。这就是我的部署架构的样子(如果你不知道,你可以忽略 kubernetes 特定的东西)-

回到实现部分,您需要逐步将 VueJS 应用程序转换为微应用程序。

假设您的项目结构如下所示(它仅显示需要更改的少数文件,而不是所有文件)-
app-1
  public
    index.html
  src
    main.js
    App.vue
    router
      index.js
    store
      index.js
将您的 vuex 状态和路由文件拆分为全局文件和应用程序特定文件 -
app-1
  public
    index.html
  src
    main.js
    App.vue
    router
      app1
        index.js
      index.js
    store
      app1
        index.js
      index.js
复制此项目(全局应用程序),从app-1 中删除global-app 特定文件,并从global-app 中删除特定文件中的app-1。还要从 app-1 项目中删除 index.htmlApp.vue -

global-appindex.html文件中添加ROUTESSTORE_MODULES变量-
<head>
  ....
  ....
  <script type="text/javascript">
    const ROUTES = []
    const STORE_MODULES = 
  </script>
</head>
<body>
  ....
  ....
  <div id="app"></div>
  <script type="text/javascript" src="/app1/micro-app.umd.min.js"></script>
  <!-- built files will be auto injected -->
</body>
ROUTES 变量更新global-approuter\index.js 文件-
const routes = [
  ....
  ....
]
routes.push(...ROUTES)

const router = new VueRouter(
STORE_MODULES 变量更新global-appstore\index.js 文件-
export default new Vuex.Store(
    ....
    ....
    modules: STORE_MODULES
)
清除app-1\src\main.js文件的内容并替换为以下内容-
import routes from '@/router/app1'
import app1 from '@/store/app1'

ROUTES.push(...routes)

STORE_MODULES['app1'] = app1
package.jsonapp-1 文件的scripts 块下定义build-app 命令-
....
"scripts": 
  "build-app": "vue-cli-service build --target lib --formats umd-min --no-clean --name micro-app src/main.js"
,
....
现在在它们的专用容器中构建和部署这两个应用程序,并更新代理容器的 nginx conf 文件以将请求转发到这些容器,如下所示 -
location / 
    proxy_pass  http://global-app:80;     

    
location /app1/ 
    proxy_pass  http://app1:80/;     

您可以使用nginx容器的IP地址和端口访问全局应用程序。

我希望我已经包含了实现基于微应用的架构所需的所有步骤。您可以参考以下作为此 PoC 的一部分创建的 git 存储库 -

https://github.com/mechcloud/large-app-docker
https://github.com/mechcloud/large-app
https://github.com/mechcloud/large-app-plugin1

虽然我不是客户端 JS 框架内部的专家,但我相信这种方法也适用于其他 JS 框架(Angular、React 等)。

【讨论】:

感谢您的详细回答。我会尝试一下并回复你 +1

以上是关于如何将整个 Vue 应用程序捆绑为单个 UMD 模块的主要内容,如果未能解决你的问题,请参考以下文章

将通配符捆绑标识符转换为单个 ID

如何在vue项目中使用UMD方式引入datav?

xml 如何使用Ant将Java程序捆绑到单个可执行.jar文件中

如何将 SonataMediaBundle 画廊限制为单个提供商?

如何将 monorepo 节点项目捆绑到单个文件中?尝试使用 ncc

如何将多个与 Vue 捆绑在一起