single-spa / single-spa-svelte

a single-spa plugin for svelte applications
Apache License 2.0
20 stars 3 forks source link

How to run the application in Standalone mode #18

Open EliseuSantos opened 2 years ago

EliseuSantos commented 2 years ago

I would like to know if you have any example of how to configure the application to run in standalone mode as it works with other frameworks: reactjs, angular vuejs...

filoxo commented 2 years ago

Standalone is enabled with React and Vue using standalone-single-spa-webpack-plugin. Standalone mode for Angular has not yet been implemented. single-spa Svelte applications created with create-single-spa use Rollup and so the webpack plugin isn't a viable option to integrate. You'd have to write an equivalent plugin for Rollup to accomplish standalone mode.

webJose commented 1 year ago

It is my humble opinion that create-single-spa generates more problems than it solves.

Here's how you can create a Vite + Svelte project using npm create vite@latest that runs simultaneously as a standalone app as well as a single-spa application.

  1. Create the project running npm create vite@latest.
  2. Open package.json and modify the scripts as shown below.
  3. Open vite.config.ts and modify it as shown below.
  4. Use singe-spa-svelte as documented, but don't do it in main.ts. Instead, leave that untouched and create a new file called spa.ts. Do the thing there.

package.json:

  "scripts": {
    "dev": "vite --mode standalone",
    "build": "vite build",
    "build-sa": "vite build --mode standalone",
    "preview": "vite preview",
    "check": "svelte-check --tsconfig ./tsconfig.json"
  },

vite.config.ts:

import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'

export default function (opts) {
  console.log('Executing Vite %s in %s mode...', opts.command, opts.mode);
  const input = {};
  let preserveEntrySignatures: any;
  let assetFileNames: string;
  if (opts.mode === 'standalone') {
    input['index'] = 'index.html';
    preserveEntrySignatures = false;
    assetFileNames = 'assets/[name]-[hash][extname]';
  }
  else {
    console.log('SPA build.');
    input['spa'] = 'src/spa.ts';
    preserveEntrySignatures = 'exports-only';
    assetFileNames = 'assets/[name][extname]';
  }
  return defineConfig({
    plugins: [svelte()],
    build: {
      target: 'es2022',
      manifest: true,
      rollupOptions: {
        input,
        preserveEntrySignatures,
        output: {
          exports: 'auto',
          assetFileNames
        }
      }
    },
    base: '/spa01'
  });
};

The last property, base, is something you'll have to figure out on your own because it depends entirely on your setup. I use relative paths because I set a proxy for the root project, and when deployed, it runs in K8s, so the same solution works in both environments.

Other than that, this is it. No plug-ins needed, and the project is simultaneously a standalone app and a single-spa app. Just run npm run dev, and your import map needs to point to <your base>/src/spa.ts.

I am writing a series of articles that cover single-spa with Svelte. If you want, you can follow it here.