Adaptacja zewnętrznego pakietu npm do natywnych funkcji przeglądarki

Autor
Damian
Terlecki
5 minut
JS

Utrzymując starsze aplikacje napisane w języku JS prędzej czy później zauważysz podczas instalacji, że niektóre pakiety oznaczone są jako deprecated. Czasami powodem tego oznaczenia jest to, że funkcje pakietu zostały zaimplementowane w najnowszych wersjach przeglądarek i autorzy rezygnują z rozwijania biblioteki na rzecz funkcji natywnych:

WARN deprecated stable@0.1.8: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility

Często zastąpienie takich funkcji natywnymi pozwala na znaczne zmniejszenie rozmiaru dostarczanej aplikacji i zapewnia większe wsparcie w przypadku potencjalnych błędów. Taka adaptacja jest możliwa dzięki skonfigurowaniu nadpisanych zależności w pliku package.json w polu overrides:

{
  "overrides": {
    "baz": {
      "bar": {
        "foo": "1.0.0"
      }
    }
  }
}

Operacja ta jest bezpieczna pod warunkiem, że nowa wersja pakietu będzie kompatybilna z pakietami zależnymi. Warto pamiętać o tym przy aktualizacji pakietów zależnych (przykładowo mogą one nagle wymagać wersji, która nie jest kompatybilna z adaptacją pakietu). Z powyższego wynika więc minus, jakim jest potencjalne utrudnienie w utrzymywaniu aplikacji.

Na przykładzie pakietu react-static pokażę Ci jak zastąpić pośrednią zależność od pakietu axios funkcją natywną fetch zaimplementowaną w przeglądarce, jak i w NodeJS.

Adaptacja pakietu npm

Definicja pakietu react-static@7.6.2 wymaga w drzewie zależności pakietu axios@^0.21.1. Właściwie jednak jedynie funkcja axios.get() jest wykorzystywana w całym narzędziu i to tylko w dwóch miejscach – jako hook Reacta dostarczający dane strony oraz do prefetchu strony.

Axios jest pakietem, który oferuje dużo więcej funkcjonalności niż natywny fetch, wspierając jednocześnie więcej przeglądarek. Z drugiej strony, funkcję fetch znajdziemy już obecnie w większości nowszych przeglądarek, a pakiet axios dokłada jakkolwiek niewielką cegiełkę do rozmiaru aplikacji.

Rozmiar pakietu axios@0.27.2 (webpack-bundle-analyzer)

Standardowo po instalacji pakietów potrzebnych do react-static, znajdziesz pakiet axios w folderze node_modules/axios relatywnie do swojego projektu. W celu podmiany własną adaptacją polecam skopiowanie zawartości do korzenia projektu. Następnie w definicji pakietu usuń niepotrzebne zależności i dodając informacje o zmianach względem oryginału:

{
  "name": "axios",
  "version": "0.0.0",
  "description": "Promise based HTTP client for the browser and node.js. MODIFIED: Customized as a wrapper for fetch GET.",
  "main": "index.js",
  "author": "Matt Zabriskie",
  "license": "MIT"
}

Plikiem wejściowym pakietu jest index.js (module.exports = require('./lib/axios');), wskazany w polu main. Docelowy plik lib/axios.js zawiera eksport modułu. Adaptujemy go, implementując jedynie funkcję get(), odwołując się bezpośrednio do natywnej funkcji fetch. Aby zachować domyślne zachowanie, dodaj nagłówek Accept, oczekując w pierwszej kolejności formatu JSON, do którego zamienimy otrzymaną odpowiedź:

'use strict';

var axios = {
    get: (path) => {
        return fetch(path, {
            method: "GET",
            headers: {
                'Accept': 'application/json, text/plain, */*'
            }
        })
            .then(response => response.json())
            .then(data => ({data}));
    }
}

module.exports = axios;

Teraz wystarczy, że podmienimy namiary na pakiet w pliku package.json w polu resolutions (lub też w polu dependencies, jeśli również z niego korzystamy). Globalne nadpisanie adaptacji pakietu znajdującej się teraz lokalnie w folderze src/axios (polecenie npm install ./src/axios dla pola dependencies) będzie wyglądać tak:

{
  "resolutions": {
    "axios": "link:src/axios"
  }
}

Przy ręcznym dodaniu zależności pozostaje jedynie wywołanie polecenia npm install w celu aktualizacji pliku package-lock.json. Na sam koniec spróbuj przygotować kilka przypadków testowych, aby zweryfikować wszystkie przypadki użycia Twojej adaptacji.