ionic-team / ionic-cli

The Ionic command-line interface
MIT License
2k stars 651 forks source link

Multi-App Configuration Issue #4121

Open Domvel opened 5 years ago

Domvel commented 5 years ago

Describe the bug https://ionicframework.com/docs/cli/configuration#config-file

In a multi-app project, apps share a single ionic.config.json file at the root of the repository instead of each app having their own.

Is this correct for the latest version of Ionic? I created the multi-apps with no-deps parameter and both apps also have their own ionic-config.json. Also .gitignore, tslint.json, package.json.

To Reproduce

  1. Create the root project. ionic start my-apps (blank template)
  2. Open the ionic.config.json and add the property "projects": {}.
  3. Create your apps by ionic start app1 --no-deps. (app1 and app2) (blank template)
  4. See that every app has its own ionic.config.json.

Expected behavior I'm not sure how the multi-app feature of Ionic works. I though I have a root project with all the project files like package.json and ionic.config.json. And the "sub-apps" only contains the sources without separated configuration files etc. Ok they can have a package.json. But why are there all the dependencies, even though the root dependencies should be used? Or do I understand something wrong? Or is the documentation wrong?

Screenshots If applicable, add screenshots to help explain your problem. image

Browser and OS (please complete the following information):

Additional context I want to create one app base (root) with multi-app feature. Each apps should use the shared root components, services, etc. But an app can also have their own components. TSLint, TSConfig, Unit-Test-Config, gitignore, etc. should be shared. But currently each subapp have a own config. Exactly the same. DRY. Maybe this is a bug for the Ionic core repository or CLI? But perhaps it's only a documentation issue. I don't know who this should actual work. This is my first attempt of building a multi-app. But the fact is, each app in a multi-app project has its own ionic.config.json. The docs says there should only be one shared in the root. Or does this mean, I should delete the config files in my sub-apps?

imhoffd commented 5 years ago

@Domvel The Ionic CLI doesn't have opinions about how you structure your monorepo. People could choose to have apps connected with a single angular.json or one for each app, or something in between. People could choose to install dependencies in each project or at the root, or something in between (this is what the Ionic CLI repo does, but it uses lerna to hoist dependencies). This goes for any of the tools which have config files and could be used at a higher level (.gitignore, tsconfig.*.json, tslint.json).

Remember, the CLI docs (aside from command reference) don't assume you're using Angular. One could create Ionic React apps alongside Ionic Angular apps and the multi-app feature would continue to work, blissfully unaware of the project's internals.

If you don't want these config files in your apps, delete them and make it work for your preferences.

johneast commented 5 years ago

I actually hit this issue last night. I have a mono-repo which contains back end code and multiple front end apps, the general structure is something like the following

- /apps/
---- /app1/
        ... An Angular App. No deps or angular.json here
---- /app2/
        ... An Angular App. No deps or angular.json here
- /back-end/
    ... back end source code and configuration
- /libs/
    ... shared code
- /node_modules/
    ... All deps for all projects here
- angular.json
- ionic.config.json
- package.json
- tsconfig.json

I came to add app3 using the ionic cli and tried the following command:

$ ionic start --no-deps
? Project name: apps/app3
? Starter template: sidemenu

The cli then went and made an app called apps-app-3 in the root of my repo. Where I was hoping it would make an app called app3 in the apps folder. So I deleted the project it had made and re-ran the command from the apps folder. Not much of a problem, however the cli assumes that you want to have an angular.json file in the project folder. For me (and a reasonable amount of people using mono-repos), I want to have one angular.json file in the root of my repo. To get to where I wanted to be I then had to copy the project property from the created angular.json and add it the one at the root of my repo, changing all of the paths and target names which was tedious.

I was wondering if it would be possible for the cli to infer values from an existing angular.json file if creating an angular app.

For instance, if creating a new angular ionic app, then the cli could use the newProjectRoot property from the angular.json file in the same folder if it exists.

Or, leave the start functionality the same, and add an application option to the generate command which adds an application to the existing workspace. This is similar to how ng allows you to create mutiple angular apps in the same workspace.

imhoffd commented 5 years ago

@johneast The apps-app-3 behavior is probably worth a separate issue.

As for the angular.json stuff, did you read my comment above? I'm not convinced the behavior should change at this moment. I understand that it's awkward to have to delete the extra angular.json and add the app config to the root angular.json. Let me go into why it likely won't change for a while:

Right now we use an old-fashioned way of starting projects. We download an archive that contains a working app, and make file changes from there. The Angular CLI and Vue CLI both use a more modern approach, where files and their contents are conditionally provisioned in a template/logic-based approach.

I would argue if we're going to start making changes to framework-based files (which change constantly, i.e. .angular-cli.json -> angular.json) after the starter is downloaded, then we should change our approach. See https://github.com/ionic-team/ionic-cli/issues/3499 for this. This will require a lot of work, and it's work we likely won't be able to prioritize for a while.

josh-m-sharpe commented 5 years ago

"The Ionic CLI doesn't have opinions about how you structure your monorepo."

@dwieeb Then what is the Ionic CLI doing? Kinda detecting that ionic.config.json has a projects attr and stuffing config in that? And also honoring the --project flag and passing that onto lower level CLIs?

If the end result is that I still have to make manual changes to various angular.json(s) and modify them accordingly, shouldn't I have to do that for my ionic.config.json(s) as well? And if I have to do that, why bother with this ionic CLI at all?

What's extremely difficult to get past is that the docs as they stand today leave us with a non-functioning app. I understand there's a world of flexibility in setting up a monorepo, so maybe the CLI can't just create one, but if that's the case, could we work to build some example apps that others could leverage as a starting point?

josh-m-sharpe commented 5 years ago

I think it's also worth noting that the ionic CLI, generally speaking, is opinionated about how an app is structured. So we're all used to running ionic start and ionic generate and the CLI spitting out a viable app structure. This is an extremely positive thing.

But then this multi-tenant philosophy, without opinions, comes out of left field and leaves everyone spinning not knowing what to do.

josh-m-sharpe commented 5 years ago

@Domvel - it seems odd your apps each have an ionic.config.json. Mine don't. Check out this repo I put together. It has explicit steps based on the Ionic CLI Documentation (even a setup.sh script!) to create the repo. Did you do something different? In the steps you outlined above I don't see that you cd apps before running ionic start maybe that has something to do with it?

imhoffd commented 5 years ago

@josh-m-sharpe To be clear, I agree. I understand how Angular monorepos are expected to work, and that ng generate application has the intended effect, and that the equivalent functionality is missing in Ionic. I mentioned at the end of my second comment what I think is a prerequisite for continuing work on the multi-app feature.

What's implemented now is a bare-bones effort to get the Ionic CLI to even operate in a monorepo, which wasn't easy to begin with. Step 2 is adding intelligence around the framework files, which in my opinion requires us to rethink our starters. Luckily, Step 1 allowed the Ionic CLI to be flexible enough for power users to do what they needed to do.

What's extremely difficult to get past is that the docs as they stand today leave us with a non-functioning app

Yeah, we're missing a full tutorial for setting up an Ionic Angular monorepo, which would utilize the multi-app feature and the Angular monorepo feature. The docs as they are today are meant to be a reference for how the Ionic CLI deals with multiple apps in a project (not how to setup an opinionated, full-featured monorepo). We haven't pushed this feature very hard because it still requires manual work, but we should still have the documentation for what exists today. If you like, we can use your issue to track that.

johneast commented 5 years ago

@dwieeb Thanks for the reply.

I appreciate how awkward it can be to code against frameworks that can change at any given time. The process at the moment is a little awkward, however it is workable and the fact that once the projects in the repo are all set up everything works is great.

I like the sound of #3499. It definitely sounds like the way to go in order to make ionic start extensible and future proof.

Some documentation or walkthroughs about how to setup a mono-repo and add ionic projects to it would be good. I'd be happy to contribute if need be.

Domvel commented 5 years ago

Now I have my multi-app. πŸ˜“ But can't execute ionic cordova run android for a specific project.

Does not work:

ionic cordova run android --project=app1

Sorry! ionic cordova run can only be run in an Ionic project directory.

Workspace (not all files listed)

root
|- src
|  |- libs (folder with shared stuff)
|  |- apps
|     |- app1 (same for app2)
|        |- main.ts
|        |- app.module.ts
|- angular.json
|- ionic.config.json
|- config.xml
|- package.json

ng serve --project=app1 works well.

Background of my workspace: It's a monorepo with 2 apps with minimal differences. So the main part is in the libs folder. There is a common package.json and deps. Also the android platform is shared. Only the angular module is different because of some pages etc. It works in browser when using the Angular CLI ng and project property.

But the Ionic commands does not work. I think the project option is ignored? It tells me that there is no ionic.config.json but it is. Look:

ionic.config.json

{
  "name": "my-apps",
  "integrations": {
    "cordova": {}
  },
  "type": "angular",
  "projects": {
    "app1": {
      "name": "App1",
      "integrations": {
        "cordova": {}
      },
      "type": "angular",
      "root": "src/apps/app1"
    },
    "app2": {
      "name": "App2",
      "integrations": {
        "cordova": {}
      },
      "type": "angular",
      "root": "src/apps/app2"
    }
  }
}

Any my angular.json is also set up well, I think. Angular serve works well. The json is huge. I post it on Stackblitz. I can't believe that the Angular config file is a json and no js-file. There is so much repeated code. But this is another topic. ... angular.json And heres the package.json

What are the criteria for the error message?

Sorry! ionic cordova run can only be run in an Ionic project directory.

If I run ionic init and enter the name, nothing will change. Because it already exists. What's wrong? πŸ€”

imhoffd commented 5 years ago

@Domvel I just walked through this again. Here's my repo: https://github.com/dwieeb/ionic-multiapp

I ran into a couple weird things with integrating Cordova, which must've been recent bugs, so I fixed them up: https://github.com/ionic-team/ionic-cli/commit/167a68cc2c581c1e82e7c8cd8498317fed15c960 and https://github.com/ionic-team/ionic-cli/commit/4e8a2268d24498c66e1867c81a62cfd866cc2d4c

I'm not getting the "can only be run in an Ionic project directory" error that you're seeing, though. Could you go through my steps and see where we might differ?

Domvel commented 5 years ago

@dwieeb Thanks. Yes, I did the same, more or less. I created the sub-apps manually without ionic start. But the workspace was initially create by the Ionic CLI. Whatever, I wondering how do Ionic detect a non-ionic repo?

Here is my workspace demo. ng serve works. It's a reduced minimal application from my original project. I hope I didn't missed anything. The philosophy of this project is to avoid code repetition. Also for the project setup. I don't want the same stuff for each app as copy. I use one setup and only load different Angular modules. Angulars apps only differs from the bootstrapped module. Only one package.json, tsconfig.ts etc. Also only one Cordova Android for both apps. The app-id is replaced later automatically in Jenkins or manually by scripts. The apps are really identically by the base. Only a few pages etc. are different. This should work.

Maybe the problem is that the apps do not have projects-setups like the root. I don't want a package.json etc. for each app. That's nonsense in my case. Because each app uses the same deps, same base etc. It sould only build the Angular app and wrap it in Cordova for Android. But what's wrong?

ionic info
[ERROR] Error while loading config (project config: .\ionic.config.json)

        Unknown project file structure. Run ionic init to re-initialize your Ionic project. Without a valid project
        config, the CLI will not have project context.

[WARN] You are not in an Ionic project directory. Project context may be missing.

Ionic:

   Ionic CLI : 5.2.5

Utility:

   cordova-res : not installed
   native-run  : 0.2.8

System:

   NodeJS : v10.15.3
   npm    : 6.4.1
   OS     : Windows 10

ionic init
? Project name: my-apps
[OK] Your Ionic project has been initialized!

(ionic init without changes.)

Domvel commented 5 years ago

Ok, now I am one step further. I removed the root stuff from the ionic.config.json.

From:

{
  "name": "my-apps",
  "integrations": {
    "cordova": {}
  },
  "type": "angular",
  "projects": {
    "app1": {
      "name": "App 1",
      "integrations": {
        "cordova": {}
      },
      "type": "angular",
      "root": "src/apps/app1"
    },
    "app2": {
      "name": "App 2",
      "integrations": {
        "cordova": {}
      },
      "type": "angular",
      "root": "src/apps/app2"
    }
  }
}

to:

{
  "projects": {
    "app1": {
      "name": "App 1",
      "integrations": {
        "cordova": {}
      },
      "type": "angular",
      "root": "src/apps/app1"
    },
    "app2": {
      "name": "App 2",
      "integrations": {
        "cordova": {}
      },
      "type": "angular",
      "root": "src/apps/app2"
    }
  }
}

Now Ionic tells me what is wrong or what it is expecting.

 ionic cordova run android --project=app1

√ Creating .\src\apps\app1\www directory for you - done!
[ERROR] Cannot load Cordova config.

        Could not find necessary file(s): config.xml, package.json.

        - .\src\apps\app1\config.xml
        - .\src\apps\app1\package.json

        You can re-add the Cordova integration with the following command: ionic integrations enable cordova --add

Hmmm πŸ€” It looks like I have to create the package.json and config.xml stuff for each app. But is there a way to use this what is in my root folder? As I wrote. Each app should use the same deps and Android config. The app-id, name, resources, etc. will be changed later by scripts. (e.g. Jenkins) Should I keep the root integrations cordova? I expected that Ionic just build the Angular app by the angular build commands and wrap it in Cordova Android from the root.

I understand why it needs separated package.json and config.xml. Because of the name and id. But the rest is equal to each app. I don't want copies.

UPDATE: Now I added the config.xml and package.json by the Ionic and NPM CLI. It works. It's just a dummy package json without deps but have the cordova property from root. It's duplicated code but I if this is the only solution for now I have to use it. I create a branch on github for it ...

UPDATE 2: Ok, it works until apk is created and installed. But on runtime I get the error: net::ERR_CONNECTION_REFUSED (http://localhost/)

Here's the current branch about Cordova Android build. But on runtime it fails on localhost connection refused. Maybe I have to set up each app with the complete package json and deps. But I don't like it. Because as I wrote: I have to manage the same stuff in each app. This is really annoying and error prone.

Can I set the package and config xml in ionic.config.json? A common use for all apps. But I understand the inconsistency. Each app requires an own id, name and resources. But maybe there is a way for my case of replacing the id, etc. by a build script (Jenkins). No need for package.json and config.xml in each app. But it looks like that this is not the working way.

Now I'm with NX to check this way. I see that there is only one package.json in the root. But each app have separated tslint.json (but extends from root tslint file). But because of the missing package.json in the apps directory, Ionic will fail too. I think we have to change this. Ionic Cordova should work with multi-apps monorepos like from NX created. Maybe Xplat is the solution.

Update: I tried nx. Ionic fails because requires the package.json for each sub-app. -.- It feels like pseudo-multi-app / pseudo-monorepo. Because it's nothing else as multiple ionic apps in one folder. For what is the no-deps option? Currently it's not really a multi-app Ionic workspace. Ok, for Angular it is a multi-app workspace. But for Ionic it's better to create seperated repositories because it does not really support multi-app monorepos. The project in ionic.config.json is just for shortcut reasons. Same as cd to the folder and execute the regular commands. - I'm tired.

TL;DR: How to use one package.json deps like Ionic and Angular for all apps? Currently Ionic requires to have a package.json for each app. But maybe it's possible to leave the deps blanks and use it from the root package? Maybe it's a node_module folder path option. idk In best case I also want only one config.xml and the other project setup stuff like tslint.json too. Ok, the app id is different. But this could be a option. e.g. in ionic.config.json?

At this moment I have a working "multi-app" monorepo. With 2 apps but 3 package json with exactly the same deps. One for app1, one for app2 and one for the lib folder. ...

Domvel commented 5 years ago

A workaround (more or less) could be to refer the packages in the dummy package of an Ionic App. (Inspired by Xplat). Not tested. (I'll test it next week).

root
β•žβ• apps
β”‚  β•žβ• app1
β”‚  β”‚  β”œβ”€ package.json
β”‚  β”‚  └─ config.xml
β”‚  β•˜β• app2
β”‚     β”œβ”€ package.json
β”‚     └─ config.xml
β”œβ”€ package.json
└─ angular.json

The root package.json contains all deps. And the package.json for each app contains a reference to the root node_modules as file-ref.

A app package json:

{
  "name": "foobar",
  "version": "0.0.0",
  "dependencies": {
    "@ionic/angular": "file:../../node_modules/@ionic/angular",
    "rxjs": "file:../../node_modules/rxjs",
    "zone.js": "file:../../node_modules/zone.js",
    "...": "etc. this is just a comment from me. :)"
  }
}

But note: Xplat uses Ionic Capacitor for the apps. There fore no config.xml is required at this place. Also note that you need the cordova property in your package.json to build Ionic Corodva. Xplat uses the capacitor.config.json file for the Android build. I have no experiences about Ionic Capacitor. Not yet. Once difference is, that you also commit the Android folder to your repo and have the native code running in Android Studio... At this moment, I don't want to use Capacitor. And I don't like this way. Ionic Cordova should just optional package.json and config.xml. With this workaround above you still have to provide the cordova-property in package.json in each app. I don't know how to refer.

domske commented 5 years ago

This is an Angular mutli app and library workspace: Take a look to the tag of my repository. Demo here

Created by the commands:

ng new my-workspace --createApplication="false"
ng generate application app1
ng generate application app2
ng generate library shared-lib

Note that there is no need for a package.json for the library folder. It's created e.g. because you could export this library as npm package. Generelly there is no need to have multiple package.json files in your workspace. See app1 and app2 they have no package.json.

Ionic Cordova should repect this workspace (multi-app / monorepo) structure and behavior. This is generated by Angular and official recommended. Ionic v4 is still a special Angular project. Especially the Cordova part. This should be fixed by:

*1) This could be optional. Each app or shared from root and handled manuelly. e.g. change the app id before build.

Generally we want only one project / workspace setup with one place to manage the dependencies. And do not repeat your self. (DRY). So we do not want to have the same configurations for each app in the workspace. Unfortunately the angular.json is still "messy". In my opinion it should be a js-file to reuse configurations. You could handle it with a node js-file. But I do not want special "hacks". Follow the mainstream / the standards to reduce the project maintenance.

Domvel commented 5 years ago

@dwieeb What are the build commands of Ionic CLI doing? (see below) My idea is to seperate the Angular build and the Ionic Cordova Build.

  1. Build the Angular project and copy the build into the www folder.
  2. Execute Ionic Cordova build to take the www folder etc. (But not try to build Angular again.)

Is this possble? Trigger the build manually in separated parts? Maybe only use ng and cordova without ionic cli? But I do not want to miss anything.

My scripts (maybe not up to date. It's from Ionic v3. But I think they have not changed.):

Run on Android ionic cordova run android

Build for Android ionic cordova build android --release --prod --generateSourceMap false

Update: Ok, I built the Angular project and build the Cordova app. I have a white screen. I have put a text between the app-root tag in the index.html to see "Loading...". And it's still displayed. So Angular does not load. I think it's because Angular needs a server. Not just locally view the index.html. But where is the magic? What is Ionic doing? Solution Ok, I figured it out: We need the ionic-webview for Cordova.

Do we need the script-tag cordova.js in the index.html in Ionic v4?

youuri commented 5 years ago

Hey,

I've got the same problem. I'm refactoring multiples apps in a monorepo using angular 8 and ionic 4. I could use the ng serve or ionic serve perfectly using the --project argument but i'm totally unable to build or run using ionic cordova command. It failed saying that i can't find the project.

Domvel commented 5 years ago

@youuri It's because Ionic requires a package.json (with cordova property) and config.xml for each project (app). If you don't want this you have to setup a pure Angular and Cordova project. In my case I built up a Angular multi-app workspace with only one package.json and config.xml and replace the app id. I also use Ionic for the UI and native plugins (Cordova wrapper). But I don't use the Ionic CLI. I just build my Ionic app using ng (Angular CLI) to www folder and build the apk with Cordova. Works great. But this is just a workaround.

youuri commented 5 years ago

@Domvel i got a dumb package.json in each of my apps with the cordova config & plugins in it. I also have a config.xml in each project and it worked as i want in this case.

But when i run ionic cordova run android --project="app1" it failed saying that project could not be found. I've investigate in the vendor file and it seems that's related to angular cli (and it's strange cause when i served the code it's good).

So i think i got a configuration issue between angular.jsonfile and ionic.config.json.

Domvel commented 5 years ago

@youuri Maybe you should use the command without quotes?

ionic cordova run android --project=app1. And check the ionic.config.json.

{
  "projects": {
    "app1": {
      "name": "App 1",
      "integrations": {
        "cordova": {}
      },
      "type": "angular",
      "root": "apps/app1"
    }
}

ONLY the projects property! No other stuff in the root. And the project should also available in your angular.json.

btw: In my case I only have the angular.json and no ionic.config.json. (as I wrote above). I'll upload a demo now to my repo.

Domvel commented 5 years ago

Here it is

A multi-app monorepo build by the official guides of the docs of Angular. Using Ionic for UI and native plugin wrapper and the webview (required for Angular). And build with Cordova. No Ionic CLI.

Note: You have to change the app id in config.xml for each app. You can do it automatically by a node script or a build system like Jenkins.

Disclaimer: Maybe it's not comfortable to add more Cordova plugins. Because proberply you have to complete the integration on installing new plugins. Install the plugins by Cordova, not Ionic. Maybe you have to add the plugins to config.xml too. But this is simple, just look to the package.json. If you want to install new plugins from the Ionic docs. Just remove the ionic keyword of the command. ... It's a promising project setup. But not yet used for real world usage. But I'll use it in the future. But I would appreciate if Ionic will solve the problem we have here soon ..

youuri commented 5 years ago

I'm not sure it's viable in my case. I'll need to have a config.xml & package.json for each ionic app cause they not share all the sames plugins. But it could be if the apps shared the same stack.

Domvel commented 5 years ago

I think there is not the only one workspace setup. It depends on what you want. I have common dependencies because each app uses the same base app (shared lib) and they only differ from the main page etc. But if you have completely different apps who uses separate dependencies like your setup, you need a package.json and config.xml for each app. So Ionic should be more flexible to use these kinds of multi-apps.

Another way is to export a shared library as npm package and use separate repositories with a simple single app Ionic setup and use the shared lib using npm package. One repo for the libs, and a repo for each app. This stops some Monorepo problems, but brings other problems. Such as the use of Angular modules. Especially in conjunction with 3rd party libraries, build and import problems, etc. No system is perfect. You will always have advantages and disadvantages. Either from your source code, IDE or workflow. You have to choose what is the right way for your application. - I have followed the principle of NX and Xplat, but uses the official Angular way for multi-app without the NX stuff to have a lightweight and less special setup. Only the Ionic Cordova CLI brought me some problems.

Conclusion: There is no perfect way to develop multiple apps with the same code base (shared library). There is always one component in your source code, your IDE or build system that causes problems or you have to do without a feature.

For Ionic CLI I just wish some more options to use Cordova for single deps like in my monorepo. I think this could be done by setting some paths and maybe a config file for each app to manage the app id and name. ...

imhoffd commented 4 years ago

πŸ‘‹ Hey all, please see this comment and this wiki article for the latest on Ionic multi-app projects and Angular Monorepos. Using ng generate (not ionic start) with ng add @ionic/angular and ionic init provides a pretty smooth experience, as far as I can tell. Please let me know what you think. Monorepos are hard.

douglasgsouza commented 4 years ago

It seems to be related to that: Wrong build path on Windows 10

ollyde commented 3 years ago

We're doing research into Ionic; created a new React Ionic app; there's no config anywhere; adding it manually does nothing? Any ideas?

Rossella-Mascia-Neosyn commented 2 months ago

@ollyde Have you found a solution?

ollyde commented 2 months ago

@Rossella-Mascia-Neosyn I started using Svelte with Capacitor. Both SSR and SPA; it's excellent.

Rossella-Mascia-Neosyn commented 2 months ago

@Rossella-Mascia-Neosyn I started using Svelte with Capacitor. Both SSR and SPA; it's excellent.

Can you explain how you did it?

ollyde commented 2 months ago

@Rossella-Mascia-Neosyn sure but I'm not in software anymore after 20 years; in hardware now, so this might be outdated.

import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
import adapterNode from "@sveltejs/adapter-node";
import adapterStatic from "@sveltejs/adapter-static";

// Determine the mode - this can be set as an environment variable or changed manually
const BUILD_MODE = process.env.BUILD_MODE || "SSR"; // default to SSR, change to 'SPA' for SPA mode

let adapterOptions = {};

// Switch depending on the mode
if (BUILD_MODE === "SPA") {
    adapterOptions = {
        pages: "build_spa",
        assets: "build_spa",
        strict: true,
        fallback: "index.html",
    };
} else {
    adapterOptions = {
        pages: "target/classes/static/",
        assets: "target/classes/static/",
        fallback: "index.html",
    };
}

const adapter = BUILD_MODE === "SSR" ? adapterNode(adapterOptions) : adapterStatic(adapterOptions);

/** @type {import('@sveltejs/kit').Config} */
const config = {
    // Consult https://kit.svelte.dev/docs/integrations#preprocessors
    // for more information about preprocessors
    preprocess: vitePreprocess(),

    kit: {
        adapter,
    },
};

export default config;

Here's my build SPA bash script for example

#!/bin/bash

# Build the SvelteKit app for Mobile (SPA)

# Function to rename +layout.server.ts files to +layout.server.ts.bak
rename_layout_files() {
    find $SRC_DIR -type f -name "+layout.server.ts" -exec mv {} {}.bak \;
    find $SRC_DIR -type f -name "+page.server.ts" -exec mv {} {}.bak \;
}

# Function to rename +layout.server.ts.bak files back to +layout.server.ts
restore_layout_files() {
    find $SRC_DIR -type f -name "+layout.server.ts.bak" -exec sh -c 'mv "$0" "${0%.bak}"' {} \;
    find $SRC_DIR -type f -name "+page.server.ts.bak" -exec sh -c 'mv "$0" "${0%.bak}"' {} \;
}

# Trap to ensure that restore_layout_files is called if the script exits early due to an error
trap 'restore_layout_files' EXIT

# Abort on any error (including if find or npm run fails)
set -e

# Set env
export PUBLIC_DEV=TRUE
export BUILD_MODE=SPA

SRC_DIR="./src"

# Rename +layout.server.ts files before the build
rename_layout_files

vite build --mode production --base

# Rename +layout.server.ts files back after successful build
# The restore_layout_files function will also be called here due to the trap if the script hasn't exited early
restore_layout_files

npx cap sync
# npx cap open ios
# npx cap open android

# Clear the trap
trap - EXIT