sveltevitesingle-spa

How to modify Vite + Svelte project in a way that the resulting JS module exports what I want


Long Story Short

I need to know how I can tell Vite that, when building my Vite + Svelte application created with npm create vite@latest (Svelte + TypeScript), the resulting JavaScript bundled module also needs to export what I want instead of creating a pure side-effects module.

Details

Ok, this is the thing: I need to learn single-spa to convert some application. My application is already MiFe'ed and in React, and since I think Svelte does a better job, I would like to take the opportunity to move to Svelte for the shell (root) project.

I am essaying my conversion like this:

  1. Create a Vite + Svelte application (I don't want SvelteKit for this because I want single-spa to route things).
  2. Create some mock of my application's homepage and set a place where other MiFe's will load.
  3. Install single-spa in this, my new root project.
  4. In main.ts, do registerApplication() for a trivial MiFe project, then start().

I did this, no issues and it seems to be working.

What I cannot get to work is the trivial MiFe project.

To create this trivial project, I decided to also do a new Vite + Svelte project. I did it like this:

  1. Create the project using npm create vite@latest and selecting Svelte with TS.
  2. npm i single-spa-svelte
  3. Export the 3 main lifecycle functions as per this document, which is the documentation of the package in step 2.

This is main.ts:

import singleSpaSvelte from "single-spa-svelte";
import App from './App.svelte';
import './app.css';

const lc = singleSpaSvelte({
  component: App,
});

export bootstrap = lc.bootstrap;
export mount = lc.mount;
export unmount = lc.unmount;

I then do (for this trivial MiFe application/parcel), npm run build and npm run preview. Now I have the server running. I examine the created dist folder to obtain the index.js' exact name (it has a hash to avoid caching issues) and copy and paste this into my root application, where registerApplication() is called, like this:

registerApplication(
    'spa01',
    () => import('http://localhost:4173/assets/index-b10091c0.js'),
    '/spa01',
    { domEl: document.getElementById('spa01') }
);

Then I run my root and voilá! It doesn't work. The module object being returned by the dynamic import() call is returning a module with zero exports.

I know this because I modified the function to log to the console the result of awaiting the dynamic import() call.

My conclusion is that Vite is bundling all modules into this one module that doesn't export anything.


Solution

  • You either have to put Vite into library mode, or configure it to preserve the exports (which happens by default in library mode).

    export default defineConfig({
      build: {
        lib: {
          name: 'MyLib',
          fileName: './src/main',
        },
      }
      // ...
    });
    
    // or
    
    export default defineConfig({
      build:{
        rollupOptions: {
          preserveEntrySignatures: 'strict',
        }
      },
      // ...
    });
    

    Would recommend just using SvelteKit, though.