Почему localhost — это тюрьма, и как из неё сбежать
Вы запускаете сервер на localhost:3000, 127.0.0.1:5173 или [::1]:8080 — всё работает идеально. Пока не попросите коллегу или друга открыть ваш проект. И тут начинается: «Страница недоступна», «Connection refused», «ERR_CONNECTION_REFUSED». Знакомо?
Проблема в том, что localhost (или 127.0.0.1) — это петлевой интерфейс. Ваш сервер слушает только на нём. Это как кричать в пустую комнату: вы слышите себя, но никто снаружи — нет. В этой статье мы разберём, как превратить локальный сервер в публичный (или хотя бы доступный в локальной сети) на TypeScript. Без магии, только проверенные методы.
Мы ответим на самые частые вопросы с Stack Overflow (где эта тема собрала тысячи просмотров) и дадим готовые решения для Express, Node.js и Vite.
1. База: что значит «слушать на всех интерфейсах»?
Когда вы пишете app.listen(3000) в Express, сервер по умолчанию слушает только localhost. Чтобы разрешить доступ извне, нужно указать 0.0.0.0 (все IPv4-интерфейсы) или :: (все IPv6).
Вот как это выглядит на TypeScript:
import express from 'express';
const app = express();
const PORT = 3000;
// Слушаем на всех интерфейсах
app.listen(PORT, '0.0.0.0', () => {
console.log(`Server is running on http://0.0.0.0:${PORT}`);
console.log(`Доступно в локальной сети по вашему IP`);
});
Теперь сервер доступен не только на localhost, но и по локальному IP вашего компьютера (например, 192.168.1.10:3000).
Как узнать свой локальный IP?
- Windows:
ipconfig→ ищите IPv4-адрес - macOS/Linux:
ifconfigилиip addr→ строкаinet 192.168.x.x
Но это только первый шаг. Часто проблема глубже — фаервол, CORS или то, что сервер всё ещё не отвечает с других устройств.
2. CORS: почему браузер блокирует запросы?
Даже если вы открыли доступ по сети, браузер может заблокировать запросы с другого домена. Это политика CORS (Cross-Origin Resource Sharing). Решение — настроить заголовки на сервере.
Установите пакет cors для Express:
npm install cors
npm install @types/cors --save-dev
Подключите в TypeScript-сервере:
import express from 'express';
import cors from 'cors';
const app = express();
// Разрешаем все источники (для разработки)
app.use(cors({
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
app.listen(3000, '0.0.0.0', () => {
console.log('CORS включён, сервер доступен извне');
});
Важно: В продакшене не используйте origin: '*' — укажите конкретные домены.
3. Фаервол: невидимый блокиратор
Даже если сервер слушает 0.0.0.0, ваш фаервол (брандмауэр) может блокировать входящие подключения. Это частая причина, по которой доступ извне не работает.
Как открыть порт (на примере Windows):
- Откройте «Брандмауэр Защитника Windows»
- Нажмите «Дополнительные параметры»
- Создайте правило для входящего подключения
- Укажите порт (например, 3000) и протокол (TCP)
- Разрешите подключение
На macOS/Linux используйте ufw или iptables:
# Разрешить порт 3000 через ufw
sudo ufw allow 3000/tcp
4. Проблема с Vite-сервером
Если вы используете Vite (популярный сборщик для TypeScript-проектов), по умолчанию он тоже слушает только localhost. Чтобы открыть доступ, измените vite.config.ts:
import { defineConfig } from 'vite';
export default defineConfig({
server: {
host: '0.0.0.0', // Слушаем все интерфейсы
port: 5173,
strictPort: true, // Не менять порт, если занят
cors: true // Включить CORS
}
});
Затем запустите npm run dev — сервер будет доступен по вашему локальному IP.
5. А если нужно из интернета? Знакомьтесь — ngrok
Все предыдущие методы работают только в локальной сети (Wi-Fi офиса или дома). Но что, если вы хотите показать проект другу в другом городе? Тут на помощь приходит ngrok — инструмент, который создаёт публичный туннель к вашему localhost.
Установите ngrok глобально:
npm install -g ngrok
Запустите туннель к вашему серверу (например, порт 3000):
ngrok http 3000
ngrok выдаст вам URL вида https://a1b2c3d4.ngrok.io. По этой ссылке ваш проект будет доступен из любой точки мира.
Интеграция ngrok с TypeScript-проектом
Вы можете автоматически запускать ngrok вместе с сервером. Вот пример с использованием @types/ngrok:
import ngrok from 'ngrok';
import express from 'express';
const app = express();
const PORT = 3000;
app.listen(PORT, '0.0.0.0', async () => {
try {
const url = await ngrok.connect(PORT);
console.log(`Публичный URL: ${url}`);
} catch (error) {
console.error('Ошибка ngrok:', error);
}
});
Совет: Бесплатный тариф ngrok ограничен (до 40 подключений/мин и случайный URL). Для продакшена используйте платный тариф или альтернативы (localtunnel, bore).
6. Частые ошибки и их решения (из Stack Overflow)
Блоги
Рекомендаций по книгам
Читайте также
Алгоритмы и структуры данных на Go: полное руководство для начинающих