Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds
Powrót do kolekcji
Przewodnik11 min czytania

Portless, koniec z numerami portów

Portless zamienia numery portów na nazwane adresy .localhost, z HTTPS i osobnymi ciasteczkami. Instalacja, praca w monorepo, udostępnianie i ograniczenia.

Portless, czyli nazwy zamiast numerów portów

Portless zastępuje adresy typu localhost:3000 nazwanymi adresami w rodzaju sklep.localhost, obsługiwanymi po HTTPS. Zamiast pamiętać, który projekt zajął który numer, uruchamiasz serwer pod nazwą i pod nią go otwierasz.

Narzędzie pochodzi z laboratoriów Vercela, jest otwarte i działa niezależnie od frameworka. Uruchamiasz je przed dowolnym poleceniem startującym serwer deweloperski, a resztą zajmuje się pośrednik działający w tle.

Problem, który to rozwiązuje

Trzy uciążliwości lokalnej pracy, które osobno wydają się drobne, a razem zjadają zaskakująco dużo czasu.

Pierwsza to konflikt numerów. Piąta uruchomiona usługa dostaje komunikat o zajętym porcie, więc zmieniasz numer, a nazajutrz nie pamiętasz, który projekt gdzie działa. Zakładka otwarta wczoraj pokazuje dziś zupełnie inną aplikację.

Druga to mieszanie się danych przeglądarki. Wszystkie projekty na localhost dzielą tę samą przestrzeń ciasteczek i magazynu lokalnego, więc sesja z jednego projektu wpływa na drugi. Wylogowanie się w jednym miejscu potrafi wylogować Cię w trzech innych.

Trzecia to brak szyfrowania. Część funkcji przeglądarki działa wyłącznie na połączeniu szyfrowanym, więc lokalne środowisko bez niego zachowuje się inaczej niż produkcja, a różnica wychodzi zwykle dzień po wdrożeniu.

Nazwane adresy rozwiązują wszystkie trzy naraz, bo osobna nazwa to osobne pochodzenie w rozumieniu przeglądarki, a pośrednik obsługuje szyfrowanie.

Uruchomienie

Code
Bash
npm install -g portless
portless sklep next dev

Serwer działa jak dotąd, na przydzielonym numerze, a Ty otwierasz https://sklep.localhost. Pośrednik przekierowuje ruch, więc framework nie wymaga żadnej konfiguracji i nie musi nawet wiedzieć, że coś stoi przed nim.

Certyfikat dla połączenia szyfrowanego powstaje przy pierwszym uruchomieniu, razem z lokalnym urzędem certyfikacji dodawanym do magazynu zaufania systemu. To wymaga uprawnień administratora raz, przy pierwszym starcie, i potem działa bez pytania.

Warto od razu zainstalować pośrednika jako usługę systemową.

Code
Bash
portless service install

Bez tego kroku po każdym restarcie komputera trzeba uruchamiać go ręcznie, co szybko psuje cały zysk z wygody. Usługa startuje razem z systemem, a odinstalowanie jest równie jednym poleceniem. Mechanizm jest inny na każdym systemie operacyjnym, natomiast polecenie pozostaje to samo, więc nie musisz wiedzieć, który z nich obsługuje Twój komputer.

Praca w monorepo

Tu narzędzie pokazuje największą przewagę, bo repozytorium z sześcioma aplikacjami to sześć numerów do zapamiętania.

Code
Bash
portless web next dev
portless api node server.js
portless docs vitepress dev
portless panel vite

Adresy stają się web.localhost, api.localhost, docs.localhost i panel.localhost, a każdy z nich jest stabilny między sesjami. Zakładka zapisana w przeglądarce prowadzi zawsze tam, gdzie prowadziła wczoraj.

Poddomeny też działają, więc api.web.localhost obok web.localhost pozwala odwzorować układ znany z produkcji. To ma znaczenie przy testowaniu zasad dotyczących ciasteczek między poddomenami, bo lokalnie zachowują się wtedy tak samo jak na docelowej domenie.

Zmiany wymagane w kodzie są zwykle żadne albo drobne. Adresy wpisane na sztywno w konfiguracji trzeba podmienić, a najprościej wystawić je zmiennymi środowiskowymi, co i tak jest lepszą praktyką.

Miejsca, które warto sprawdzić przy tej okazji, są trzy: konfiguracja zasad dostępu między pochodzeniami po stronie serwera, adresy przekierowań powrotnych przy logowaniu przez zewnętrznego dostawcę oraz adres bazowy w testach uruchamiających przeglądarkę. Wszystkie trzy zawierają zwykle adres z numerem portu wpisany kiedyś na szybko i zapomniany, a każdy z nich zawodzi w inny, mylący sposób.

Udostępnianie poza własną maszyną

Poza nazwami lokalnymi narzędzie obsługuje trzy scenariusze, w których adres ma być widoczny szerzej.

Pierwszy to sieć lokalna. Nazwa w odpowiedniej domenie sprawia, że telefon podłączony do tej samej sieci otwiera aplikację bez szukania adresu IP komputera. Przy testowaniu widoku mobilnego to oszczędność kilku minut przy każdej sesji.

Drugi to udostępnienie przez prywatną sieć nakładkową, włączane jedną flagą. Aplikacja staje się dostępna dla urządzeń zapisanych do tej samej sieci, bez wystawiania czegokolwiek do publicznego internetu.

Trzeci to adres publiczny, i tu narzędzie nie odsyła Cię do osobnego programu. Jedna flaga wystawia aplikację przez publiczną odnogę tej samej sieci nakładkowej, druga przez zewnętrzną usługę tunelującą. W obu przypadkach adres lokalny działa dalej, a tunel jest sprzątany przy zamknięciu aplikacji.

Każdy z tych trybów to jeden przełącznik, odpowiednio przy uruchamianiu aplikacji i przy uruchamianiu samego pośrednika.

Code
Bash
portless mojaplikacja --tailscale next dev
portless mojaplikacja --funnel next dev
portless mojaplikacja --ngrok next dev
portless proxy start --lan

Każdy z nich ma odpowiednik w zmiennej środowiskowej, co bywa wygodniejsze przy pracy zespołowej: wpisany raz w pliku środowiska nie wymaga pamiętania o fladze przy każdym uruchomieniu i nie trafia przypadkiem do polecenia zapisanego w repozytorium.

Rozróżnienie między drugim a trzecim trybem jest tu najważniejsze, bo od niego zależy, kto zobaczy Twoją aplikację. Sama flaga sieci nakładkowej trzyma ruch między Twoimi urządzeniami, więc nadaje się do pokazania pracy w zespole i nie wystawi adresu klientowi spoza organizacji. Dopiero flaga publiczna albo flaga tunelu zewnętrznego otwiera adres dla każdego, kto go dostanie, i obie wymagają wcześniejszego włączenia odpowiedniej usługi po stronie dostawcy, w przeciwnym razie polecenie kończy się błędem przed uruchomieniem serwera.

Co się zmienia w codziennej pracy

Trzy rzeczy, które po tygodniu używania okazują się ważniejsze niż sama wygoda zapamiętywania nazw.

Pierwsza to zakładki i historia przeglądarki. Adres stabilny między sesjami sprawia, że autouzupełnianie w pasku adresu wreszcie działa poprawnie, zamiast podpowiadać cztery różne projekty pod jednym numerem. Przy pracy nad kilkoma repozytoriami naraz to oszczędność drobna, za to powtarzana kilkanaście razy dziennie.

Druga to narzędzia deweloperskie w przeglądarce. Zapisane punkty wstrzymania, filtry w podglądzie sieci i ustawienia w zakładce aplikacji są przypisane do pochodzenia, więc przy wspólnym adresie mieszały się między projektami. Osobna nazwa oznacza osobny zestaw ustawień, który zostaje tam, gdzie go zostawiłeś.

Trzecia dotyczy narzędzi automatyzujących pracę na Twoim komputerze. Polecenie z nazwą jest jednoznaczne i nie wymaga zgadywania numeru ani odczytywania go z wyjścia serwera, co przy skryptach i asystentach uruchamiających polecenia usuwa źródło błędów trudnych do odtworzenia.

Warto natomiast wiedzieć, że zmiana adresu potrafi unieważnić zapisane sesje. Dane trzymane dotąd pod wspólnym adresem nie przeniosą się pod nową nazwę, więc pierwszego dnia po przejściu trzeba zalogować się we wszystkich lokalnych środowiskach ponownie. To jednorazowa niedogodność i zarazem dowód, że rozdzielenie faktycznie działa.

Portless kontra alternatywy

RozwiązanieMocna stronaSłabośćKiedy wybrać
PortlessZero konfiguracji, HTTPS, niezależny od frameworkaMłody projekt, wymaga instalacji globalnejMonorepo z wieloma usługami
Wpisy w pliku hostówDziała wszędzie, nic nie instalujeszRęczna edycja, brak szyfrowaniaJeden albo dwa stałe adresy
Własny pośrednikPełna kontrola, dowolna konfiguracjaKonfiguracja i utrzymanie po Twojej stronieNietypowe wymagania sieciowe
Osobny tunel do internetuAdres dostępny dla każdegoKolejne narzędzie w procesieGdy nie chcesz wpinać tunelu w polecenie startowe

Pierwszy wiersz wygrywa wtedy, gdy usług jest kilka i uruchamiasz je codziennie. Przy jednej aplikacji na stałym numerze zysk jest niewielki i instalacja globalnego narzędzia nie ma uzasadnienia.

Ostatni wiersz to inna kategoria i warto o tym pamiętać przy porównywaniu. Tunel wystawia adres do publicznego internetu, czego nazwane adresy lokalne same z siebie nie robią. Osobne narzędzie tunelujące nie jest tu jednak warunkiem, bo pośrednik potrafi je uruchomić za Ciebie: flaga publiczna dokłada adres widoczny z zewnątrz obok adresu lokalnego, zamiast go zastępować.

Obie wbudowane drogi do adresu publicznego zakładają jednak zainstalowany i zalogowany program zewnętrznej usługi, a to jest dokładnie ten warunek, którego czasem nie chcesz spełniać. Wtedy prościej wychodzi tunel niewymagający ani instalacji, ani konta, jak tunnl.gg stawiany jedną komendą SSH. Ceną jest losowa poddomena i brak stałego adresu, więc do jednorazowego pokazu albo odebrania webhooka nadaje się dobrze, a do adresu, który ma działać przez tydzień, już nie.

Dlaczego lokalny HTTPS przestał być fanaberią

Warto rozwinąć wątek szyfrowania, bo to najczęściej niedoceniany powód sięgania po takie narzędzie.

Przeglądarki od lat ograniczają część możliwości do stron uznanych za bezpieczne. Dotyczy to dostępu do kamery i mikrofonu, geolokalizacji, powiadomień, mechanizmów działania bez sieci oraz kilku nowszych interfejsów. Adres localhost jest w tym kontekście traktowany ulgowo, natomiast adres w sieci lokalnej otwierany z telefonu już nie, i tam różnica boli najbardziej.

Drugi powód dotyczy ciasteczek. Ustawienia wymuszające bezpieczne połączenie i ograniczające wysyłanie ciasteczek między witrynami zachowują się inaczej bez szyfrowania. Logowanie działające lokalnie i psujące się na środowisku testowym to klasyczny objaw tej różnicy, a przyczyna bywa szukana godzinami po niewłaściwej stronie.

Trzeci to mieszana zawartość. Strona ładowana po szyfrowanym połączeniu nie pobierze zasobu po nieszyfrowanym, więc integracja z zewnętrzną usługą potrafi działać wyłącznie w jednym z tych układów. Odwzorowanie produkcji lokalnie usuwa całą tę klasę niespodzianek.

Wniosek jest prosty: im bliżej lokalne środowisko odwzorowuje produkcję, tym mniej błędów wychodzi dopiero po wdrożeniu. Nazwany adres z szyfrowaniem i osobnymi ciasteczkami jest tu tańszym sposobem na to zbliżenie niż stawianie pełnego środowiska testowego dla każdego programisty.

Ograniczenia, o których warto wiedzieć

Projekt jest młody, więc kilka rzeczy wymaga świadomej decyzji przed wpięciem go w proces całego zespołu.

Instalacja globalna oznacza, że każda osoba w zespole musi go zainstalować, a wersje mogą się rozjechać. Przy narzędziu wspólnym dla zespołu warto zapisać w dokumentacji projektu, którą wersję zakładacie.

Dodanie własnego urzędu certyfikacji do magazynu zaufania systemu to operacja, która w części organizacji podlega politykom bezpieczeństwa. Warto sprawdzić to zawczasu, zamiast dowiadywać się przy zablokowanym poleceniu.

Pośrednik nasłuchuje na porcie wymagającym podwyższonych uprawnień, więc usługa systemowa działa z prawami administratora. To jest normalne dla tej klasy narzędzi i mimo to warto o tym wiedzieć.

Wreszcie sama nazwa domeny lokalnej bywa różnie obsługiwana przez starsze narzędzia wiersza poleceń i biblioteki. Jeśli jakiś skrypt w Twoim projekcie sam odpytuje serwer, sprawdź go po zmianie adresów, bo część klientów HTTP domyślnie nie ufa własnym certyfikatom.

Wprowadzenie w zespole

Narzędzie instalowane globalnie wymaga innego podejścia niż zwykła zależność projektu, więc kilka słów o tym, jak zrobić to bezboleśnie.

Zacznij od siebie i popracuj tak tydzień, zanim zaproponujesz to reszcie. Część problemów, na przykład skrypt nieufający lokalnemu certyfikatowi, wychodzi dopiero przy codziennym używaniu, a lepiej odkryć je samemu niż na zebraniu.

Potem zapisz w dokumentacji repozytorium trzy rzeczy: polecenie instalacyjne, zakładaną wersję i dokładne polecenia uruchamiające poszczególne usługi. Bez tego trzeciego punktu każda osoba wymyśli własne nazwy i za miesiąc nikt nie będzie wiedział, czy adres z opisu błędu prowadzi do tej samej usługi.

Nazwy warto ustalić wspólnie i trzymać się ich, bo w tym tkwi cała wartość. Nazwa odpowiadająca katalogowi w repozytorium jest najprostszą konwencją i nie wymaga niczyjej pamięci.

Zostaw też dotychczasowy sposób uruchamiania jako działający. Polecenie startujące serwer bez pośrednika powinno nadal działać, żeby osoba, u której coś nie zagrało, mogła pracować dalej, zamiast czekać na pomoc. Narzędzie, które da się ominąć, przyjmuje się w zespole znacznie łatwiej niż takie, bez którego nic nie ruszy.

Typowe błędy

Pierwszy to pominięcie instalacji usługi systemowej. Po restarcie komputera adresy przestają działać, a przyczyna nie jest oczywista.

Drugi to trzymanie adresów na sztywno w kodzie. Zmienna środowiskowa rozwiązuje to raz i przydaje się również przy wdrożeniu.

Trzeci to mylenie udostępniania w sieci prywatnej z adresem publicznym. To pierwsze nie pokaże aplikacji osobie spoza Twojej sieci, a że obie rzeczy włącza się podobnie wyglądającą flagą, łatwo sięgnąć po niewłaściwą i albo pokazać klientowi pustkę, albo wystawić do internetu środowisko, które miało zostać w zespole.

Czwarty to zakładanie, że wszystkie narzędzia w projekcie zaakceptują lokalny certyfikat. Skrypty odpytujące serwer bywają tu wyjątkiem i wymagają wskazania urzędu certyfikacji.

Piąty to wprowadzenie narzędzia w zespole bez zapisania tego w dokumentacji projektu. Nowa osoba klonuje repozytorium, uruchamia polecenie z opisu i dostaje komunikat o braku programu.

Szósty to używanie go tam, gdzie nie ma problemu. Jedna aplikacja na jednym numerze nie potrzebuje warstwy pośredniczącej, a każde dodatkowe narzędzie w procesie to kolejna rzecz, która może się zepsuć w najgorszym momencie.

FAQ

Czy Portless działa z każdym frameworkiem?

Tak, ponieważ nie integruje się z frameworkiem. Uruchamiasz je przed dowolnym poleceniem startującym serwer, a pośrednik przekierowuje ruch niezależnie od tego, co działa pod spodem. Sprawdza się tak samo z Next.js, Vite i zwykłym serwerem w Node.

Skąd bierze się certyfikat dla HTTPS?

Przy pierwszym uruchomieniu powstaje lokalny urząd certyfikacji dodawany do magazynu zaufania systemu, a certyfikaty dla poszczególnych nazw są wystawiane na jego podstawie. Nic nie wychodzi poza Twoją maszynę.

Czy zastępuje tunel do internetu?

Nie zastępuje, tylko go wbudowuje. Poza siecią lokalną i prywatną siecią nakładkową między Twoimi urządzeniami dostępne są dwie flagi wystawiające adres publiczny: jedna przez publiczną odnogę tej samej sieci nakładkowej, druga przez zewnętrzną usługę tunelującą. Obie wymagają zainstalowanego i zalogowanego programu tej usługi, a do dłuższego pokazu klientowi i tak zwykle lepsze będzie wdrożenie podglądowe, na przykład na Vercelu, bo nie zależy od tego, czy Twój komputer jest włączony.

Czy każdy w zespole musi to zainstalować?

Tak, to narzędzie instalowane globalnie na maszynie, a nie zależność projektu. Warto zapisać ten wymóg w dokumentacji repozytorium razem z zakładaną wersją, żeby nowa osoba nie utknęła na pierwszym poleceniu.

Czy rozwiązuje problem mieszania się ciasteczek?

Tak, i to jest jego niedoceniana zaleta. Każda nazwa to osobne pochodzenie w rozumieniu przeglądarki, więc ciasteczka i magazyn lokalny są rozdzielone między projektami, zamiast dzielić jedną przestrzeń pod wspólnym adresem.

Kod i dokumentacja stoją w repozytorium na GitHubie, a listę wydań znajdziesz na stronie wydań projektu.