Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

fix(svelte): Update top-level route list#64272

Merged
fkling merged 7 commits into
mainfrom
fkling/sk/update-top-level-ignore-route
Aug 6, 2024
Merged

fix(svelte): Update top-level route list#64272
fkling merged 7 commits into
mainfrom
fkling/sk/update-top-level-ignore-route

Conversation

@fkling

@fkling fkling commented Aug 5, 2024

Copy link
Copy Markdown
Contributor

tl;dr: Everything is derived from window.context.svelteKit.knownRoutes

buckle up

Context

After the new web app was enabled by default on dotcom I looked at dotcom data in Sentry to see if there was anything out of the ordinary. I noticed a high number of errors related to resolving repository information. The most common non-existing repository that was reported was -/sign-out.

Screenshot 2024-08-05 at 15 39 52

Of course this shouldn't happen. /-/sign-out is the sign out URL and shouldn't be interpreted as a repository.

Currently we prevent SvelteKit from interpreting specific paths as repositories by using the reporev parameter validator:

// src/params/reporev.ts
const topLevelPaths = [
    'insights',
    'search-jobs',
    'saved-searches',
    // ... many more here
]

const topLevelPathRegex = new RegExp(`^(${topLevelPaths.join('|')})($|/)`)

// This ensures that we never consider paths containing /-/ and pointing
// to non-existing pages as repo name
export const match: ParamMatcher = param => {
    // Note: param doesn't have a leading slash
    return !topLevelPathRegex.test(param) && !param.includes('/-/')
}

-/sign-out was not in that list, including others which have been added since this file was originally created.

Adding it would have been the simple solution but having to maintain this list manually has always irked me. Now we have a better way...

Production changes

Client side

It turns out we are already sending a list of known routes to the client in window.context.svelteKit.knownRoutes to basically do the same thing: test whether a given path is a page or a repository.

// src/lib/navigation.ts
let knownRoutesRegex: RegExp | undefined

function getKnownRoutesRegex(): RegExp {
    if (!knownRoutesRegex) {
        knownRoutesRegex = new RegExp(`(${window.context?.svelteKit?.knownRoutes?.join(')|(')})`)
    }
    return knownRoutesRegex
}

// ...

export function isRouteEnabled(pathname: string): boolean {
    let foundRoute: SvelteKitRoute | undefined
 
    // [...]

    if (foundRoute) {
        if (foundRoute.isRepoRoot) {
            // Check known routes to see if there is a more specific route than the repo root.
            // If yes then we should load the React app (if the more specific route was enabled
            // it would have been found above).
            return !getKnownRoutesRegex().test(pathname)
        }
        return true
    }

    return false
}

Why do we have the reporev validator and isRouteEnabled? They basically do the same thing (check whether a path is a known page or a repository) the first (reporev) is used by SvelteKit to determine which route a path corresponds to (i.e. to navigate to the repository page or whether the page doesn't exist) and the second one (isRouteEnabled) is used after the route resolution but before route loading. It's used to trigger a full page refresh to fetch the React version if necessary.

Anyways, since we already have a list of known pages from the server, the parameter validator should just use it too. Except it didn't work, which made the following server side changes necessary.

Server

We register routes in multiple places. Right now knownRoutes is populated from the router created in cmd/frontend/internal/app/ui/router.go, but this does not include /-/sign-out. This route (and others) are defined in cmd/frontend/internal/app/router/router.go (I don't know what the difference is). I extended the sveltekit route registration code so that's possible to register routes from multiple routers.

I couldn't test it yet however because I currently can't get Sourcegraph to run locally.

Development mode changes

After the above changes, navigating to a React only page in development, e.g. /insights would show a 'repo not found error' because window.context.svelteKit.knownRoutes was empty in development. So every non-existing page would be interpreted as missing repository.

Hardcoding a list of known pages again just for development seemed to be a step backwards. So I spent quite a bit of time to find a way to extract the JS context object from the HTML page returned by the origin server and inject it into the HTML page generated by SvelteKit, similar to how we do it for the React app.

Additionally the value of window.context.svelteKit.knownRoutes is now used to setup the proxy to non-supported pages from the server, so we don't have to maintain this regex anymore either:

 // Proxy requests to specific endpoints to a real Sourcegraph
 // instance.
 '^(/sign-(in|out)|/.assets|/-|/.api|/.auth|/search/stream|/users|/notebooks|/insights|/batch-changes|/contexts)|/-/(raw|own|code-graph|batch-changes|settings)(/|$)': { ... }

This means that requesting non-svelte pages will also return the corresponding React version in development.

Test plan

Manual testing.

@cla-bot cla-bot Bot added the cla-signed label Aug 5, 2024
@fkling fkling force-pushed the fkling/sk/update-top-level-ignore-route branch 2 times, most recently from b8b1d61 to a555d0e Compare August 5, 2024 14:25
@fkling fkling marked this pull request as ready for review August 5, 2024 14:25
@fkling fkling requested a review from camdencheek August 5, 2024 14:25
@fkling fkling self-assigned this Aug 5, 2024
@fkling fkling force-pushed the fkling/sk/update-top-level-ignore-route branch from a555d0e to 400c1dd Compare August 5, 2024 14:31
Comment thread client/web-sveltekit/.env Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed anymore since we are loading the real window.context object from the origin server.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This module/plugin now encapsulates all the proxy handling.


// Additional endpoints that should be proxied to the real Sourcegraph instance.
// These are not part of the known routes, but are required for the SvelteKit app to work.
const additionalEndpoints = ['/.api/', '/.assets/', '/.auth/']

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't get rid of all the hardcoding (or I have to add route registration in even more places 🤷🏻 )

Comment on lines +110 to +114
existingValue := fromContext(ctx)
if existingValue != nil {
value.knownRoutes = append(existingValue.knownRoutes, knownRoutes...)
}
next.ServeHTTP(w, req.WithContext(context.WithValue(ctx, contextKey{}, value)))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This combines the list from multiple routes.

Comment thread client/web-sveltekit/dev/vite-sg-proxy.ts Outdated

@camdencheek camdencheek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. You comfortable merging this with one day to release?

@fkling

fkling commented Aug 5, 2024

Copy link
Copy Markdown
Contributor Author

You comfortable merging this with one day to release?

Yes. The user facing/production is rather small and straightforward.

fkling added 4 commits August 6, 2024 01:26
The core problem seems to be that we've not been `await`ing adding the
initialization scripts.
Comment on lines +125 to +127
await this.page.addInitScript(() => {
window.localStorage.setItem('temporarySettings', '{"webNext.welcomeOverlay.dismissed": true}')
})

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@camdencheek Found out why the dialog was still showing locally. This statement needed to be moved out of the conditional.

@fkling fkling enabled auto-merge (squash) August 6, 2024 09:51
@fkling fkling merged commit e4a8ce5 into main Aug 6, 2024
@fkling fkling deleted the fkling/sk/update-top-level-ignore-route branch August 6, 2024 09:53
fkling referenced this pull request Aug 7, 2024
A consequence of https://github.com/sourcegraph/sourcegraph/pull/64272
is that redirecting to the cody marketing page on dotcom didn't work.
That's because `/cody` is not provided by the server as a known page.

A simple fix would be to mark the link as external, but we'd have to
keep in mind to do this in all places (present and future).

A more "central" fix is to add this page to a hardcoded list of known
pages that are not provided by the server.
fkling referenced this pull request Aug 7, 2024
There couldn't isn't a 'one step' way to start a local Sourcegraph
instance with the SvelteKit app.

This commit adds `sg start enterprise-sveltekit` to fix that.

The changes in https://github.com/sourcegraph/sourcegraph/pull/64272
allow us to run the vite dev server in front of the Sourcegraph
instance, instead of building the assets and having them served by
frontend.
This gives us the benefit of hot module reloading and in general seems
to be a less fragile approach.

It's basically the same what we do with the React app in development
mode.
fkling referenced this pull request Aug 7, 2024
Fixes srch-851

A consequence of https://github.com/sourcegraph/sourcegraph/pull/64272
is that redirecting to the cody marketing page on dotcom didn't work.
That's because `/cody` is not provided by the server as a known page.

A simple fix would be to mark the link as external, but we'd have to
keep in mind to do this in all places (present and future).

A more "central" fix is to add this page to a hardcoded list of known
pages that are not provided by the server.


## Test plan

Manual testing
fkling referenced this pull request Aug 8, 2024
There currently isn't a 'one step' way to start a local Sourcegraph
instance with the SvelteKit app.

This commit adds `sg start enterprise-sveltekit` to fix that.

The changes in https://github.com/sourcegraph/sourcegraph/pull/64272
allow us to run the vite dev server in front of the Sourcegraph
instance, instead of building the assets and having them served by
frontend.
This gives us the benefit of hot module reloading and in general seems
to be a less fragile approach.

It's basically the same what we do with the React app in development
mode.

## Test plan

`sg start enterprise-sveltekit` starts the vite dev server as well as
the sourcegraph instance. Navigating to
`https://sourcegraph.test:3443/search` opens the Svelte app (when
enabled and logged in). Making a change in a source file updates the web
page immediately.

`sg start web-sveltekit-standalone` still works
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants