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

Import groups / namespaces #317

Open
1 task
brawaru opened this issue Jan 15, 2024 · 1 comment
Open
1 task

Import groups / namespaces #317

brawaru opened this issue Jan 15, 2024 · 1 comment

Comments

@brawaru
Copy link

brawaru commented Jan 15, 2024

Describe the feature

Automatic imports are nice, but sometimes you don't want to clutter your virtual global scope with a lot of different things that share something in common. It would be great if Unimport could help you in situations like this.

Imagine a situation where you have a folder messages where each file would contain its own localisable message declarations exported as defaults:

// messages/page-titles.ts
export default defineMessages({
  projects: {
    id: 'page.projects.title',
    defaultMessage: 'Projects',
  },
})
// messages/errors.ts
export default defineMessages({
  notFound: {
    id: 'error.not-found',
    defaultMessage: 'Resource not found',
  },
})
// messages/utils.ts
export function getWorldGreeting() {
  return defineMessage({
    id: 'greetings.world',
    defaultMessage: 'Hello, world!',
  })
}

You don't really want to import each file separately, since pageTitles and errors are quite confusing. Nor do you want to rely on some naming conventions (like having files named like errors-messages to keep it clean.

In this case you'd likely prefer to have a globalMessages namespace, that would've contained all the imports than Unimport discovered, like pageTitles, errors, and anything else. It would also tree-shaking, as if you've done a specific import rather than imported everything at once.

To do so manually without Unimport right now you can make a barrel file:

// messages/index.barrel.ts
import pageTitles from "./page-titles.ts"
import errors from "./errors.ts"
export * from "./utils.ts"
export { pageTitles, errors }

And then the file that would export that barrel:

// messages/index.ts
export * as globalMessages from "./index.barrel.ts";

Now you can import { globalMessages } from '~/messages'. You can also add this to your Unimport.

But what if Unimport could group imports like this automatically for you?

You'd add a scan option:

unimport.vite({
  dirs: [
    './utils/*',
    { from: './messages/*', as: 'globalMessages' },
  ],
})

… and then would be able to use that through ‘variable’:

// input: pages/projects/index.vue/<script setup>
console.log(formatMessage(globalMessages.pageTitles.projects))
declare global {
  const globalMessages: Readonly<{
    pageTitles: typeof import('../../messages/page-titles.ts')['default']
    errors: typeof import('../../messages/errors.ts')['default']
    getWorldGreeting: typeof('../../messages/utils.ts')['getWorldGreeting']
  }>
}

… which would expand to something along the lines of:

// output: pages/projects/index.vue/<script setup>
import pageTitles from '../../messages/page-titles.ts'
console.log(formatMessage(pageTitles.projects))

It may also work with other language features like destructuring, as long as it's deterministic (did you know that something like this would blow up tree-shaking in rollup?):

// src/a.js
const { pageTitles: { projects: projectsTitle } } = globalMessages
// src/a.js [transformed]
import pageTitles from '../../messages/page-titles.ts'
const { projects: projectsTitle } = pageTitles

Additional information

  • Would you be willing to help implement this feature?
@varHarrie
Copy link

varHarrie commented Feb 21, 2024

When the number is large enough, all variables are exposed globally, which will indeed cause certain pollution to eslintrc globals and types, and can easily cause conflicts.

Hope there was a way to do something similar:

const code = `
$.foo();
$.bar();
`

const { injectImports } = createUnimport({
  imports: [
    { name: 'foo', from: 'my-lib', as: '$.foo' },
    { name: 'bar', from: 'my-lib', as: '$.bar' },
  ]
})

const { code } = await injectImports(code)

Output:

import { foo as $__foo, bar as $__bar } from 'my-lib';

const $ = { foo: $__foo, bar: $__bar };

$.foo();
$.bar();

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

2 participants