vue.jsvite

why my vite config(optimizedeps.include) is not working?


EDIT: I have create a minimal reproduction, please check this
For some reasons, I have to copy github:event-source's code to my own vite project and use it. I download the code and put it in 'src/utils/eventsource/index.js', and set my vite.config.js like following

export default defineConfig({
  build: {
    commonjsOptions: {
      include: [/src\/utils\/eventsource\/index.js/, /node_modules/],
    },
  },
  optimizeDeps: {
    include: ['src/utils/eventsource/index.js'],
  },
});

I tried import this module by 3 ways and start a dev server:

  1. import { EventSourcePolyfill } from '../utils/eventsource': an error will be printed in the console: Uncaught SyntaxError: The requested module '/src/utils/eventsource/index.js' does not provide an export named 'EventSourcePolyfill'
  2. import * as eventsource from '../utils/eventsource';: works well but when I use const { EventSourcePolyfill, NativeEventSource, EventSource } = eventsource; to get EventSourcePolyfill, NativeEventSource,and EventSource and print them in console, they are all undefined
  3. import eventsource from '../utils/eventsource';: The same error as first way's is printed error

Solution

  • Vite dev and build have different toolchains (esbuild and Rollup), it's common for them to work differently. CommonJS modules are supposed to be imported as default in ES modules, so regardless of the configuration the correct way to use it is:

    import eventsource from '...'
    const {EventSourcePolyfill} = eventsource
    

    optimizeDeps.include and build.commonjsOptions.include options may work for NPM packages but may not work for local modules.

    This can be fixed by using local dependency and npm i:

      "dependencies": {
        "eventsource": "file:./src/utils/eventsource"
      }
    

    This also requires to create dummy package.json file in src/utils/eventsource in order for it to be processed as a package, then it can be imported as eventsource.

    Similarly, resolve.alias can be used in Vite configuration for the same purpose, this doesn't require extra package.json:

    import { fileURLToPath, URL } from "url";
    ...
    resolve: {
      alias: {
        "eventsource": fileURLToPath(new URL("./src", import.meta.url)) + '/utils/eventsource/index.js',
      }
    },
    

    Alternatively, Vite CommonJS plugin could be used (not to be confused with Rollup plugin that uses build.commonjsOptions.include):

    import { defineConfig } from 'vite';
    import commonjs from 'vite-plugin-commonjs'
    
    export default defineConfig({
      plugins: [
        commonjs({
          filter(id) {
            return id.match(/[\/]src[\/]utils[\/]eventsource[\/]index.js/)
          }
          ...
    

    Alternatively, the module could be rewritten as ESM instead of CJS/UMD with only few changes.

    The following UMD wrapper:

    (function (global) {
      "use strict";
    
      ...
    
      (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
          var v = factory(exports);
          if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
          define(["exports"], factory);
        }
        else {
          factory(global);
        }
      })(function (exports) {
        exports.EventSourcePolyfill = EventSourcePolyfill;
        exports.NativeEventSource = NativeEventSource;
        exports.EventSource = R;
      });
    }(typeof globalThis === 'undefined' ? (typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : this) : globalThis));
    

    Is replaced with :

    export default (function (global) {
      "use strict";
    
      ...
    
      return {
        EventSourcePolyfill;
        NativeEventSource;
        EventSource: R;
      };
    })(globalThis);