Closed pReya closed 8 months ago
I think the way to go here might be to support import * as Components from '@components'
syntax, so you could then use <Components.ComponentA />
etc. A bit more verbose but you could choose a short name like import * as UI ...
and use <UI.ComponentA />
etc. I guess.
@delucis Have you given this any more thought? It would be nice to have a way to import namespaces. The syntax could look something like:
AutoImport({
imports: [
{
// generates:
// import * as Components from '@components/index.js';
'@components/index.js': [['*', 'Components']],
},
],
}),
The current workaround is to use a default export instead of a named export.
- export {
+ export default {
ComponentA,
ComponentB
}
or use another file that re-exports the namespace object as a default export.
import * as Components from '@components/index.js';
export default Components;
The downside still is that the exports need to be done manually, i.e., the "barrel" file still needs to exist. It's verbose and can slow things down. But the solution to that is already tracked by a separate issue (#20).
Haven't had time to consider it much, but I like your syntax I think! I guess it's a little bit magic, but no more than the rest of the API design really.
Are you interested in implementing this?
The current workaround is to use a default export instead of a named export.
- export { + export default { ComponentA, ComponentB }
Thanks for the suggestion. How would you then load this file with astro-auto-import
?
Thanks for the suggestion. How would you then load this file with
astro-auto-import
?
The usual way you’d do a default import:
AutoImport({
imports: [
{
// generates:
// import { default as Components } from '@components/index.js';
'@components/index.js': [['default', 'Components']],
},
],
}),
Then you can use them like:
<Components.ComponentA />
<Components.ComponentB />
Are you interested in implementing this?
Maybe! I was looking through the source code and couldn't quite understand how it works 😅
The usual way you’d do a default import:
AutoImport({ imports: [ { // generates: // import { default as Components } from '@components/index.js'; '@components/index.js': [['default', 'Components']], }, ], }),
Then you can use them like:
<Components.ComponentA /> <Components.ComponentB />
Actually, it looks like this approach breaks hydration. Not sure if it's a bug in astro or astro-auto-import. See repro
It’s actually stupider than it looks 😅
I think we’d need to change this function:
Right now that collects a bunch of x as y
into an array, e.g. ['default as A', 'named as B']
then at the end wraps those in curly braces: { default as A, named as B }
. Later that gets mixed into a line like import INSERT_HERE from 'module'
.
So if we’re lucky, we can just special case '*'
so it doesn’t end up in the curlies. One thing we might need to double check: can you combine namespace imports with named imports? i.e. is the following code valid:
import * as Namespace, { something } from 'module';
or would it have to be?
import * as Namespace from 'module';
import { something } from 'module';
Actually, it looks like this approach breaks hydration. Not sure if it's a bug in astro or astro-auto-import. See repro
Looks like an Astro bug. Even importing the barrel file directly breaks hydration:
import Barrel from '../components';
import Counter from '../components/Counter.tsx';
# Hello
<Barrel.Counter client:load />
<Counter client:load />
is the following code valid:
import * as Namespace, { something } from 'module';
or would it have to be?
import * as Namespace from 'module'; import { something } from 'module';
i think it needs to be the latter. in which case, maybe the below syntax would make more sense? this will prevent invalid imports.
AutoImport({
imports: [
{
// generates:
// import * as Namespace from 'module';
'module': 'Namespace',
},
],
}),
Looks like an Astro bug. Even importing the barrel file directly breaks hydration:
@delucis @mayank99 As far as I can see, withastro/astro#32 still only allows to use the imported components via namespace, e.g. Barrel.ComponentA
, right? Any workaround to use it without the Barrel
prefix?
Any workaround to use it without the Barrel prefix?
No. This would require astro-auto-import
to know somehow what is exported from your index file and we can’t easily. To do that we’d need to read the index file, parse it with a JS AST tool, collect all the named exports and then use the result to build the import. It’s not impossible but it’s quite a lot more complex than the current implementation.
The prefix can be as short as you like, so if it’s just the authoring noise your concerned about, I’d recommend choosing something shorter like e.g. UI
so you can refer to UI.ComponentA
.
For now, if you need the unprefixed name, you’d need to use the named import approach and tell astro-auto-import
yourself all the exports you have.
Thanks for the detailed explanation!
In my project I have a single
index.ts
file that just imports all of my separate components and then re-exports them as named exports (barrel file).This way, I used to be able to use all my components through a single import statements (possibly with a TS alias), like this:
Now I want to use
astro-auto-import
, and I was wondering if there is any way to auto-import all the files that get exported from my index file, without repeating/duplicating all the module names, and without prefixing them with a namespace.I'd love to have a single source of truth for all the usable components, and I'd love it to be my index file rather than the Astro config.