Skip to content

Adding a routes.json manifest file #1824

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

Adding a routes.json manifest file #1824

wants to merge 1 commit into from

Conversation

johnnysprinkles
Copy link
Contributor

This relates to the general topic of making adapter-static more powerful and useful, discussed in various issues including:

sveltejs/rfcs#52
#1533
#1561

When you use adapter-static you get a big tree of files in your build/ folder, and it's up to you to figure out how to serve them in response to incoming requests. The simplest thing to do is check for an exact match and existence of the file on disk. Doing anything more complex would need information about what the routes are. We can currently kind of parse the manifest.js file but it would be much easier to simply open a JSON file, which any kind of runtime or language supports. The output is like this:

jpsimons@Johns-MacBook-Pro sv2 % cat .svelte-kit/build/generated/routes.json
[
  {
    "pattern": "^\\/$",
    "params": [],
    "componentPath": "src/routes/index.svelte"
  },
  {
    "pattern": "^\\/about\\/?$",
    "params": [],
    "componentPath": "src/routes/about.svelte"
  },
  {
    "pattern": "^\\/todos\\/?$",
    "params": [],
    "componentPath": "src/routes/todos/index.svelte"
  },
  {
    "pattern": "^\\/item\\/([^/]+?)\\/?$",
    "params": [
      "id"
    ],
    "componentPath": "src/routes/item/[id].svelte"
  }
]

That's the stock demo app, with the addition of a parameterized route.

My next step is I want to make an "adapter-static tester" in the form of an npx you can run to serve your static build folder. It would be fully decoupled from server-side Node, and would only be implemented in Node for convenience. It will prove that the artifacts could be served by anything.

Note: I tried to do the changelist thing, which I couldn't get to work. Also, a test unrelated to my stuff was already failing.

Before submitting the PR, please make sure you do the following

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpx changeset and following the prompts

@changeset-bot
Copy link

changeset-bot bot commented Jul 4, 2021

⚠️ No Changeset found

Latest commit: 01e78b6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Member

@benmccann benmccann left a comment

Choose a reason for hiding this comment

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

I don't quite understand what you're trying to do. Any static file host can already serve the output of adapter-static and it's not coupled to a Node serving environment. E.g. you can just run python3 -m http.server in the build directory. Is there any new functionality this would allow?

return {
pattern: pattern.slice(1, pattern.length - 1), // strip delimiters
params: route.params,
componentPath: route.a[route.a.length - 1]
Copy link
Member

Choose a reason for hiding this comment

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

there won't be any .svelte files in the build directory, so is this really useful?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True but it's an easy transformation to get from that to the HTML file. Basically replacing .svelte with .html and possibly adding an /index.

@johnnysprinkles
Copy link
Contributor Author

Correct, static file hosting is covered, which is a special case of the web server general case. A couple things:

  1. Actually knowing what the routes are instead of just try/catching on a file read seems like a more correct way of doing things.
  2. Those parameterized routes of course, something like /item/[id], no way to know how to parse the route params and find the corresponding HTML artifact without this info. It can be obtained from regex slicing the JS file but why make it hard?
  3. Aside from parameterized routes, you can certainly imagine a case where there's not a 1:1 correspondence. Maybe for example your web server knows if the user is signed in, and hitting the root / path causes it to serve either an index_anonymous.html or an index_signedin.html. This kind of thing is easier and more robust if you know what all the routes are.

@johnnysprinkles
Copy link
Contributor Author

Also one other thing... if the web server knows the route information, it can interpolate that into the response as a global variable or whatever, and then none of the changes I suggest in sveltejs/rfcs#52 (threading that info through into a singleton, messing around with page store, etc) would even be necessary.

@johnnysprinkles
Copy link
Contributor Author

Also just wanted to restate my argument about static SSR since I know you and Rich agree on a different opinion... my view is that static SSR (or SSG if you like) is a really awesome development, and largely obviates dynamic SSR. It's in line with Svelte philosophy of "do everything you can at compile time", it allows the flexibility to use any server runtime, and should be less resource intensive for high traffic on a given machine. I think we should be using it for everything!

And, there's really no need to be hung up on this idea that parameters from the page store need to match at build time and client runtime. Clearly, page.host is a counter example of that. At build time, host would be "localhost" but at runtime of course you'd want the real "in situ" host. This does mean you could be dumb and check it in load and do something with it, then have a mismatch between JS enabled/disabled, first load and client-side transition, etc.

export async function load({ page }) {
  return {
    props: {
      message: `Hello, welcome to the website at ${page.host}`
    }
  }
}

In this case, you know the "page.host" only makes sense at runtime, so you'd want to have any logic referencing only in client-side code, i.e. onMount.

My argument is the exact same holds for parameterized path params, and for query strings for that matter.

@johnnysprinkles
Copy link
Contributor Author

And it is looking like I'll need to maintain a fork of SvelteKit, which I hate to have to do, but if I do I'll document the motivation clearly and it won't be a continuously diverging fork, just "SvelteKit + like 4 commits".

@johnnysprinkles
Copy link
Contributor Author

johnnysprinkles commented Jul 5, 2021

And also, of course I'd like to get your opinion to see where you're coming from Ben. What web architectures excite and interest you? Do you think React's current direction of streaming SSR can give you all the benefits of static SSR (instant page load, at least for the shell of the page) and dynamic SSR (client never has to build up its own DOM for the complete initial render)? It almost reminds me of when @Rich-Harris mentioned Phoenix Live View at Svelte Summit, but just all on the same initial HTTP connection.

@johnnysprinkles
Copy link
Contributor Author

So this might not actually be strictly necessary... if you use a wildcard convention for path params which include the param's name, while prerendering, I think you could just descend the filesystem tree much like simple static server would do, and for any path part that's not found, look for a sibling directory using said convention.

I still think it's a good idea to have the routes available in a JSON file, but I can't really argue that not having them is blocking anything.

@johnnysprinkles
Copy link
Contributor Author

Yeah, there are more important and necessary things to think about here, I think this PR is a distraction, let me close it and there will be a couple PRs coming.

@benmccann
Copy link
Member

I'm afraid I can barely keep up with all the activity on this repo. It'd help if you could organize your thoughts concisely and have a specific ask if any. There's quite a few messages here since I last took a look, so I'm not sure what to respond to if anything

@johnnysprinkles
Copy link
Contributor Author

Totally agree, I've littered the repo with lots of comments and issues. Let's consider this PR closed. I might think about resolving all my open issues and creating a new one that's more concise, which would basically say this:

"If you use static pre-rendering, the parts of the page that depend on dynamic query params or path params will of course have to be client-rendered. But SvelteKit can't support this very well as-is. Here's how we support that better."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants