Skip to content
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

Run code on the client regardless of whether layout is reset #2169

Closed
jsprog opened this issue Aug 11, 2021 · 8 comments
Closed

Run code on the client regardless of whether layout is reset #2169

jsprog opened this issue Aug 11, 2021 · 8 comments
Labels
feature request New feature or request
Milestone

Comments

@jsprog
Copy link

jsprog commented Aug 11, 2021

Describe the problem

@anudeepreddy already opened a pull request #2160 to solve the problems mentioned in #2154 and #1356, and not sure if it'll really solve the other problem mentioned in #2130.

But According to @Rich-Harris comments from #1356, by importing src/routes/__layout.svelte with other _layout.reset.svelte files, we avoid the extra dynamic import for the error page that may fail if imported at demand.

I really like the idea of having an app level layout file, as it open other possibilities including app level imports and gaining access to $app/stores without having to duplicate code in every __layout.reset.svelte.

Unfortunately, the current approach isn't playing well with code splitting, and I'm starting to worry about bloating other minimal pages with unnecessary components and other modules (e.g: login page).

Describe the proposed solution

I recommend that src/routes/__layout.svelte will get splitted into two other files:

  1. The first one would be the app layout, and always imported. It should cover error pages, and other app level imports, and from there, the programmer could gain access to $app/stores and other objects.
  2. The second one is optional and specific to the root path.

In case if anyone objected about the additional nesting level of layout:

  • the second file could be optional and not mandatory
  • we still could have a root level layout attached to body
  • I'm not sure if <svelte:fragment> will play an important role with this, but I'll try to think about it later.

Alternatives considered

I'm listing some possibilities for naming conventions. These are not decisive, and others may come up with better alternatives:

  • __layout.svelte and __layout.main.svelte
  • __root.svelte and __layout.svelte

Importance

nice to have

Additional Information

No response

@benmccann
Copy link
Member

benmccann commented Aug 13, 2021

This sounds very similar to #1530

@benmccann benmccann changed the title Split "src/routes/__layout.svelte" into two other files Ability to run some piece of code on the client regardless of whether layout is reset Aug 13, 2021
@benmccann benmccann changed the title Ability to run some piece of code on the client regardless of whether layout is reset Run code on the client regardless of whether layout is reset Aug 13, 2021
@benmccann benmccann added the feature request New feature or request label Aug 13, 2021
@benmccann benmccann added this to the 1.0 milestone Aug 13, 2021
@Conduitry Conduitry mentioned this issue Sep 1, 2021
@frederikhors
Copy link
Contributor

This is EXTREMELY IMPORTANT.

@frederikhors
Copy link
Contributor

Let's say I'm using @urql/svelte and its initClient().

If I use that method both in

  1. src/routes/__layout.svelte and in
  2. src/routes/login/__layout.reset.svelte

it initializes my urql client two times!

Is there a workaround today?

I'm using it like this because in src/routes/__layout.svelte I redirect the user to /login if is not authenticated.

@DhyeyMoliya
Copy link

DhyeyMoliya commented Oct 24, 2021

I was facing this double initialization issue in CSS, where my __layout.svelte css was messing up with __layout.reset.svelte in #1356 and #1100.

I have a workaround to use css by a
<link> tag inside <svelte:head>
But still, it is not technically perfect. I am still facing issues in creating apps with different styling in sub routes.

@jchanes04
Copy link

There does currently seem to be a conflation between different uses of __layout.svelte in the root path location. Here's the ones I can see mentioned here:

  • Layout which should apply to all paths under the root path (which is essentially all paths, because that's how paths work).
  • Layout which should apply to ONLY the root path. Currently only possible by putting a layout.reset.svelte on all other paths, which is obviously messy.
  • Layout which should be applied regardless of other resets later in the path.
  • "Layout" which just executes setup scripts for the client side.

Option 4 should not be a layout at all, as it's not "laying anything out" on the client side. There are already proposals for this, namely #1538 and #1530. These will run any client side initialization code you specify without having to include it in an otherwise useless layout file.

The other three are more debatable. Currently, options 1 and 2 are the same and option 3 does not exist. My idea would be to make option 1 into __layout.svelte, option 2 into __layout.root.svelte, and option 3 into __layout.global.svelte. This would greatly increase the flexibility of layout files and remove the need for a lot of strange workarounds.

@rmunn
Copy link
Contributor

rmunn commented Dec 2, 2021

One possible workaround could be the technique I mention in this proposed FAQ entry:

import { initClient } from 'some-library';

const noop = () => {};
let storedClient = null;
export const client = readable(null, (set) => {
  if (!storedClient) {
    storedClient = initClient('whatever params you need');
  }
  set(storedClient);
  return noop;
});

Then in the rest of your code, just import the client store and use it as $client.get('some-query'). You're guaranteed that the initClient function will be called exactly once (or zero times if it's never actually needed). Note that if the user refreshes the page, then initClient will be called again, but that's almost always what you'd want.

@AlexRMU
Copy link

AlexRMU commented Dec 18, 2021

@rmunn, and how is store better than a simple variable?

//db.js
import { initClient } from 'some-library';

let db;
export function GetDB() {
    if (!db) {
        db = new initClient("...");
    }
    return db;
}
//api endpoint or else
import { GetDB } from "$lib/db";
const client = GetDB();

export async function get(req) {

    let result = await client.func();

};

@mrkishi
Copy link
Member

mrkishi commented Apr 5, 2022

This is now possible with (rather advanced, don't freak out) usage of named layouts:

/src/routes/
  /__layout-app.svelte             # your app-wide layout
  /__layout@app.svelte             # your default layout, goes inside app-wide layout `/__layout-app.svelte`
  /__layout-reset@app.svelte       # an empty <slot/> layout, goes inside app-wide layout `/__layout-app.svelte`
  /some/regular/page.svelte        # goes inside layout `/__layout@app.svelte`
  /some/random/page@reset.svelte   # goes inside reset layout `/__layout-reset@app.svelte`

You can have app, root, path and reset-specific code in named layouts that you can structure freely.

@mrkishi mrkishi closed this as completed Apr 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request
Projects
None yet
Development

No branches or pull requests

8 participants