- Точка входа для приложения
- Точка входа для библиотеки
- Точка входа библиотеки и приложения в одном проекте
- Итог
В разработке приложений есть такое понятие как точка входа. Понимание того, как правильно выделять точки входа, может значительно улучшить архитектуру вашего проекта и расширить его возможности.
Точка входа для приложения
Большинство приложений — это достаточно объемный проект, состоящий из множества модулей. Но когда запускается приложение, то запускается какой-то один конкретный файл, он и является точкой входа:
// file: src/my-application/index.js
export default () => console.log('Welcome to my application!')
// file: index.js
import app from './src/my-application/index.js'
app()
Выше пример небольшого проекта из двух файлов:
- src/my-application/index.js — определена и экспортирована функция, выводящая сообщение в консоль
- index.js — импортируется и вызывается функция
.
├── index.js
├── package.json
└── src
└── my-application
└── index.js
Модуль index.js в таком проекте является точкой входа. Если вызвать этот файл командой node index.js
из директории проекта, то начнется выполнение нашего приложения, произойдет вызов функции app()
, и мы увидим результат:
node index.js
Welcome to my application!
В проекте бывают несколько точек входа. Каждая может работать как отдельное приложение и при этом использовать общую логику.
Обычно в точке входа происходит вызов одной функции. Могут быть исключения, но всегда лучше стремиться к вызову одной единственной функции. Почему это так — об этом ниже.
Точка входа для библиотеки
Если в приложениях точкой входа является то место, где происходит вызов самого приложения в виде функции или какого-то кода, то для библиотек ситуация иная. В библиотеках мы не должны в обычной ситуации вызывать код. Библиотека предоставляет функцию или набор функций, а когда их вызывать решает тот, кто импортирует библиотеку в свой модуль.
Например, библиотека lodash
предоставляет различный набор вспомогательных функций. Мы можем импортировать любое количество функций из этой библиотеки, и сами решать какую когда использовать:
import { random } from 'lodash'
console.log(random(0, 5))
Когда мы указываем подобный импорт, мы не указываем конкретный файл, откуда нужно импортировать функцию, а только указываем название библиотеки. Но как тогда интерпретатор узнает где находится нужная нам функция? Это происходит благодаря тому, что в npm-пакете есть точка входа для этого самого пакета, то есть точка входа библиотеки, npm-пакет является библиотекой.
Чтобы указать точку входа библиотеки, которую мы разрабатываем, мы должны указать в package.json в свойстве "main"
путь к файлу, который экспортирует нашу функцию или набор функций, если библиотека предоставляет несколько функций. Благодаря этому, тем, кто будет использовать эту библиотеку, не нужно знать в каком файле определена функция. Модуль, который указан в "main"
и будет импортироваться при импорте всей библиотеки.
Точка входа библиотеки и приложения в одном проекте
Часто бывает такое, что проект является приложением, но при этом его так же можно сделать и библиотекой. Представьте, что вы разрабатываете небольшое приложение, которое спрашивает у пользователя его возраст и печатает на экран в каком году он родился.
Решая эту задачу в лоб, вы можете написать в своем проекте один единственный файл. Не будем вдаваться в подробности кода, сейчас это не так важно:
// file: index.js
console.log('Сколько вам лет?')
const age = 18 // Каким-то способом получаем возраст пользователя, через терминал. Сейчас не важно как
const birthYear = 2005 // Подсчитываем результат
console.log(`Ваш год рождения: ${birthYear}`)
Вы можете пока не знать как получить значение, которое пользователь ввел в терминал или как получить текущую дату, чтобы рассчитать нужный год. Сейчас это не важно, поэтому в коде мы просто поставили заготовленные ответы.
Такое приложение будет работать и выполнять свою задачу. Но мы можем значительно расширить возможности нашего проекта, при этом потратив минимум усилий:
// file: src/index.js
export default (age) => {
const birthYear = 2005 // Подсчитываем результат
return birthYear
}
// file: index.js
import getBirthYear from './src/index.js'
console.log('Сколько вам лет?')
const age = 18 // Каким-то способом получаем возраст пользователя, через терминал. Сейчас не важно как
const birthYear = getBirthYear(age)
console.log(`Ваш год рождения: ${birthYear}`)
Мы выделили функцию подсчета года рождения в отдельный модуль. Теперь мы можем указать в "main"
нашего пакета путь к этому модулю ./src/index.js
. Теперь все, кто будет импортировать наш пакет, смогут использовать функцию для подсчета года рождения. Выделив функцию, мы значительно повысили возможности переиспользования нашего проекта.
Хорошей практикой считается всегда выделять подобные функции в ваших проектах. Это делается не только для переиспользования. Например, это значительно упрощает тестирование вашего проекта.
Обратите внимание, что мы не добавили вызов console.log()
и получение возраста в функцию. Это сделано потому, что эти операции предназначены только для консольных приложений. Если бы мы вместо возврата значения из функции делали просто вывод в консоль, то такую функцию нельзя было бы использовать для других задач, например, для веб-приложений.
По умолчанию в "main"
указывается файл index.js — это файл, который находится в корне проекта. Ниже пример package.json как он мог бы выглядеть для нашего проекта:
{
"name": "birth-year",
"type": "module",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Свойство "main"
указывает на файл src/index.js.
.
├── index.js
├── package.json
└── src
└── index.js
Итог
Мы познакомились с точками входа для приложений и библиотек. Разобрали, что для приложений точка входа является местом, где начинается выполнение кода, а для библиотек это модуль с экспортом сущностей и указанный в "main"
. Так же мы разобрали как можно расширить возможности проекта с помощью выделения логики в отдельную функцию, которая может быть переиспользована в других задачах. Все, что мы обсудили, тесно связано с проектированием проекта и позволит заложить фундамент хорошей архитектуры для сложных проектов.
Самостоятельная работа
- В проекте hexlet-js изучите какой файл импортируется из библиотеки lodash при импорте функций из этой библиотеки
- Перенесите логику из index.js в src/index.js, оберните в функцию и экспортируйте ее
- В файле index.js сделайте импорт функции из src/index.js и вызов этой функции
- Укажите в
"main"
путь к модулю с экспортом функции - Добавьте все изменения на гитхаб
Дополнительные материалы
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.