vitejs / vite-plugin-vue2

Vite plugin for Vue 2.7
MIT License
544 stars 46 forks source link

vite-plugin-vue2 does not support some components of ElementUI #16

Closed fychinesepjj closed 2 years ago

fychinesepjj commented 2 years ago

vue@2.7 和 ElementUI@2.15 可以通过 vue-cli 正常打包与渲染( webpack,参考的官方文档 ) 但切换成 vite +vite-plugin-vue2 后,部分组件如 el-table无法渲染且无任何异常错误。 这个问题通过 webpack 就打包不存在问题,所以推断 vite-plugin-vue2 可能存在 bug,希望 Evan You 在百忙之中抽空看下。

dependencies

  "dependencies": {
    "element-ui": "^2.15.9",
    "vue": "^2.7.0-beta.8"
  },
  "devDependencies": {
    "@vitejs/plugin-vue2": "^1.1.1",
    "vite": "^2.9.12"
  }

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue2 Vite App</title>
</head>
<body>
  <div id="app"></div>
  <script type="module" src="/src/main.js"></script>
</body>
</html>

main.js

import 'element-ui/lib/theme-chalk/index.css';

import Vue from 'vue'
import ElementUI from 'element-ui';
import App from './App.vue'

Vue.config.productionTip = false
Vue.use(ElementUI);

new Vue({
  render: h => h(App),
}).$mount('#app')

table component

<template>
    <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="date"
        label="日期"
        width="180">
      </el-table-column>
      <el-table-column
        prop="name"
        label="姓名"
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="地址">
      </el-table-column>
    </el-table>
  </template>

  <script>
    export default {
      data() {
        return {
          tableData: [{
            date: '2016-05-02',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1518 弄'
          }, {
            date: '2016-05-04',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1517 弄'
          }, {
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }, {
            date: '2016-05-03',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1516 弄'
          }]
        }
      }
    }
  </script>

image image

fychinesepjj commented 2 years ago

@yyx990803 Hi,尤大,介于 elementUI 库在国内应用比较广泛,不知你能否抽时间帮忙看下这个问题呢? 目前我测试了 webpack 和 vite 两种构建方案,webpack 方式下运行良好,vite 方式下是只有 el-table有这个问题,怀疑内部可能有一些 hack 语法无法支持,不过从运行结果看又没有任何异常提示,让我无法定位错误,所以需要你的支持,谢谢!

yyx990803 commented 2 years ago

根本原因是 element-ui 用的是 cjs 语法然后 require 了 vue,导致它引用了 cjs 版本的 vue,而你的主应用跑的是 esm 版本的 vue(实际上等于应用里跑了两个 Vue)

这个情况在 Vue 3 依赖里比较少见,可以通过默认强行制定 vue 的解析路径解决。

fixed in 1.1.2

fyeeme commented 2 years ago

上次也碰到了,以为是因为beta版本导致,没有在意。

fychinesepjj commented 2 years ago

@yyx990803 感谢尤大的回复~,这个细节我确实没注意到。 @fyeeme 也是对比 webpack 和 vite 两种打包方式后,才确认不是 Vue2.7 beta的问题,ElementUI 嫌疑更大

anyesu commented 1 year ago

commit/9a78726 改完后还是有问题,开发模式能显示 el-table 了,但打包后显示不出来。

"vue": "2.7.14"
"vite": "4.4.9"
"@vitejs/plugin-vue2": "2.2.0"
"element-ui": "2.15.13"

debug 后发现,@rollup/plugin-aliasresolvePluginscreateResolver 两处地方实例化,只有在 createResolver 中拿到的 resolve.alias 是修改后的预期值,而 resolvePlugins 在 configResolved 之前执行 ,所以拿到的 resolve.alias 是修改前的原始值。这两处地方入参不一致应该会有问题,但开发模式竟然能正常运行而打包模式不行,就很奇怪。

而且,按照 Vite 文档描述的,修改 resolve.alias 的代码应该写在 config 钩子而不是 configResolved 钩子中:

const elementUiVueAliasPlugin = (): VitePlugin => ({
  name: 'element-ui-vue-alias',
  config(config) {
    const alias = config.resolve?.alias;
    if (!alias) {
      return {
        resolve: {
          alias: {
            vue: 'vue/dist/vue.runtime.esm.js'
          }
        }
      } as UserConfig;
    }

    if (Array.isArray(alias) && !alias.some(({ find }) => find === 'vue')) {
      alias.push({
        find: 'vue',
        replacement: 'vue/dist/vue.runtime.esm.js'
      });
    } else if (!alias['vue']) {
      alias['vue'] = 'vue/dist/vue.runtime.esm.js';
    }

    return null;
  }
});

临时解决办法就是项目配置中手写 resolve.alias :( 参考

// vite.config.ts
export default defineConfig({
  resolve: {
    alias: [
+     {
+       find: 'vue',
+       replacement: 'vue/dist/vue.runtime.esm.js'
+     }
    ]
  }
});