Why not export default? – Telegram
Channel created
Почему не стоит использовать export default в своей кодовой базе?
- export default позволяет экспортировать анонимные функции:

Если где-либо будет выброшена ошибка, в ее stack trace все анонимные функции, через которые она прошла, будут помечены записью at <anonymous>, что усложнит поиск места возникновения данной ошибки.

В React, если таким способом экспортировать компонент, он не получит имени в дереве компонентов в React DevTools, следовательно будет сложнее увидеть полную картину и понять, с каким компонентом мы имеем дело.

Также, такое содержимое мы не сможем найти через поиск по коду в IDE, так как оно попросту не присвоено ни в какую переменную (на уровне исходного кода), а следовательно не имеет имени.

Обычно авто-импорты в редакторах/IDE предлагают импортировать такие функции по имени файла.
Например, для импорта значения дефолтного экспорта из файла some-thing.ts будет предложено имя someThing для функции и SomeThing для класса.
Тем не менее, при переименовании такого файла, имя у существующих импортов заменено не будет, при этом для следующих импортов будет предложено уже новое имя в соответствии с новым именем файла.

Таким незаметным образом в коде могут появиться импорты одного и того же значения под разными именами, и возникнет ситуация, описанная в следующем пункте.

- Импорт такого значения беспрепятственно позволяет указать ему любое имя:

/* component.js */
const Component = () => { ... }
export default Component

/* other-file.js */
import MyComponent from 'component.js'
import OtherComponent from 'component.js' // или так?
import Something from 'component.js' // а может даже так?


Это усиливает влияние человеческого фактора на код, особенно когда у кого-нибудь из разработчиков по какой-то причине нет авто-импорта в редакторе/IDE.
Кто-угодно сможет легко импортировать содержимое под другим именем, что сильно усложнит поиск мест, в которых это содержимое используется.

При использовании именованного экспорта, в любом случае придется указать изначальное имя переменной.
Даже если надо импортировать ее под другим именем:

import { Component as Something } from 'component.js'

Именованные экспорты упрощают поиск по проекту и рефакторинг.

- С дефолтными экспортами проблематично делать реэкспорт, например в UI слое:

/* ui/button.js */
export default Button() {}

/* ui/link.js */
export default Link() {}

/* ui/index.js */
export * from './button'
export * from './link'
// -> Error: multiple default exports


Это усложняет код и добавляет нежелаемый бойлерплейт.

- Код становится менее консистентным:

Код с двумя видами экспортов менее единообразен и сложен в понимании. К тому же, дефолтные экспорты часто требуют иного подхода, например, при реэкспортах.

При использовании именованных экспортов все кейсы решаются одинаково просто.
👍231👎1
Исключения:

- Экспорт основного содержимого библиотеки.
(например, чтобы можно было сделать так: import React from 'react')
Тем не менее, обычно это все еще нежелательно.

- Некоторые модули, которые в соответствии с архитектурой фреймворка должны быть экспортированы по умолчанию.
(например, компоненты страниц в Next.js)

- Различные конфиги и все остальное, чьими потребителями является программный код, а не разработчики.
Это позволяет упростить код внутри библиотеки - она может просто сделать require файла и получить необходимый объект, без обращения к полю.
Дополнительная информация:

- Google в своем стайлгайде предлагает использовать именованные экспорты:
https://google.github.io/styleguide/jsguide.html#es-module-exports

- В Gitlab перешли на именованные экспорты:
https://gitlab.com/gitlab-org/frontend/rfcs/issues/20
Была ли эта информация полезна?
👍1👎1
Лайфхак для использования React.lazy с именованными экспортами


export const namedLazy = <T extends Record<string, any>>(
loader: () => Promise<T>,
name: keyof T,
) =>
React.lazy(async () => {
const module = await loader()
return { default: module[name] }
})




Использование:

const Component = namedLazy(() => import('./component'), 'ComponentName')


Кстати, WebStorm при рефакторинге с переименованием даже подтягивает новое имя компонента во второй аргумент =)
🔥31👍5👎1