Does vite handle module imports differently during development versus production?

I am currently working on incorporating the jointjs library into a Vue application. It is being declared as a global property in Vue and then modified accordingly. Below is a basic example of what I am trying to achieve:

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

// custom connectors are required
let customConnectors={
    f: function() {}
}

Vue.use({
    install: function (Vue) {
        // In development, the following methods work:
        //    _.assign(joint.connectors, customConnectors);
        //    _.each(customConnectors, (item, key) => { joint.connectors[key] = item;});
        // and this:
        //    for (const connector in customConnectors) {
        //       joint.connectors[connector] = customConnectors[connector];
        //     }
        // However, none of these methods work in production, throwing errors about joint being a constant or not extensible
        // The statement below causes a build error regarding 'f' not being exported by jointjs/src/connectors
        //    joint.connectors['f'] = customConnectors['f'];
        // This one gives the same error but runs without any issue; However, it only works when minified, potentially just removing the statement 
        joint.connectors.f = customConnectors.f; 
        Vue.joint = joint;
    }
});

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

All the examples mentioned in the comments above function well during development. None of them work once built for production.

The issue appears to be that in production, the jointjs import is treated as a constant whereas in development it is not?

Below is my vite configuration:

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,
  }
});

Is this behavior intentional? Am I missing a build option?

If needed, here is a link to a repository with a reproduction: https://github.com/dovrosenberg/vite-test

Thank you!

Answer №1

Special thanks to the helpful tips provided by Estus Flask in the comments, I have successfully implemented this solution.

My approach involved using rollup to convert jointjs into an ES module initially.

To begin, run npm i --save-dev rollup-plugin-commonjs

It's worth noting that Rollup should already be installed as vite utilizes it.

A configuration file named rollup.config.js was created in the root directory of the project:

import commonjs from 'rollup-plugin-commonjs';

export default {
  input: 'node_modules/jointjs/joint.mjs',
  output: {
    file: 'src/plugins/jointjsESM.js',
    format: 'es',
    freeze: false,  // crucial for preventing everything from being constant
  },
  plugins: [
    commonjs({
      extensions: [ '.js', '.mjs' ],
      ignoreGlobal: false,
      sourceMap: false,
    }),
  ],
};

The value assigned to output.file can be adjusted based on where you want the resulting module to reside.

You can then set up a package.json script (or utilize npx) to execute rollup --config rollup.config.js

This action generates the new module file at the specified output.location. This script can be executed prior to vite build within a build pipeline.

Instead of importing with import * as joint from 'jointjs', you'll import from the generated output file and manually assemble the joint object with the necessary components. For instance:

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

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

In addition, you have the option to designate jointjs solely as a dev dependency since it isn't utilized during the build process.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Animate.css does not function properly when loaded locally

I'm currently using a Flask server to host an HTML file for testing purposes. Within the head of this HTML file, I have linked to a locally stored animate.min.css file (<link rel="stylesheet" type="text/css" href="{{ url_fo ...

How to detect the Back Button or Forward Button events in a single-page application

Currently, I am developing a single-page application that utilizes ASP.NET MVC, Backbone.js, and JQuery. My task involves capturing the browser's back and forward button events for breadcrumb implementation. I previously attempted to use the hashchan ...

What is the process for utilizing the TypeScript compiler with nodejs?

I have a sample code saved in a file called hello.ts Upon the completion of nodejs setup on Windows, execute the following command to install typescript: npm install -g typescript Is there a way to compile hello.ts directly with node.js? While using "T ...

Navigating the art of employing different fonts for a website

I am looking to incorporate the trainway font into my website, but I'm concerned that the user may not have it installed on their device. Is there a way to showcase text in a specific font without requiring the user to download and install it? Thank ...

Express: utilizing rawBody or buffer for a specific endpoint

I am looking to access the rawBody (buffer) specifically for a POST request on one route within my application. Currently, I have the following code snippet in my app.js: app.use(bodyParser.json({ verify: function(req, res, buf) { req.rawBody = buf; }})) ...

Establishing express routing results in API call returning 404 error indicating resource not found

I need some clarification on how to configure my Express routing using app.use and router. My understanding is that I can create a router and then attach it to a route using app.use() to handle all routing related to that route. Can someone assist me in ...

Error Found: Unexpected Colon (:) in Vue TypeScript File

Important Update: After thorough investigation, it appears that the issue is directly related to the boilerplate being used. As a temporary solution, it is recommended not to extract the TypeScript file but keep it within the .vue file for now. In a sim ...

Guide to changing an image on a canvas with KineticJS

I am currently working on developing a canvas that will display a hotel floor view. I have images stored in a database which I am drawing onto the canvas using x and y coordinates from the database as reference points. However, I want to add touch events t ...

Tips for aligning text in MUI Breadcrumbs

I am currently utilizing MUI Breadcrumb within my code and I am seeking a solution to center the content within the Breadcrumb. Below is the code snippet that I have attempted: https://i.stack.imgur.com/7zb1H.png <BreadcrumbStyle style={{marginTop:30}} ...

Updates in dropdown events when options data has been modified

Hey there, I'm wondering about dropdown events. Let's say I have two dropdowns. When a selection is made in the first dropdown, all options in the second dropdown are replaced with new ones. For example, let's say the first dropdown has thes ...

The variable _spPageContextInfo has not been defined, resulting in a ReferenceError

The code in my JavaScript file looks like this: var configNews = { url:_spPageContextInfo.webAbsoluteUrl, newsLibrary: 'DEMONews', listId: '' }; // Attempting to retrieve the List ID $.ajax({ url: configNews.url + "/_a ...

The unexpected blank space appearing beneath my website as a result of images and videos placed on the

There seems to be some random white space on my website between the main body elements and the footer. Interestingly, removing the cat image and videoplayer eliminates this white space. However, I don't want to remove them completely, so I'm tryi ...

Having trouble with looping the CSS background using JavaScript in CodePen

Can someone help me with looping through CSS background images? Why is the background not changing in this code example: http://codepen.io/anon/pen/dGKYaJ const bg = $('.background').css('background-image'); let currentBackground = 0; ...

Should you include the dollar sign in a Vue HTML variable or not?

I’m a bit confused about whether or not I should include $ when using a Vue HTML variable: new Vue({ data: { a: "myData" } }); Do I need to use: <h1>My value is {{ a }}</h1> or <h1>My value is {{ $a }}</h1> What ...

Troubleshooting Node.js and Express: Adding to array leads to displaying "[object Object]"

As a newcomer to web development and currently enrolled in a course for it, I am in the process of creating a test web server before diving into my main project. In this test scenario, my goal is to extract the value from a text block and add it to a respo ...

Transform two fixed elements into dynamic elements using JQuery

Is there a way to replace two static elements in the table <tr class="item-row"> with data from an ajax call instead of just appending to them? Currently, I am using this javascript line to append: $(".item-row:last").after('<tr class="item- ...

Failed promise preventing access to getItems or getCollections in VUE and Directus

I am just starting out with vueJS and Directus, navigating my way through the online documentation to learn more. I am currently on the lookout for a helpful tutorial that provides step-by-step instructions on how to connect to a remote Directus installati ...

Ensure modifications to a variable are restricted within an if statement

I am struggling to find a way to globally change a variable within an if statement and ensure that the modifications persist. User input: !modify Bye var X = "Hello" if (msg.content.includes ('!modify')) { X = msg.content.replace('!modi ...

Adjust the height of a div in JQuery to fit new content after specifying a height previously

I have a division element with an initial height of 0 and opacity set to zero, its overflow is hidden, and it contains some content. <div style='height: 0px; opacity: 0px; display: none; overflow: hidden; border: 1px solid #000;' id='myd ...

What are the steps to modify the authorization header of an HTTP GET request sent from a hyperlink <a href> element?

I have a unique Angular application that securely saves JWT tokens in localstorage for authentication purposes. Now, I am eager to explore how to extract this JWT token and embed it into an HTTP GET request that opens up as a fresh web page instead of disp ...