Vite开发与生产环境模块导入处理是否有差异?修改jointjs生产环境失效
问题原因
你遇到的问题不是Vite的Bug,属于生产构建阶段的预期优化行为:
- Vite在生产构建时会使用esbuild对ES模块进行压缩优化,ES规范本身规定模块的导出对象是不可修改的,开发环境为了兼容热更新等能力,没有开启严格的导出冻结限制,所以你直接修改导入的joint对象可以生效。
- 生产构建时esbuild会将第三方库的导出对象标记为不可扩展的常量,你对
joint.connectors的赋值操作会被判定为无副作用的死代码,要么被直接移除,要么运行时抛出不可修改的报错。
可行解决方案
方案1:拷贝导出对象后修改(最推荐,无副作用)
不要直接修改原始导入的joint对象,先做一层浅拷贝后再修改拷贝后的对象,最后挂载到Vue全局即可:
import Vue from 'vue'; import * as joint from 'jointjs'; import App from '@/App.vue'; let customConnectors={ f: function() {} } Vue.use({ install: function (Vue) { // 浅拷贝joint对象,避开ES模块导出不可修改的限制 const customJoint = Object.assign({}, joint); // 修改拷贝后的对象的connectors属性 Object.assign(customJoint.connectors, customConnectors); // 挂载拷贝后的对象到Vue全局 Vue.joint = customJoint; } }); let app = new Vue({ // 传入拷贝后的customJoint而非原导入对象 joint: Vue.joint, render: h => h(App) }).$mount('#app');
方案2:修改Vite配置关闭对应优化
如果你不想改动业务代码,可以在Vite配置中关闭对jointjs的导出常量优化:
import { defineConfig } from 'vite'; import { createVuePlugin } from 'vite-plugin-vue2'; import ViteComponents from 'vite-plugin-components'; import path from 'path'; export default defineConfig({ plugins: [ createVuePlugin(), ViteComponents({ }) ], server: { port: 8080 }, resolve: { alias: [ { find: '@', replacement: path.resolve(__dirname, 'src') } ] }, // 新增以下配置 optimizeDeps: { exclude: ['jointjs'] }, build: { chunkSizeWarningLimit: 600, esbuild: { // 保留对导入对象属性赋值的副作用代码 keepNames: true } } });
方案3:使用UMD版本引入jointjs
你也可以直接在入口HTML中通过script标签引入jointjs的UMD版本,此时joint会挂载为window全局对象,不受ES模块导出规则限制,可以直接修改属性。
内容的提问来源于stack exchange,提问作者Dov Rosenberg
相关产品推荐
相关产品推荐

