GithubHelp home page GithubHelp logo

howesteve / elegua Goto Github PK

View Code? Open in Web Editor NEW
67.0 67.0 4.0 312 KB

Elegua - a small, reactive PWA router for Svelte

Home Page: https://elegua.netlify.app/

License: Apache License 2.0

JavaScript 27.23% Svelte 47.43% HTML 0.95% TypeScript 24.39%

elegua's People

Contributors

howesteve avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

elegua's Issues

View transition support

Thanks for amazing project. I also hate file based routing and I really like elegua router. Is there any plan to add support for view transitions?

Update/Set multiple searchParams at once

Hi,

I am currently migrating an old web app to Svelte and came across this nice and easy routing library.
Thanks to the inclusion of searchParams this is very much the thing I was looking for without any additional fuzz.

My application makes some use of date-ranges and, due to some backward compatibility I need to have at the moment, these are handled via two URL query parameters (start and end).
When utilizing $searchParams and setting one after the other I basically get the "forward" movement I want: page is updating based on both new values. Though, internally, it is pushing two states.
This becomes apparent when going back via browser history: I basically get two steps: one for changing parameter 1, one for changing parameter 2.

I found a workaround using "goto":

      const u = new URL(window.location.href);
      u.searchParams.set('start', formatDate(newStart));
      u.searchParams.set('end', formatDate(newEnd));
      goto(u);

This provides the behavior I intend.

I was wondering if this is an edge case with my application and I should leave it as such or if there is another way (e.g. adding a custom $searchParams setter) to improve elegua here?

If my explanations were unclear let me know and I will try to improve.

Best regards,
Sven

Persisting/restoring data between navigation

Right now this SPA router components lose their state when going backwards in history which makes it behave differently than most browsers, where going backwards shows page's last state, eg. with filled form fields, different opened tabs, changed element positions or states, the page scroll position, etc (theres a lot to consider!)

Currently we have to implement this logic ourself - creating history store, with derived stores per page/component/path, track path/url changes, then manage the page state/history by cloning, pushing and restoring the states from this history store.

It would be nice if this library provided it's own build store/logic that does that that we can use.

Component loading after a resolve call, before the params store is set

Hi! Firstly, thanks for all the work put into writing this package! I think it is really neat.

I don't really know if this is a bug or if it is intended behaviour, but I was following the examples and run into the following issue (very simplified, for clarity):

App.svelte

<script>
  import {path, resolve, params} from 'elegua';
  import Foo from './Foo.svelte';

  async function getUser() {
    console.log("Here I get the currently logged in user from the backend and save it in a store")
    return null
  }
</script>

<main>
  {#await getUser()}
    Loading...
  {:then _}
    {#if resolve($path, 'foo/:slug')}
      <Foo slug={$params['slug']} />
    {:else}
      404
    {/if}
  {/await}
</main>

Foo.svelte

<script>
  export let slug;
  
  async function queryBackend() {
    console.log(`Here we query the backend with slug ${slug}`)
  }
</script>

{#await queryBackend()}
  Loading...
{:then _}
  <h1>Foo component</h1>
{/await}

The issue I have is that the backend call from the Foo component is executed before the $params store is set. I.e., the queryBackend function is printing "Here we query the backend with slug undefined".

This can be fixed in two ways, firstly by changing slug in the Foo component for $params['slug'], or by doing an await tick() at the beginning of queryBackend.

So the question is: Is this intended behaviour? (in which case, it would be nice to document that it can happen). If not, is there any way to guarantee that the params store is set before resolve returns?

Resolve always matches beyond the specified string when using named params

For example, in the demo page:

{#if resolve($path, '/blog/:post')}
  <Post id={$params['post']}

the resolve call will return true for urls such as https://elegua.netlify.app/blog/fake-post-0/abc (see here or here)

If I'm not mistaken, can be fixed by adding a $ at the end of namedPath:

export function namedPath(route: string): RegExp {
  // checking for named component paths
  return RegExp(
    route.split('/').map((x) =>
        x.startsWith(':') ? `(?<${regExpEscape(x.slice(1, x.length))}>[a-zA-Z0-9][a-zA-Z0-9\_\-]*)` : regExpEscape(x)
      ).join(`\\/`) + '$'
  );
}

Named parameter doesn't match route when it begins with a number

Thanks for sharing this library, I appreciate its simple approach to routing!

It seems like string parameter matching using resolve() will only match a route if the URL path segment begins with letter. For example, if I have the simple routing below:

{#if resolve($path, '/blogs/:id/:slug')}
  <p>Blog ID: {$params['id']}</p>
{:else}
  <p>Oops...</p>
{/if}

This routing will not match in all the scenarios I would expect:

  • /blogs/xy/new-post ✔️
  • /blogs/x1/new-post ✔️
  • /blogs/1x/new-post
  • /blogs/11/new-post

This seems to be because string routing builds a RegExp for string parameters similar to ([a-zA-Z][a-zA-Z0-9\_\-]*). This pattern only matches if the first character is in [a-zA-Z]. Here's a test link for the regex produced by this example for reference: https://regex101.com/r/0ABtfm/1

I can work around this by using a manual regex test instead, like resolve($path, /\/blogs\/(?<id>\w+)\//)

Unable to resolve page through dynamic()

Hello! I'm building out a POC with Elegua and Vite + Svelte, but I ran into an issue with dynamic routing. Whenever I use a named params route in the list of routes for the dynamic() method, Vite HMR freezes up and fails to render anything.

I'm unsure if I set up my routes wrong, but here's the gist of how it looks like on my end:

in App.svelte:

<svelte:component this={dynamic($path, [
  ["/", Home],
  ["/login", Login],
  ["/register", Register],
  ["/chara", Chara],
  ["/chara/new", CharaNew],
  ["/chara/:id", CharaSingle, { id: $params["id"] }]
], Error)} />

in CharaSingle.svelte:

<script lang="ts">
  import { params } from "elegua";
  export let id = "";
</script>

<h1>This is Id: {id}</h1>
<p>this is params: {JSON.stringify($params)}</p>

But if I place the CharaSingle component inside an if block, it renders with no issues:

{#if resolve($path, "/chara/:id")}
  <CharaSingle id={$params["id"]} />
{/if}

I set up a stackblitz project to showcase the issue here: https://stackblitz.com/edit/vitejs-vite-ur49yb?file=src%2FApp.svelte

Is there something I'm missing? Please let me know.

Support for lazy component imports

dynamic() is really nice to make our code cleaner.

Yet it could be even better.

Right now every component inside dynamic loads at the same time when user visits the page. It would be nice to have them load on-demand, with lazy imports. The reason behind this feature request is that once your application grows and we have dozens of routes/pages, the browser then "downloads" all components at once and the initial page load can be longer, especially on mobile networks.

The lazy import should look like this (keep in mind the svelte:component needs to change too to something like this):

<svelte:component this={dynamic($path, [
  ['/', () => import('./Home.svelte')],
  ['/about',  () => import('./About.svelte')],
  ['/blog',  () => import('./Blog.svelte')],
  ['/blog/:post',  () => import('./Post.svelte'), {id: $params['post']}],
],  () => import('./Error.svelte'))} />

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.