如何将vue项目进行拆分出来的打成独立的CDN包进行版本控制并引用?

vuecli4.5.13,vue3.4.31 elemet-plus~2.7.6
目前由于项目太大想对项目进行拆分,将部分功能打包以标签形式引入使用,可以减少代码体积和打包时间等,并且可以使用版本进行控制

想法是先将部分代码拆分成独立的组件项目打包成umd

打包命令

build:vue-cli-service build --target lib --inline-vue --dest lib src/components/index.js

src/components/index.js

import XLLogin from './HelloWorld.vue';
const components = {
    XLLogin,
};

function install(Vue) {
  const keys = Object.keys(components);
  keys.forEach((name) => {
    const component = components[name];
    Vue.component(component.name || name, component);
  });
}

export {
    XLLogin,
}

export default {
  install,
  ...components,
};

HelloWorld

<template>
    <div>
        <button>222</button>
        <el-button>我是 ElButton</el-button>
        <el-alert title="Success alert" type="success" />
    </div>
</template>

<script setup>
//  import { ElButton } from 'element-plus'q
// import { ElLoading, ElButton, ElAlert, ElMessage } from 'element-plus'
        console.log(window)
        const loading = ElLoading.service({
            lock: true,
            text: 'Loading',
            background: 'rgba(0, 0, 0, 0.7)',
        })
        ElMessage({
            message: 'Congrats, this is a success message.',
            type: 'success',
        })
        // XlLoading({
        //     message: 'Congrats, this is a success message.',
        //   type: 'error',
        // })
        setTimeout(() => {
            loading.close()
        }, 2000)
</script>

vue.config.js

const path = require( 'path' );
const AutoImport = require('unplugin-auto-import/webpack')
const ElementPlus = require( 'unplugin-element-plus/webpack' );
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
module.exports = {
    css: { extract: false },
  configureWebpack: {
        // externals: {
      // vue: 'Vue',
    //  'element-plus': 'element-plus',
    //  '@shining3d/ui-components':'@shining3d/ui-components',
    //  '@shining3d/xl-element-plus':'@shining3d/xl-element-plus',
    //  '@shining3d/matomo':'@shining3d/matomo'
    // },
        resolve: {
            symlinks: false,
            alias: { 
      }
        },
        plugins: [
            ElementPlus({
                resolvers: [ElementPlusResolver()],
                useSource: true
            }),
      AutoImport({
        resolvers: [ElementPlusResolver()],
      }),
      Components({
        resolvers: [ElementPlusResolver()],
      }),
        ]
    },
}

在项目的public/html中使用<script src="lib/xl-login@0.0.1.umd.js"></script>引入

遇到问题
1、如果按照上述打包方式增加--inline-vue的话报错

Uncaught TypeError: Cannot read properties of null (reading 'isCE')
    at renderSlot (runtime-core.esm-bundler.js:2093:1)
    at button2.mjs:72:23
    at normalizeChildren (runtime-core.esm-bundler.js:7382:1)
    at createBaseVNode (runtime-core.esm-bundler.js:7188:1)
    at _createVNode (runtime-core.esm-bundler.js:7265:1)
    at createBlock (runtime-core.esm-bundler.js:7117:1)
    at Proxy.<anonymous> (button2.mjs:43:38)
    at renderComponentRoot (runtime-core.esm-bundler.js:887:1)

2、如果不增加--inline-vue
那么必须在项目的html中增加
<script src="https://cdn.jsdelivr.net/npm/vue@3.4.31/dist/vue.global.prod.js"></script>
然后页面报错

runtime-core.esm-bundler.js:265 Uncaught 
TypeError: Cannot read properties of null (reading 'setupContext')
    at nM (vue.global.prod.js:5:25015)
    at e.useSlots (vue.global.prod.js:9:14301)
    at useButton (use-button.mjs:25:25)
    at setup (button2.mjs:21:84)
    at callWithErrorHandling (runtime-core.esm-bundler.js:195:1)
    at setupStatefulComponent (runtime-core.esm-bundler.js:7633:1)
    at setupComponent (runtime-core.esm-bundler.js:7594:1)
    at mountComponent (runtime-core.esm-bundler.js:5030:1)
    at processComponent (runtime-core.esm-bundler.js:4996:1)
    at patch (runtime-core.esm-bundler.js:4468:1)

如果只有一个div button是没问题的
但是引入element-plus之后,使用ElLoading,ElMessage没有问题,使用标签<el-></el->这种样式就存在问题了

参考了https://github.com/vuejs/core/issues/4344回答,使用vite解决,我准备尝试
希望能得到其他解决方案

到这我就不知道怎么做了,我的想法是将每个拆分出来的打成独立的包,最好是所有依赖全部在包内不依赖项目,vue可以script引入也行,但是走到这进行不下去了

阅读 1.6k
1 个回答
  1. 问题太长,不太确定你的具体问题,说说我的做法
  2. 首先,只对非常边缘的项目做这样的操作,保证用户体验
  3. 边缘包构建成 ESM lib 包,方便的代码内 import(url)
  4. 主项目把这些仓库标记为 external,或者使用动态加载。前者要求 html 里要主动引用,并且绑定到 window;后者更自由一些,我比较喜欢
  5. 但是要注意,尽量不要在大规模生产环境中这么做,因为公共 cdn 可靠性并不高,性能也一般,尤其在大陆反问哪,通常不足以很好的支撑产品
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题