Jakość kodu jest kluczową częścią procesu rozwoju, zwłaszcza jeśli chcesz pracować wydajnie w sposób długoterminowy. Istnieje wiele podejść i najlepszych praktyk, w tym całe metodologie zwinne, ale większość z nich odnosi się do dużego, korporacyjnego projektu prowadzonego przez co najmniej 6 osób.
Co powinniśmy zrobić, gdy projekt jest niewielka lub klient wciąż nie wie, czy warto zainwestować więcej? Oczywiście, na Etap MVP projektu, kod Stylizacja lub testy jednostkowe nie są najwyższym priorytetem. Inwestorzy zazwyczaj chcą mieć dobry produkt I daj spokój - jeśli działa, to nie potrzebuje testów, prawda?
Właściwie mam pewne doświadczenie w Tworzenie aplikacji od podstawnawet bez stosowania najlepszych praktyk. Pewne okoliczności biznesowe zmusiły mnie do szukania kompromisu między planami budżetowymi inwestora a listą "nice-to-have" dewelopera. Na szczęście, jeśli korzystasz z GitHub, większość typowych problemów związanych z jakością kodu można rozwiązać w kilka minut.
W tym artykule pokażę, jak korzystać z przepływów pracy GitHub w środowisku Node.js w celu standaryzacji bazy kodu.
Kilka założeń zanim zaczniemy:
- Jesteś zaznajomiony z NPM i konsolą Linux.
- Masz pewne doświadczenie z preprocesorami stylów, modułami ładującymi, bundlerami itp.
- Wiesz, do czego służą lintery i naprawdę chcesz wykorzystać je w swoich projektach.
1. Typowa struktura projektu JavaScript
Jeśli kiedykolwiek korzystałeś z frameworków JS, takich jak Vue lub React, można łatwo zauważyć pewne wspólne cechy między nimi, np:
- /src z całą logiką JS i komponentami,
- /test dla testów jednostkowych i e2e,
- /aktywa dla stylów, obrazów itp.
Nawet jeśli mówimy o JavaScript projekt, pracujemy w Węzeł środowisko, więc oczywiście powinno być również kilka rzeczy Node, takich jak package.json, package-lock.json i /node_modules w naszym katalogu głównym.
Wszystkie te rzeczy są na swoim miejscu - to właśnie nazywamy konwencja. Frameworki są wymyślane, aby zapewnić pewne rozsądne konwencje, więc zazwyczaj nie musimy nawet dbać o początkowy wzorzec projektowy. Ponieważ w tym przykładzie chcę wyjaśnić kilka podejść, nie zastosuję żadnych gotowych rozwiązań, takich jak Vue CLI.
Czas zrozumieć, co kryje się pod tymi wszystkimi magicznymi skryptami!
2. Rozszerzenie typowego projektu Node
Aby zapewnić wysokiej jakości rozwiązania, lintery są pierwszą rzeczą, od której powinniśmy zacząć podczas tworzenia nowego projektu. Skupmy się na dwóch linterach - Stylelint dla stylów (*.scss) i ESLint dla plików źródłowych (*.js). Oba te lintery są dostępne w NPM i dość łatwe w konfiguracji. Korzystanie z linterów wymaga przejścia przez proces instalacji, dodania plików konfiguracyjnych i zdefiniowania skryptów projektu. Zróbmy to krok po kroku.
3. Dodawanie Stylelint
Instalacja Stylelint w środowisku Node jest naprawdę prosta. Zgodnie z oficjalne dokumentymusisz po prostu uciekać:
npm install --save-dev stylelint stylelint-config-standard
i poczekać, aż się skończy.
stylelint-config-standard zapewnia domyślny zestaw reguł lintingu i może być zastąpiony dowolnym pakietem, który lepiej odpowiada Twoim potrzebom (np. Styl Airbnb). Następnie utwórz nowy ukryty plik .stylelintrc.jsonktóry jest plikiem konfiguracyjnym Stylelint, odpowiedzialnym za ładowanie naszych predefiniowanych reguł:
{
"extends": "stylelint-config-standard"
}
W tej chwili jedyną brakującą rzeczą jest jakiś skrypt (lub skrypty) NPM zadeklarowany w pliku package.json, aby rozpocząć linting naszych plików SCSS. Oto moja propozycja:
"scripts": {
"lint:scss": "stylelint '**/*.scss' --syntax scss -f verbose --color",
"lint:scss:fix": "stylelint '**/*.scss' --syntax scss --fix -f verbose -color".
}
Jak widać, zadeklarowałem skrypt zawierający -fix opcja - tej opcji należy użyć przed wypchnięciem zmian do repozytorium.
Należy pamiętać, że korzystanie z niego jest złą praktyką. -fix w przepływie CI, ponieważ wtedy kod przekazywany do produkcji nie jest poprawnie stylizowany w repozytorium. Dlatego potrzebujemy obu skryptów.
Przetestujmy nasz linter, tworząc plik /assets/scss/styles.scss z pewną zawartością, np:
body {
background-color: #fff;
}
npm run lint:scss
W konsoli powinno pojawić się coś takiego:
> stylelint '**/*.scss' --syntax scss -f verbose --color
assets/scss/styles.scss
2:21 ✖ Oczekiwane wcięcie 2 spacje wcięcie
Sprawdzono 1 źródło
~/Codest/Projects/github-workflow-demo/assets/scss/styles.scss
Znaleziono 1 problem
poziom ważności "błąd": 1
wcięcie: 1
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! [email protected] lint:scss: `stylelint '**/*.scss' --syntax scss -f verbose --color`
npm ERR! Status wyjścia 2
Oznacza to, że nasz linter działa!
Wynik pokazuje dokładnie, która linia powoduje błąd i opisuje problem do rozwiązania. Niektórych błędów nie da się naprawić automatycznie, ponieważ wymagają one decyzji dewelopera, ale w większości przypadków wystarczy uruchomić to samo polecenie z rozszerzeniem -fix więc uruchommy ją.
npm run lint:scss:fix
Teraz powinieneś zobaczyć zielone wyjście bez znalezionych błędów:
stylelint '**/*.scss' --syntax scss --fix -f verbose --color
1 sprawdzone źródło
/Users/wojciechbak/Codest/Projects/github-workflow-demo/assets/scss/styles.scss
Znaleziono 0 problemów
4. Dodawanie ESLint
Ten krok jest prawie taki sam jak poprzedni. Zainstalujemy ESLint, zdefiniujemy domyślny zestaw reguł i zadeklarujemy dwa wywoływalne skrypty NPM - jeden dla CI, drugi dla pre-push. Przejdźmy przez to!
Jeśli używasz NPM w swojej codziennej pracy, być może chciałbyś zainstalować ESLint globalnie. Jeśli nie, zapoznaj się z instrukcjami instalacji na stronie oficjalne dokumenty.
npm install -g eslint
Gdy polecenie eslint jest dostępne na komputerze, wystarczy uruchomić je w projekcie:
eslint --init
Postępując zgodnie z dalszymi instrukcjami wyświetlanymi w terminalu, wystarczy podjąć kilka decyzji dotyczących projektu, takich jak
- Javascript lub TypeScript
- Styl Airbnb lub styl Google
- typ konfiguracji (plik JSON, plik JS lub inline w package.json)
- Moduły ES (import/eksport) lub wymagać składnia
W tym miejscu warto napisać kilka słów o formatatorze kodu o nazwie Prettier. Jest on w pełni ustandaryzowany i kompatybilny z większością edytorów kodu (np. VS Code). Prettier zapewnia wiele zestawów predefiniowanych reguł stylizacji kodu, współpracuje z linterami i może być świetnym wsparciem w dążeniu do najwyższej jakości kodu. Aby zrozumieć, czym dokładnie jest Prettier, odwiedź tę stronę porównanie z oficjalnych dokumentów.
Jeśli tak się stanie, plik konfiguracyjny ESlint (np. .eslintrc.json, w zależności od tego, co wybrałeś wcześniej) powinien pojawić się w katalogu głównym, gdzieś obok .stylelintrc.json stworzony wcześniej.
Teraz musimy zdefiniować skrypty w package.json tak samo jak w przypadku plików SCSS:
"scripts": {
"lint:js": "eslint '**/*.js' --ignore-pattern node_modules/",
"lint:js:fix": "eslint '**/*.js' --ignore-pattern node_modules/ --fix".
}
Gratulacje! ESLint jest już gotowy do użycia. Sprawdźmy, czy działa poprawnie. Utwórz /src/index.js z pewną zawartością:
console.log("coś");
Uruchom linter:
npm run lint:js
Wynik powinien wyglądać następująco:
> eslint '**/*.js' --ignore-pattern node_modules/
~/Codest/Projects/github-workflow-demo/src/index.js
1:1 ostrzeżenie Nieoczekiwana instrukcja konsoli no-console
1 problem (0 błędów, 1 ostrzeżenie)
To ostrzeżenie nie zniknie po użyciu -fix opcja, ponieważ linters nie wpływa na potencjalnie znaczący kod. Służą one tylko do stylizacji kodu, w tym białe spacje, nowe linie, średniki, cudzysłowy itp.
5. Definiowanie przepływów pracy GitHub
Przepływy pracy GitHub są dość dobrze udokumentowane. Zapraszam do zagłębienia się w ten temat, ale na razie zaimplementuję prosty workflow do lintowania naszego kodu po wypchnięciu do zdalnego repozytorium (oczywiście hostowanego na GitHubie).
Utwórz /.github/workflows katalog i nowy code-quality-workflow.yml ponieważ przepływy pracy GitHub muszą być definiowane za pomocą plików YAML.
Aby uruchomić prawidłowy workflow, musimy odpowiedzieć na kilka pytań:
- Kiedy chcemy uruchomić nasz przepływ pracy (przy wypychaniu, przy żądaniu ściągnięcia, przy scalaniu itp.)
- Czy chcemy wykluczyć niektóre sytuacje (takie jak push do gałęzi master)?
- Jakie środowisko musimy skonfigurować, aby poprawnie uruchamiać nasze polecenia (w tym przykładzie - Node)?
- Czy musimy instalować zależności? Jeśli tak, to w jaki sposób powinniśmy je buforować?
- Jakie kroki musimy wykonać, aby ukończyć kontrolę?
Po kilku przemyśleniach i kilku godzinach pracy z przykładowymi dokumentami .yml plik może wyglądać następująco:
Nazwa: Jakość kodu
on: 'push'
jobs:
code-quality:
name: Lint source code
runs-on: ubuntu-latest
kroki:
- uses: actions/checkout@v1
- nazwa: Setup Node
uses: actions/setup-node@v1
with:
node-version: '12.1'
- name: Zależności pamięci podręcznej
uses: actions/cache@v1
with:
path: ./node_modules
key: $(( runner.OS ))-dependencies-$(( hashFiles('**/package-lock.json') ))
restore-keys: |
$(( runner.OS ))-dependencies-$(( env.cache-name ))-
$(( runner.OS ))-dependencies-
$(( runner.OS ))-zależności-
- name: Zainstaluj zależności
run: |
npm install
- name: Lint files
run: |
npm run lint
GitHub zapewnia wszystkie rzeczy środowiskowe, których potrzebujemy. W ostatniej linii uruchamiamy polecenie npm run lint która nie była wcześniej zdefiniowana:
"scripts": {
"lint": "npm run lint:js && npm run lint:scss"
}
Zauważ, że w naszym przepływie pracy nie używam :fix polecenia.
Po wykonaniu wszystkich tych kroków możesz cieszyć się pięknym wynikiem z GitHub przed scaleniem Pull Request: