jorgegorka / svelte-router

Svelte Router adds routing to your Svelte apps. It's designed for Single Page Applications (SPA). Includes localisation, guards and nested layouts.
MIT License
508 stars 42 forks source link

Prefix and public subpath gives 404 #130

Open jobcespedes opened 2 years ago

jobcespedes commented 2 years ago

I am trying to serve a spa from subpath app/. However it is giving 404 errors when https://localhost:5000/app/

The reason for it, its to serve another web site from root (https://example.com/) and this app in app/ (https://example.com/app/), but from a different server

Reproduce

From a base setup, the following steps were followed:

  1. Add app prefix to the app: Ex: <Router {routes} options={ {prefix: 'app'} } />
  2. Move public/ content to public/app.
  3. Change path references in public/app/index.html to include '/app'. Example: src="/build/bundle.js" to src="/app/build/bundle.js"

More details

Step 2

Before step 2, public/ looked like:

public/
├── build
│   ├── bundle.css
│   ├── bundle.js
│   └── bundle.js.map
├── config.js
├── favicon.ico
├── global.css
├── index.html
└── static
    └── fonts

Now it looks like:

public/
└── app
    ├── build
    │   ├── bundle.css
    │   ├── bundle.js
    │   └── bundle.js.map
    ├── config.js
    ├── favicon.ico
    ├── global.css
    ├── index.html
    └── static
        └── fonts

Step 3

index.html content is now:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width,initial-scale=1" />

        <title>Kio web</title>

        <link rel="icon" type="image/png" href="/app/favicon.ico" />
        <link rel="stylesheet" href="/app/global.css" />
        <link rel="stylesheet" href="/app/build/bundle.css" />

        <script defer src="/app/config.js"></script>
        <script
            src="https://cdn.socket.io/4.4.1/socket.io.min.js"
            integrity="sha384-fKnu0iswBIqkjxrhQCTZ7qlLHOFEgNkRmK2vaO/LbTZSXdJfAu6ewRBdwHPhBo/H"
            crossorigin="anonymous"
        ></script>
        <script defer src="/app/build/bundle.js"></script>
    </head>

    <body></body>
</html>

Expected result

https://localhost:5000/app/ loads app index route

Actual result

https://localhost:5000/app/ redirects to https://localhost:5000/app/404

jorgegorka commented 2 years ago

Hello @jobcespedes:

Can you, please, post the contents of the routes file?

jobcespedes commented 2 years ago

Hi Jorge,

Here it is route.js content:

import { get } from 'svelte/store'
import { isAuthenticated } from '$lib/storages/authStorages'
import Index from '$views/Index.svelte'
import Login from '$views/Login.svelte'
import SSO from '$views/SSO.svelte'
import SignUp from '$views/SignUp.svelte'
import Sites from '$views/sites/Index.svelte'
import SiteDetail from '$views/sites/Detail.svelte'
import CreateSite from '$views/create-site/CreateSite.svelte'
import SiteLayout from '$views/sites/_layout.svelte'
import IndexLayout from '$views/_layout.svelte'
import NotFound from '$views/NotFound.svelte'

const isAuth = () => get(isAuthenticated)

const defaultGuard = { guard: isAuth, redirect: '/login' }

const routes = [
    {
        name: '/',
        component: Index,
        layout: IndexLayout,
        onlyIf: defaultGuard
    },
    {
        name: '/login',
        component: Login
    },
    {
        name: '/sso',
        component: SSO
    },
    {
        name: '/sign-up',
        component: SignUp
    },
    {
        name: '/sites',
        component: Sites,
        layout: SiteLayout,
        onlyIf: defaultGuard
    },
    {
        name: '/sites/:id',
        component: SiteDetail,
        layout: SiteLayout,
        onlyIf: defaultGuard
    },
    {
        name: '/create-site',
        component: CreateSite,
        onlyIf: defaultGuard
    },
    {
        name: '404',
        path: '404',
        component: NotFound
    }
]

export { routes }
jobcespedes commented 2 years ago

Hello, Changing something related to sirv in package.json partially help:

diff --git a/package.json b/package.json
index 2a26324..23934ea 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
        "scripts": {
                "build": "rollup -c",
                "dev": "rollup -c -w",
-               "start": "sirv public -s",
+               "start": "sirv public -s app/index.html",
                "lint": "npm run format && eslint --ignore-path .gitignore .",
                "format": "prettier --write --plugin-search-dir=. .",
                "pretty": "npx pretty-quick --write \"{,!(node_modules|public)/**/}*.{js,svelte}\""

However, one issue remains (it could be some config or route missing on our part). Using http://localhost:5000 works. It is redirected http://localhost:5000/app/ automatically. However, using http://localhost:5000/app/ directly in the url bar, does not work. It gives http://localhost:5000/app/404

jobcespedes commented 2 years ago

I found that using http://localhost:5000/app/ directly in the url, looks for a pathname '/app'. So we add one route with than name, redirecting to "/" and now it works. I do not know if it qualified as a bug or just some route missing.

For completion of this issue, I am appending the routes.js with the fix:

import { get } from 'svelte/store'
import { isAuthenticated } from '$lib/storages/authStorages'
import Index from '$views/Index.svelte'
import Login from '$views/Login.svelte'
import SSO from '$views/SSO.svelte'
import SignUp from '$views/SignUp.svelte'
import Sites from '$views/sites/Index.svelte'
import SiteDetail from '$views/sites/Detail.svelte'
import CreateSite from '$views/create-site/CreateSite.svelte'
import SiteLayout from '$views/sites/_layout.svelte'
import IndexLayout from '$views/_layout.svelte'
import NotFound from '$views/NotFound.svelte'

const isAuth = () => get(isAuthenticated)

const defaultGuard = { guard: isAuth, redirect: '/login' }

const routes = [
    {
        name: '/',
        redirectTo: '/app'
    },
    {
        name: '/app',
        component: Index,
        layout: IndexLayout,
        onlyIf: defaultGuard
    },
    {
        name: '/login',
        component: Login
    },
    {
        name: '/sso',
        component: SSO
    },
    {
        name: '/sign-up',
        component: SignUp
    },
    {
        name: '/sites',
        component: Sites,
        layout: SiteLayout,
        onlyIf: defaultGuard
    },
    {
        name: '/sites/:id',
        component: SiteDetail,
        layout: SiteLayout,
        onlyIf: defaultGuard
    },
    {
        name: '/create-site',
        component: CreateSite,
        onlyIf: defaultGuard
    },
    {
        name: '404',
        path: '404',
        component: NotFound
    }
]

export { routes }
jobcespedes commented 2 years ago

Please omit last message. A new pathname and redirect is not needed. My mistake. Running npm ci fixed it.

jobcespedes commented 2 years ago

Still an issue when deploy to web server (npm run build). However, appending # to the end of the URL works. Ex https://example.com/app/#