В public так же лежат файлы css, js, jpg которые использует страничка, и к сожалению клиент может получить к ним доступ, если я предоставляю эту директорию.
Не понимаю, что в этом плохого? Если у клиента не будет доступа к css, js и другим ресурсам, то они перестанут работать, картинки не будут отображаться, шрифты станут отображаться стандартными.
Как было бы поступить правильней, предоставляя страницу?
Не храните никаких приватных данных в папке такого рода как /public. Название папки говорит само за себя - публичная информация.
В какой именно момент следует закрывать соединение, методом end()?
res.end() закрывает не соединение, а заканчивает ответ на запрос. При этом соединение может оставаться открытым, если оно keep-alive.
Правилен ли такой подход?
Нет, неправильный. Подключите логгер типа
morgan или любой другой:
app.use(morgan(':id :method :url :response-time'));
и читайте логи, если они вам интересны.
А если файл index.html не будет меняться, не надо его описывать, как частный случай. express.static() делает гораздо больше чем просто sendFile(). Он указывает поисковикам, например, дату последнего изменения файла, чтобы не переиндексировать файл, файл должен быть доступен не только по запросу GET, но и по запросу HEAD.
Если от клиента со странички прилетает ajax запрос, то я отдельно обрабатываю его отсылая данные, и закрываю это соединение, но основное соединение, через которое я предоставил страницу должно постоянно находиться открытым?
Ajax и соединения - это совсем разные уровни абстракции. Соединения если рассматривать на уровне tcp, открываются и закрываются автоматом. Модулями http или https они не регулируются. Если необходимо работать с соединениями, нужен модуль net. Ajax сработает в любом случае, даже если соединение закрыто, он откроет новое, опять же автоматически, браузер не предоставляет api клиентскому javascript управлять соединениями к серверу кроме WebSocket.