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

Private Components #9297

Closed
olafurw opened this issue Oct 6, 2023 · 4 comments
Closed

Private Components #9297

olafurw opened this issue Oct 6, 2023 · 4 comments

Comments

@olafurw
Copy link

olafurw commented Oct 6, 2023

Describe the problem

Components in Svelte are relatively straight forward, which is nice. There's a file, in the file is the component and everything you need to render it.

But as I've been working with a larger and larger application written in Svelte another concept keeps cropping up. Private components.

Most components are designed in a way where they can be used anywhere, Buttons for example. But often a component is designed to be used inside/with another component, a ListItem component inside a List component or a PageTitle component next to a PageBody component.

Importing a ListItem component by itself works but most of the time doesn't make sense and avoiding that problem would be nice.

Describe the proposed solution

The other issue tickets I've seen are about inheritance or supporting multiple components in one file. But I feel there is a simpler way if you just want private components.

Usually how projects structure components that are connected is to create a folder that would then contain all of them. By leveraging that idea we could try a couple of ways:

  • ListItem.private.svelte can only be imported by files in the same folder.
  • Any component inside of a folder called +private can only be imported by components that are siblings of the +private folder.

FYI. These are just suggested solutions, all names are subject to bikeshedding.

This would then leverage the same or similar methods that check for server files imports in client only files. This should also not impact existing code.

Alternatives considered

There are two other discussion threads I have found.

Multiple components in one file #2940
Component inheritance #192

Also saw this video recently and it looked promising initially but even though you've created a more visual hierarchy, the child components can still be imported in other places.

Importance

would make my life easier

@Prinzhorn
Copy link
Contributor

Prinzhorn commented Oct 6, 2023

There's a dedicated place and process for RFCs here: https://github.com/sveltejs/rfcs

What you describe sounds like something you should be able to setup (maybe via a plugin) in a bundler, as it doesn't sound Svelte specific at all.

Edit: Also if you internally introduce a naming convention of a +private folder then that should keep people on your team from importing random components from other parts of the project, no? Without actually preventing this on a bundler level.

@olafurw olafurw changed the title RFC: Private Components Private Components Oct 6, 2023
@olafurw
Copy link
Author

olafurw commented Oct 6, 2023

Renamed the issue since it's not a formal RFC.

If this could be setup as a Rollup plugin then that would be nice, sure. Regarding the naming convention, not sure there, since I'm more worried about accidental imports and if some sort of automated check can remove a thing I have to worry about then that's a win in my book.

@Jak-Ch-ll
Copy link

I recommend to handle your specific use-case with the no-restricted-imports ESLint rule. Something along these lines should work:

    'no-restricted-imports': [
      'error',
      {
        patterns: [
          {
            // only allow imports from +private folder on same level
            group: ['**/+private/*', '!./+private/*'],
            message: "Don't import private modules.",
          },
        ],
      },
    ],

This **/+private/* pattern makes it so, ESLint will throw an error when any import statement includes the +private folder. The !./+private/* specifically allows the import if it comes from the same level. The neat advantage is, that this works for any file, not just Svelte.

I see two problems with having some kind of implementation of private components in Svelte. First of all, Svelte (in contrast to SvelteKit) does not make any assumptions about a projects file structure. Even SvelteKit does only do that for routes. The second point is that privacy on the file level is not a concept in JavaScript. Inside a file everything is private unless exported, but once a file is exporting something it can be imported from anywhere. So as long as Svelte sticks to a single component per file, I don't see think private components will be a thing.

In the end they are also not strictly necessary. When writing a library you would only re-export the public components anyway. And when writing an application you can use a linter, as I described above.

@Rich-Harris
Copy link
Member

As others have noted, this is outside Svelte's remit

@Rich-Harris Rich-Harris closed this as not planned Won't fix, can't repro, duplicate, stale Apr 3, 2024
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

No branches or pull requests

4 participants