sveltejs / sapper

The next small thing in web development, powered by Svelte
https://sapper.svelte.dev
MIT License
6.99k stars 432 forks source link

Decouple Routes from code to be executed! #1082

Closed acewf closed 4 years ago

acewf commented 4 years ago

Is your feature request related to a problem? Please describe. Svelte is dependent on browser routes to load and execute code. if you serve a page in other route context, you will get a broken page.

Made one example based on the template to demonstrate this! https://github.com/acewf/template/tree/master/src

it builds a dynamic route for 2 locales, and on each locale, there is a localised countdown. this project uses nginx as webserver, and if a route location isn't found it serves the english version of the countdown.

You can see from this example, the route http://localhost/invalid/countdown works, but route like http://localhost/invalid/countdown/route doesn't

or even worst in my opinion when you have the following route not working http://localhost/invalid/countdown/index.html

Describe the solution you'd like code execution needs to correlated without using browser routes! maybe the page represented by html or by the javascript could have a hash gives relation need to understand what scripts needs to be executed.

Describe alternatives you've considered Tested if could get any work arounds, but none seem to work.

How important is this feature to you? I think this feature is important for the entire community, and also help Svelte/Sapper getting a wider adoption.

vipero07 commented 4 years ago

To me, your example looks like it works as I would expect. Which is to say, you don't have any http://localhost/invalid/countdown/route route defined, so it shouldn't work, as it wouldn't know what to show. You would need a folder named route with its own index in the [slug]/countdown folder.

However if you want English as a fallback you should consider just redirecting the user to the English version. As a user experience, it would be awkward to see something like German in the URL and the entire page is in English. Alternatively, you could throw an error and say that language isn't supported and offer links to the supported languages.

acewf commented 4 years ago

@vipero07 not sure you understand the question or if explain myself wrongly! a framework shouldn't give architectural constrains. If a file like html can be served using a route alias, and it loads the required files, and present no errors. then it should work like route was build for.

Another example for this is, if you have some script running on example.com/ why wouldn't it run if your route is example.com/index.html

This is the constrain that sapper currently presents, at least from tests i have made!

antony commented 4 years ago

I too can't understand the issue here.

You appear to be using a slug to control which version of a page is served, which is fine, and works as you would expect.

You go on to say that the route http://localhost/invalid/countdown/route doesn't work, which isn't surprising, since there is no file called route.js or route.html nor a folder called route with a file called index.html inside it, in the countdown directory.

You then say that http://localhost/invalid/countdown/index.html doesn't work, which is again expected, since Sapper doesn't map .html extensions to routes. If you wanted this page to work, you should create a file called index.html.html or .index.html.js in the countdown directory.

In your followup you say that example.com/ would work, but example.com/index.html wouldn't. This is also correct for the reason I mentioned earlier.

Sapper uses filesystem based routing meaning that it builds routes dynamically based on the files that exist within your routes directory. This is clearly documented, and works predictably.

If you want to do mapping/catchalls/routing/redirects, you can do so via a number of methods:

  1. using a webserver like nginx as you mentioned
  2. Adding middleware to polka to handle routing before Sapper handles it
  3. Using a routing function from your hosting (such as routes on Zeit's now)
  4. Adding a someroute.js file in the location which uses req to redirect to your desired page.

I'm closing this for now, but feel free to provide further clarity if I've misunderstood your issue.

acewf commented 4 years ago

Hi @antony thanks for taking a look into this.

not sure you had the chance of running the provided example. also not sure how wrongly i explained the issue, but i will try to break it down in a few other examples, so the issue is more clear.

Firstly i would like to say sapper is a framework, and the usage i do with sapper is building static pages, these static pages are building according the structure you give on routes.

If i have a simple webserver (apache/nginx/express) serving a simple static html that loads a script, on the following folder structure for example:

while browsing this, wouldn't matter if the user goes to example.com or to example.com/index.html, the file some-script.js would be loaded and execute is functionality.

sapper is enforcing a decision that this code only run when the url example.com, what it shoudn't because even with example.com/index.html all the scripts are being loaded.

Another example without using sapper would be, if i copied that index.html to the folder homepage, keep in mind it will still load correctly all the scripts, to a structure like this:

browsing to example.com or example.com/homepage/ would get the script functionality.

But trying to achieve this with sapper, wouldn't be possible unless i create files for routes/homepage

I would like to keep this issue OPEN, although seems not easy thing to be fixed, i think is important.

antony commented 4 years ago

not sure you had the chance of running the provided example.

I did, yeah

while browsing this, wouldn't matter if the user goes to example.com or to example.com/index.html, the file some-script.js would be loaded and execute is functionality.

In Sapper, the route example.com/index.html would have to be explicitly created as index.html.js or .index.html.svelte or index.html.html. Sapper doesn't map .html extensions to routes, and there is no plan to do so, as it isn't relevant for 99% of cases.

sapper is enforcing a decision that this code only run when the url example.com, what it shoudn't because even with example.com/index.html all the scripts are being loaded.

That doesn't make any sense, sorry.

But trying to achieve this with sapper, wouldn't be possible unless i create files for routes/homepage

Correct, because Sapper isn't mapping .html files to routes. There is no rule for websites that pages must end in .html or any extension at all, this seems to be specific to your use case. For this reason, you can simply add redirects using server-side routes, middleware, or some other mechanism.

This issue might be important for your specific use-case, and therefore the onus is upon you to work out a way to create these html mappings (I'd recommend doing so in nginx).

acewf commented 4 years ago

@antony is exactly what isn't working on sapper, even if you map a file on nginx to other route, the script although is loaded, it doesn't run the functionality, because the route isn't the expected

antony commented 4 years ago

@acewf I see, so you're mapping the route in nginx and then passing what from nginx to Sapper?

Sapper needs the request from nginx to have the path it expects, not the path the user is visiting. Something like:

location ^/(.*)\.html$) {
    rewrite ^/(.*)\.html$ $1;
}

I forget the exact syntax, but essentially tell nginx to strip the .html extension off and make the request to Sapper.

This has nothing to do with Sapper, though.

acewf commented 4 years ago

How doesn't make anysense?

sapper is enforcing a decision that this code only run when the url example.com, what it shoudn't because even with example.com/index.html all the scripts are being loaded.

That doesn't make any sense, sorry.

sapper should help us to make static files, and when this files are loaded, if they load every dependency without errors, should deliver the functionality that are build for.

The issue i am raising isn't related to nginx, it could provide other webservers.

antony commented 4 years ago

@acewf going to a route that doesn't exist, won't work, it's as simple as that. Going back to your original example, and running it, the following works:

http://localhost:3001/invalid/countdown http://localhost:3001/en/countdown http://localhost:3001/pt/countdown

because they all map to routes defined in your app

The following don't work:

http://localhost:3001/invalid/countdown/route // because route.html or route/index.html doesn't exist in your app. http://localhost/invalid/countdown/index.html // because index.html.html or index.html.js doesn't exist in your app.

There is nothing mysterious or unpredictable about that, and:

if they load every dependency without errors

These routes don't load every dependency without error, they don't load at all, because they don't exist

You can inspect the list of routes inside the generated src/node_modules/@sapper directory and see what is mapped.

Sapper's job is to serve html, among other things, but this has nothing to do with serving routes with the extension .html, or any other extension for that matter.

acewf commented 4 years ago

@antony so according to you comment

@acewf going to a route that doesn't exist, won't work, it's as simple as that.

How would you achieve something like at you can see on this examples: https://outriders.square-enix-games.com/fr/blah https://outriders.square-enix-games.com/fr/blah/asdas https://outriders.square-enix-games.com/en-us/blah

This routes don't exist, but they still pages functionality isn't lost!

antony commented 4 years ago

You can consult this issue to learn about wildcard routes:

https://github.com/sveltejs/sapper/issues/1092#issuecomment-588437441

acewf commented 4 years ago

@antony i will give this a try.

Either way, think sapper should adopt a system based a unique ID to trigger the load and execution of scripts, instead depending on the route.

Thanks for your input.

antony commented 4 years ago

I have no idea what that means. You'll have to comprehensively document exactly what sort of system that is and how it would work.

Sapper uses filesystem based routing, and urls from the browser to determine what to load, and that's unlikely to change.

On Wed, 19 Feb 2020 at 21:19, Ace notifications@github.com wrote:

@antony https://github.com/antony i will give this a try.

Either way, think sapper should adopt a system based a unique ID to trigger the load and execution of scripts, instead depending on the route.

Thanks for your input.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sveltejs/sapper/issues/1082?email_source=notifications&email_token=AABVORO3METL3G4JJ7S5EOLRDWO7TA5CNFSM4KO3O6K2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEMJW5XA#issuecomment-588476124, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABVOROT7TY66PLKYQUL3XDRDWO7TANCNFSM4KO3O6KQ .

--


ꜽ . antony jones . http://www.enzy.org

thgh commented 4 years ago

Just wanted to chime in and say that I needed this feature too.

Example 1: I want to POST to /render and show the result.

Example 2: I don't want to the frontend to be aware of admin pages. (or any page that should only be server generated)

Example 3: I want to add extra scripts, stylesheets, secrets, data to a specific page. (think of IE11 support)

Example 4: I want a multilingual site that supports both /about and /en/about. The problem is that /[lang]/index.svelte is ambiguous, params.lang could be a language or a slug.

The last example is probably possible by overwriting req.url now that I see it like that. I imagine an API for the others like this:

// src/routes/render.js
import { render } from '@sapper/server'
import Result from './Result.svelte'

export async function post (req, res) {
  res.end(await render(Result, req))
}
antony commented 4 years ago

@thgh can you figure out if you can cover any of your cases with wildcard routes, documented above, and if there are things you aren't able to do, then raise an appropriate issue(s)?

Unless I'm missing something, I think:

1) You can POST to a server route render.js and add stuff to the request - I use this for search 2) You can create server routes admin.js, or define polka routes 3) You can add an alias/flag when legacy is passed in rollup,js and use it to include/exclude scripts, as well as a bunch of other stuff - or, a server route which the frontend requests which either does or doesn't return your scripts 4) I feel like wildcard routes could solve this

iceye commented 3 years ago

How is it possible to manage rewrites with this i.e. many urls for the same file (file name has a limit and the only option is to have multiple file with the same content)? Sorry but this is a crazy choice, why not just remove that check?