vite 在开发和生产中是否对模块导入进行了不同的处理?

Are module imports treated differently by vite in development and production?

我正在尝试将库 (jointjs) 导入 Vue 应用程序。它在 Vue 上被分配为全局 属性 并随后被修改。这是我正在尝试做的事情的简单再现:

import Vue from 'vue';
import * as joint from 'jointjs';
import App from '@/App.vue';

// we need to get our own connectors
let customConnectors={
    f: function() {}
}

Vue.use({
    install: function (Vue) {
        // In development, this works:
        //    _.assign(joint.connectors, customConnectors);
        // as does this:
        //    _.each(customConnectors, (item, key) => { joint.connectors[key] = item;});
        // and this:
        //    for (const connector in customConnectors) {
        //       joint.connectors[connector] = customConnectors[connector];
        //     }
        // but none of those work in production, saying joint is a constant or not extensible
                // this one gives a build error about f not being exported by jointjs/src/connectors
                //    joint.connectors['f'] = customConnectors['f'];
        // this one gives the same error but runs without error; but only when minified, so I think it's actually
                //    just removing the statement 
                joint.connectors.f = customConnectors.f; 
        Vue.joint = joint;
    }
});

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

上面评论中的每个示例在开发中都可以正常工作。 None 它们在为生产而构建时工作。

问题似乎出在生产中,jointjs 的导入被视为常量,但在开发中却不是?

这是我的vite配置:

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')
      }
    ]
  },
  build: {
    chunkSizeWarningLimit: 600,
  }
});

这是故意的行为吗?我缺少构建选项吗?

如果有帮助的话,这里是一个复制回购协议:https://github.com/dovrosenberg/vite-test

谢谢!

感谢评论中 Estus Flask 的提示,我成功完成了这项工作。

我先用rollup把jointjs转成了ES模块

npm i --save-dev rollup-plugin-commonjs

应该已经安装了 Rollup,因为 vite 使用它。

我在项目根目录下创建了一个rollup.config.js文件:

import commonjs from 'rollup-plugin-commonjs';

export default {
  input: 'node_modules/jointjs/joint.mjs',
  output: {
    file: 'src/plugins/jointjsESM.js',
    format: 'es',
    freeze: false,  // this is key to preventing everything from being constant
  },
  plugins: [
    commonjs({
      // search for files other than .js files (must already
      // be transpiled by a previous plugin!)
      extensions: [ '.js', '.mjs' ],  // Default: [ '.js' ]

      // if true then uses of `global` won't be dealt with by this plugin
      ignoreGlobal: false,  // Default: false

      // if false then skip sourceMap generation for CommonJS modules
      sourceMap: false,  // Default: true
    }),
  ],
};

output.file 值可以指向您希望生成的模块所在的位置。

然后您可以创建 package.json 脚本(或使用 npx)到 运行 rollup --config rollup.config.js

这将在 output.file 位置创建新的模块文件。您可以 运行 在 vi​​te 构建之前将此脚本作为构建管道的一部分。

然后,您从输出的文件中导入而不是 import * as joint from 'jointjs',但是您需要使用您需要的任何部分自己 assemble 联合对象...例如:

import {
   g,
   dia,
   shapes,
   connectors,
} from '@/plugins/jointjsESM.js';

let joint = { g, dia, shapes, connectors};

您还可以将 jointjs 移动为仅作为开发依赖项安装,因为它不会用作构建的一部分。