vue-demi icon indicating copy to clipboard operation
vue-demi copied to clipboard

TypeError: o.resolveComponent is not a function & 能否提供一个打包 vue2、vue3 组件库的 demo

Open Murphycx94 opened this issue 3 years ago • 4 comments

我想打包一个 vue2、vue3 都可用的组件库 打包完后的组件,在 vue3 项目中使用没有问题 但是在 vue2 项目中运行时报了如下错误

Uncaught TypeError: e.defineComponent is not a function
    at eval (index.js?dead:6)
    at eval (index.js?dead:6)
    at eval (index.js?dead:6)
    at Object.../../long-bridge/fe-toolbox/packages/vue3-components/lib/LbNoticeBar/index.js (app.js:937)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)
    at eval (cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js&:4)
    at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js& (app.js:960)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)

当我修改打包命令 vue-demi-switch 2 && yarn build 打包后

Uncaught TypeError: o.withScopeId is not a function
    at eval (index.js?dead:6)
    at eval (index.js?dead:6)
    at eval (index.js?dead:6)
    at Object.../../long-bridge/fe-toolbox/packages/vue3-components/lib/LbNoticeBar/index.js (app.js:937)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)
    at eval (cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js&:4)
    at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js& (app.js:960)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)

这是我其中的一个组件 Icon 组件

<template>
  <svg class="icon iconfont" aria-hidden="true" @click="e => $emit('click', e)">
    <use :xlink:href="`#icon-${name}`"></use>
  </svg>
</template>

<script>
import { defineComponent } from 'vue-demi'

export default defineComponent({
  name: 'LbIcon',
  props: {
    /**
     * isRequired.
     */
    name: {
      type: String,
      required: true
    }
  }
})
</script>

<style lang="scss" scoped>
.icon {
  width: 1em;
  height: 1em;
  overflow: hidden;
  vertical-align: -0.15em;
  cursor: pointer;
  fill: currentColor;
}
</style>

这是打包后的代码

/*!
 * @lb-public/vue3-components v0.5.0 Mon Jul 26 2021 19:07:24 GMT+0800 (中国标准时间)
 * (c) 2021 @lbf2e.
 * Released under the MIT License.
 */
!(function (e, n) {
  'object' == typeof exports && 'undefined' != typeof module
    ? (module.exports = n(require('vue-demi'), require('vue')))
    : 'function' == typeof define && define.amd
    ? define(['vue-demi', 'vue'], n)
    : ((e = 'undefined' != typeof globalThis ? globalThis : e || self).index = n(e.VueDemi, e.Vue))
})(this, function (e, n) {
  'use strict'
  const i = e.defineComponent({ name: 'LbIcon', props: { name: { type: String, required: !0 } } }),
    o = n.withScopeId('data-v-7a1e4f22')(
      (e, i, o, t, d, r) => (
        n.openBlock(),
        n.createBlock(
          'svg',
          { class: 'icon iconfont', 'aria-hidden': 'true', onClick: i[1] || (i[1] = n => e.$emit('click', n)) },
          [n.createVNode('use', { 'xlink:href': `#icon-${e.name}` }, null, 8, ['xlink:href'])]
        )
      )
    )
  return (i.render = o), (i.__scopeId = 'data-v-7a1e4f22'), i
})

Murphycx94 avatar Jul 26 '21 11:07 Murphycx94

我想打包一个 vue2、vue3 都可用的组件库 打包完后的组件,在 vue3 项目中使用没有问题 但是在 vue2 项目中运行时报了如下错误

Uncaught TypeError: e.defineComponent is not a function
    at eval (index.js?dead:6)
    at eval (index.js?dead:6)
    at eval (index.js?dead:6)
    at Object.../../long-bridge/fe-toolbox/packages/vue3-components/lib/LbNoticeBar/index.js (app.js:937)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)
    at eval (cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js&:4)
    at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js& (app.js:960)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)

当我修改打包命令 vue-demi-switch 2 && yarn build 打包后

Uncaught TypeError: o.withScopeId is not a function
    at eval (index.js?dead:6)
    at eval (index.js?dead:6)
    at eval (index.js?dead:6)
    at Object.../../long-bridge/fe-toolbox/packages/vue3-components/lib/LbNoticeBar/index.js (app.js:937)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)
    at eval (cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js&:4)
    at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js& (app.js:960)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)

这是我其中的一个组件 Icon 组件

<template>
  <svg class="icon iconfont" aria-hidden="true" @click="e => $emit('click', e)">
    <use :xlink:href="`#icon-${name}`"></use>
  </svg>
</template>

<script>
import { defineComponent } from 'vue-demi'

export default defineComponent({
  name: 'LbIcon',
  props: {
    /**
     * isRequired.
     */
    name: {
      type: String,
      required: true
    }
  }
})
</script>

<style lang="scss" scoped>
.icon {
  width: 1em;
  height: 1em;
  overflow: hidden;
  vertical-align: -0.15em;
  cursor: pointer;
  fill: currentColor;
}
</style>

这是打包后的代码

/*!
 * @lb-public/vue3-components v0.5.0 Mon Jul 26 2021 19:07:24 GMT+0800 (中国标准时间)
 * (c) 2021 @lbf2e.
 * Released under the MIT License.
 */
!(function (e, n) {
  'object' == typeof exports && 'undefined' != typeof module
    ? (module.exports = n(require('vue-demi'), require('vue')))
    : 'function' == typeof define && define.amd
    ? define(['vue-demi', 'vue'], n)
    : ((e = 'undefined' != typeof globalThis ? globalThis : e || self).index = n(e.VueDemi, e.Vue))
})(this, function (e, n) {
  'use strict'
  const i = e.defineComponent({ name: 'LbIcon', props: { name: { type: String, required: !0 } } }),
    o = n.withScopeId('data-v-7a1e4f22')(
      (e, i, o, t, d, r) => (
        n.openBlock(),
        n.createBlock(
          'svg',
          { class: 'icon iconfont', 'aria-hidden': 'true', onClick: i[1] || (i[1] = n => e.$emit('click', n)) },
          [n.createVNode('use', { 'xlink:href': `#icon-${e.name}` }, null, 8, ['xlink:href'])]
        )
      )
    )
  return (i.render = o), (i.__scopeId = 'data-v-7a1e4f22'), i
})

Have you solved it

francisZimo avatar Aug 23 '21 10:08 francisZimo

vue3-sketch-ruler contain template compile demo with vue-demi to vue2/3

kakajun avatar Feb 03 '22 23:02 kakajun

我想打包一个 vue2、vue3 都可用的组件库 打包完后的组件,在 vue3 项目中使用没有问题 但是在 vue2 项目中运行时报了如下错误

Uncaught TypeError: e.defineComponent is not a function
    at eval (index.js?dead:6)
    at eval (index.js?dead:6)
    at eval (index.js?dead:6)
    at Object.../../long-bridge/fe-toolbox/packages/vue3-components/lib/LbNoticeBar/index.js (app.js:937)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)
    at eval (cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js&:4)
    at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js& (app.js:960)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)

当我修改打包命令 vue-demi-switch 2 && yarn build 打包后

Uncaught TypeError: o.withScopeId is not a function
    at eval (index.js?dead:6)
    at eval (index.js?dead:6)
    at eval (index.js?dead:6)
    at Object.../../long-bridge/fe-toolbox/packages/vue3-components/lib/LbNoticeBar/index.js (app.js:937)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)
    at eval (cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js&:4)
    at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js& (app.js:960)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)

这是我其中的一个组件 Icon 组件

<template>
  <svg class="icon iconfont" aria-hidden="true" @click="e => $emit('click', e)">
    <use :xlink:href="`#icon-${name}`"></use>
  </svg>
</template>

<script>
import { defineComponent } from 'vue-demi'

export default defineComponent({
  name: 'LbIcon',
  props: {
    /**
     * isRequired.
     */
    name: {
      type: String,
      required: true
    }
  }
})
</script>

<style lang="scss" scoped>
.icon {
  width: 1em;
  height: 1em;
  overflow: hidden;
  vertical-align: -0.15em;
  cursor: pointer;
  fill: currentColor;
}
</style>

这是打包后的代码

/*!
 * @lb-public/vue3-components v0.5.0 Mon Jul 26 2021 19:07:24 GMT+0800 (中国标准时间)
 * (c) 2021 @lbf2e.
 * Released under the MIT License.
 */
!(function (e, n) {
  'object' == typeof exports && 'undefined' != typeof module
    ? (module.exports = n(require('vue-demi'), require('vue')))
    : 'function' == typeof define && define.amd
    ? define(['vue-demi', 'vue'], n)
    : ((e = 'undefined' != typeof globalThis ? globalThis : e || self).index = n(e.VueDemi, e.Vue))
})(this, function (e, n) {
  'use strict'
  const i = e.defineComponent({ name: 'LbIcon', props: { name: { type: String, required: !0 } } }),
    o = n.withScopeId('data-v-7a1e4f22')(
      (e, i, o, t, d, r) => (
        n.openBlock(),
        n.createBlock(
          'svg',
          { class: 'icon iconfont', 'aria-hidden': 'true', onClick: i[1] || (i[1] = n => e.$emit('click', n)) },
          [n.createVNode('use', { 'xlink:href': `#icon-${e.name}` }, null, 8, ['xlink:href'])]
        )
      )
    )
  return (i.render = o), (i.__scopeId = 'data-v-7a1e4f22'), i
})

Have you solved it

理论上是没法同时兼容vue2、vue3 但是可以做到一份代码分别打出vue2版本的包、与vue3版本的包

可以使用rollup实现

  1. 使用vue-demi开发
  2. rollup.config.js 自定义插件resolveId, vue2的vue-demi 指向vue2版本,vue3的vue-demi 指向vue3版本
  3. 同时要兼容 rollup-import-vue,vue2 的编译使用:https://github.com/KesionX/rollup-plugin-vue-2 vue3的编译使用:https://github.com/vuejs/rollup-plugin-vue

eg: 提供一个不算完整的rollup.config.js ,但能够表达我的意思

import commonjs from 'rollup-plugin-commonjs' 
import vue_2 from "rollup-plugin-ue2";
import vue_3 from "rollup-plugin-vue";

function vueTransformPlugin(isVue2){
    return {
        resolveId (source) {
            if (/vue-demi/.test(source)) {

                if (isVue2) {
                    return "./node_modules/vue-demi/lib/v2/index.mjs";
                } else {
                    return "./node_modules/vue-demi/lib/v3/index.mjs";
                }
            }
        }
    }
}
/**
* returns {import ('rollup' ).RollupOptions}
*/
function getBaseConfig(isVue2){
    const vueConfig = {
        css: true,
        style: {
            preprocessOptions:{
                less: {
                    javascriptEnabled: true,
                }
            }
        }
    }
    const vueComplier = isVue2 ? vue_2(vueConfig) : vue_3(vueConfig);
    return {
        external:[
            /@vue\/composition-api/,
            ...Object.keys (dependencies| {}),
            ... Object. keys (peerDependencies| {}),
        ],
        input: "./src/index.ts",
        output: {
            dir: `dist/${isVue2 ? "u2" : "'u3"}`,
            format: "esm",
            globals: { vue: "Vue" },
        },
        plugins: [
            commonjs(),
            vueComplier,
            vueTransformPlugin(isVue2)
        ]
    }
}

const config_ue2 = getBaseConfig(true);
const config_ue3 = getBaseConfig(false);
export default [config_ue2, config_ue3];

KesionX avatar May 10 '22 17:05 KesionX

如果只使用 jsx 的 render ,不使用template语法可以吗

zss1004504439 avatar Aug 02 '22 09:08 zss1004504439

有示例吗,跑不起来

zss1004504439 avatar Aug 22 '22 02:08 zss1004504439

This library is only compatible with the public API, the vnode-related API is not adapted. It is recommended to use template or JSX with different versions of Vite plugin to generate two versions of the bundle file.

本库仅抹平了公开 API,vnode 相关的 API 并没有做适配。建议使用 template 或 JSX并配合不同版本 Vite plugin 生成两个版本的打包文件。

sxzz avatar Sep 04 '22 15:09 sxzz