Pewnie niektórzy są juz lekko zmęczeni tematem migracji bloga z Wordpressa do Jekylla. Z drugiej strony, sporo osób prosiło mnie o opisanie, w jaki sposób przeprowadziłem się z jednej z tych platform na drugą. Postanowiłem więc, że spełnię te prośby i tym samym raz na zawsze zamkniemy ten temat! Początkowo planowałem opisać całość “za jednym zamachem” ale okazało się, że opis samej tylko migracji danych z Wordpressa do Jekylla to prawie 2 tysiące słów. Dlatego też, temat został podzielony na dwie części: dziś opisuję jak przeniosłem posty i całą resztę do Jekylla, natomiast za tydzień przedstawię jak przeprowadziłem deployment do Heroku!

Migracja Wordpress - Jekyll

Zanim rozpocząłem operację przeniesienia wszystkich wpisów, stron itd., do Jekylla, trzeba było najpierw przeprowadzić jego instalację, utworzyć repozytorium na GitHubie i jeszcze parę innych rzeczy. Poniżej opisuję te kroki bardziej szczegółowo.

Instalacja Jekylla

Przenosiny na Jekylla rozpocząłem oczywiście od jego instalacji. Jeśli masz już wcześniej zainstalowane Ruby (ja miałem, jeśli Ty nie masz to musisz sprawdzić jak to zrobić w Twoim systemie operacyjnym) to wystarczy wykorzystać RubyGems, czyli menedżer pakietów Ruby:

gem install jekyll

Powyższe zainstaluje Ci Jekylla w najnowszej stabilnej wersji. Jak się później okazało, w moim przypadku konieczne było użycie tej komendy z dodatkowym parametrem:

gem install jekyll --pre

W ten sposób zainstalowałem sobie wersję “pre-release” (w chwili pisania tego tekstu jest to wersja 3.6.0.pre.beta1). Dlaczego? Ano dlatego, że kluczowe było dla mnie prawidłowe kolorowanie składni JSX, czego nigdy nie udało mi się zrobić w Wordpressie.

Do tego celu potrzebowałem odpowiedniej wersji biblioteki Rouge, która odpowiada za kolorowanie składni w Jekyllu (obsługa JSX pojawiła się w wersji 2.0.6 tej biblioteki). Niestety, stabilna wersja Jekylla używa biblioteki Rouge w znacznie starszej wersji i jest to zależność wymagana. Próba instalacji nowszej wersji Rouge i usunięcie wersji wymaganej (można mieć zainstalowane kilka wersji danego “gema” jednocześnie) powodowało błąd.

Dopiero we wspomnianej wersji 3.6.0 Jekylla dodano możliwość użycia biblioteki Rouge w najnowszej wersji, postanowiłem więc, że póki co skorzystam z wersji “pre-release”, oczywiście do czasu aż stanie się ona wersją stabilną.

Konfiguracja Jekylla

Po zainstalowaniu Jekylla mogłem przystąpić do jego konfiguracji. Praktycznie wszystko możemy ustawić edytując plik _config.yml. Myślę, że nie ma sensu abym wdawał się w szczegóły konfiguracyjne - to każdy może sobie sprawdzić w dokumentacji Jekylla.

W tym miejscu dodam tylko, że na tę chwilę korzystam tylko z trzech wtyczek dla Jekylla (to się być może zmieni w przyszłości). Pluginy te to:

  • jekyll-feed
  • jekyll-sitemap
  • jekyll-twitter-plugin

Co robią dwa pierwsze jest raczej oczywiste. Trzeci z nich usprawnia lekko proces osadzania tweetów.

Bundler i Gemfile

Oprócz konfiguracji w pliku _config.yml warto też używać narzędzia o wdzięcznej nazwie Bundler. Pozwala ono na kontrolę i instalację właściwych wersji poszczególnych “gemów” oraz ich zależności.

Bundlera instalujemy standardowo:

gem install bundler

Następnie należy dodać do głównego katalogu projektu plik Gemfile, w którym definiujemy wszystkie wymagane przez nasz projekt zależności - jest to więc swoisty odpowiednik pliku package.json znany nam z npm. W moim przypadku, plik ten wygląda następująco (w momencie pisania tego tekstu):

source 'https://rubygems.org'

ruby '2.4.1'

gem 'jekyll', '3.6.0.pre.beta1'
gem 'json'

# plugins
gem 'jekyll-sitemap'
gem 'jekyll-twitter-plugin'

# for deployment
gem 'rack-rewrite'
gem 'rack-contrib'
gem 'rake'
gem 'puma'

group :jekyll_plugins do
   gem "jekyll-feed", "~> 0.6"
end

gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

Część powyższych zależności dodana została później, na potrzeby deploymentu do Heroku. Omówię je w kolejnej części artykułu.

Posiadając zainstalowane narzędzie Bundler oraz utworzony plik Gemfile zawierający wymagane przez nasz projekt zależności, możemy uruchomić polecenie:

bundle install

Spowoduje ono instalację wszystkich niezbędnych pakietów zdefiniowanych w pliku Gemfile wraz z ich zależnościami. Oprócz tego utworzony zostanie plik Gemfile.lock, w którym Bundler zapisuje dokładne wersje zainstalowanych pakietów. Dzięki temu, jeśli wywołamy polecenie bundle install na innej maszynie, zostaną na niej zainstalowane dokładnie te same wersje pakietów co u nas.

Uwaga! Powyższe kroki będą niezbędne w późniejszym procesie deploymentu!

Szablon

Jekyll instalowany jest wraz z domyślnym szablonem o nazwie Minima. Oczywiście od początku wiedziałem, że nie chcę z niego korzystać tylko stworzyć swój własny szablon.

Minima jest szablonem opartym o “gemy” (w dokumentacji jest to nazwane z angielska “gem-based”). Oznacza to, że szablon ten jest osobnym pakietem, który można zainstalować za pomocą menedżera pakietów Ruby (wspomniane wcześniej RubyGems). Ja natomiast wolałem mieć pełną kontrolę nad szablonem w ramach mojego bloga.

Dlatego też, po przestudiowaniu dokumentacji Jekylla dotyczącej szablonów, usunąłem odwołania do szablonu Minima z plików Gemfile oraz _config.yml. Następnie, dla ułatwienia, przeniosłem zawartość szablonu Minima do głównego katalogu projektu bloga. Dzięki temu, mogłem sprawdzić jak ten szablon działa i na jego podstawie, modyfikując odpowiednie pliki, stworzyć własny wygląd bloga.

Dodatkowo, skonfigurowałem sobie webpacka i ustawiłem wszystko tak, aby generowały się osobne “bundle” zawierające kod JavaScript specyficzny dla danego typu strony (posty, podstrony). Do tego oczywiście jeden “bundle” dla vendors oraz jeden, o nazwie common zawierający kod współdzielony przez wszystkie typy stron.

Na tę chwilę webpackiem “ogarniam” tylko kod JavaScript, ponieważ Jekyll ma wbudowaną obsługę Sass. Planuję jednak przerobić to tak, aby style również były “traktowane” webpackiem. Dzięki temu uzyskam lepszą optymalizację wynikowego kodu CSS, a przy okazji pewnie zamiast Sass’a zastosuję mój ulubiony Stylus

Repozytorium na GitHubie

Po zainstalowaniu i skonfigurowaniu Jekylla, utworzyłem repozytorium na GitHubie, w którym będę trzymać cały projekt wraz z wpisami, obrazkami itp. Jest to repozytorium prywatne więc nie podaję do niego linka…

W tym miejscu warto wspomnieć, które pliki i katalogi dodałem do ignorowanych, tak aby nie wysyłały się one na serwer. Oto zawartość mojego pliku .gitignore w chwili pisania tego tekstu:

.sass-cache
.tweet-cache
.jekyll-metadata

_site
node_modules
assets/scripts

Trzy pierwsze wpisy to katalogi ukryte, tworzone podczas generowania strony przez Jekylla lub przez wtyczki (tutaj jekyll-twitter-plugin). Obecności wśród ignorowanych katalogu node_modules zapewne nie muszę Ci wyjaśniać.

Najważniejszy wpis to _site. Jego obecność tutaj wynika bezpośrednio z tego jak działa Jekyll. Otóż praca z nim wygląda w następujący sposób: do odpowiednich katalogów dodajemy posty oraz podstrony bloga (w formacie Markdown); następnie uruchamiamy polecenie:

jekyll build

Powoduje ono, że Jekyll przegląda katalogi naszego projektu, na tej podstawie generuje statyczne strony HTML, a wszystko w rezultacie ląduje w katalogu _site. Ten katalog następnie powinien być “serwowany” przez serwer WWW. Jak więc widać, jest to katalog generowany za każdym razem gdy coś zmienimy w naszym projekcie, nie ma więc sensu go wrzucać do repozytorium.

Uwaga! Dopilnuj, aby do repozytorium trafiły też pliki Gemfile oraz Gemfile.lock!

Przeniesienie danych z Wordpressa

Ok, Jekyll jest już w zasadzie skonfigurowany i umieszczony w repozytorium na GitHubie. Teraz nadeszła pora na najtrudniejszą część procesu czyli przeniesienie wpisów i podstron (wraz ze zdjęciami itp.) z Wordpressa do Jekylla.

Eksport danych z Wordpressa

Do eksportu danych w Wordpressa użyłem standardowej metody eksportu do formatu XML, jaki dostępny jest w menu NarzędziaExport tego CMS’a. Początkowo wybrałem opcję eksportu wszystkich treści ale po zaimportowaniu ich do Jekylla okazało się, że jest tego wszystkiego trochę za dużo.

Celem tej migracji było uproszczenie mojego bloga, nie potrzebowałem więc podstron typu “Kontakt” i wielu innych. Z tego względu postanowiłem przeprowadzić operację jeszcze raz i tym razem wyeksportowałem tylko posty, z zamiarem ręcznego przeniesienia treści podstron, które będę chciał mieć w nowym blogu.

Import danych do Jekylla

Importu wyeksportowanych wcześniej z Wordpressa postów dokonałem z użyciem metody zalecanej w dokumentacji Jekylla dla migracji z platformy wordpress.com. Do tego celu potrzebowałem narzędzia jekyll-import, które zainstalowałem następująco:

gem install jekyll-import

Pakietu tego nie trzeba dodawać do pliku Gemfile, ponieważ użyjemy go tylko raz, w celu importu. Kolejna rzecz, to uruchomienie procesu importu (wyeksportowane dane znajdują się w pliku nafrontendzie_posty.xml):

ruby -rubygems -e 'require "jekyll-import";
  JekyllImport::Importers::WordpressDotCom.run({
    "source" => "nafrontendzie_posty.xml"
  })'

Po zakończeniu działania powyższej komendy, w katalogu _posts znajdują się wszystkie wpisy wyeksportowane z Wordpressa. Oczywiście zawierają one metadane niezbędne dla Jekylla, takie jak autor, tytuł, data publikacji itp. Oprócz tego, do katalogu assets trafiły wszystkie obrazki użyte w treści postów. Niestety… Nie wszystko jest tak idealnie jakbyśmy tego chcieli…

Po pierwsze, posty zaimportowały się w formacie *.html, a nie *.md (Jekyll radzi sobie dobrze z obiema formami). W zasadzie można to tak zostawić i dopiero nowe posty tworzyć z użyciem składni Markdown, ja jednak postanowiłem to sobie przekonwertować (o tym za moment).

Po drugie, tak jak napisałem powyżej, obrazki się zaimportowały ale tylko te, które znajdują się w treści wpisów. W Wordpressie natomiast jest coś takiego jak “featured image” (po naszemu “obrazek wyróżniający”) czego standardowo nie ma w Jekyllu. Tutaj niestety musiałem sobie poradzić “ręcznie” i o tym również za chwilę.

Konwersja postów w HTML do Markdown

Do skonwertowania postów w formacie HTML do Markdown użyłem skryptu JavaScript znalezionego w tym repozytorium. Znajdziesz w nim plik index.js, który zawiera cały niezbędny kod.

Zawartość tego pliku skopiowałem do pliku convert.js, który umieściłem w głównym katalogu bloga. Wymaga on jednej zależności: html-md, którą tymczasowo zainstalowałem za pomocą yarn:

yarn add html-md

Teraz wystarczyło tylko uruchomić skrypt z pomocą Node.js:

node ./convert.js

I voilà! W katalogu _posts znajdują się teraz pliki *.md, natomiast oryginalne pliki HTML zostały przeniesione do katalogu _posts_html (po sprawdzeniu czy wszystko jest ok, można je bezpiecznie usunąć).

Obrazki wyróżniające

Tutaj niestety było więcej roboty, którą pewnie dałoby się jakoś zautomatyzować. Nie znalazłem jednak do tego żadnego gotowca, postanowiłem więc, że przeniosę wszystko ręcznie.

Ogólnie moje podejście wyglądało tak (rozwiązanie podsunął mi jakiś blog post znaleziony w internecie):

  • dla każdego z postów pobrałem odpowiednie zdjęcie ze starego bloga i umieściłem je w podkatalogu featured folderu assets
  • każdy wpis w Jekyllu zawiera metadane, w których umieściłem dodatkowe ustawienie image i przypisałem do niego ścieżkę do odpowiedniego pliku graficznego

Przykładowe metadane wyglądają tak:

---
layout: post
title: Na Frontendzie od nowa!
date: 2017-09-18 07:30:00 +02:00
type: post
published: true
status: publish
categories:
- opinie
tags: []
image: /assets/featured/Depositphotos_5868057_original.jpg
full: true
author:
  login: burczu
  email: b.dybowski@gmail.com
  display_name: Bartek Dybowski
  first_name: Bartek
  last_name: Dybowski
---

Teraz wystarczyło tylko wykorzystać zapisany w ten sposób link w szablonie. Mamy tam do niego dostęp poprzez zmienną page:

<img class="post-header__image" src="/assets/featured/{{ page.image }}" alt="Featured image of the post" />

Napisałem sobie też skrypt, który odpowiada za przycinanie i optymalizację tych obrazków, ale to jest temat na osobny wpis. Jeśli jesteś tym zainteresowany daj znać w komentarzach lub w prywatnej wiadomości, a być może przedstawię go w przyszłości na blogu!

Ostatnie szlify przed publikacją

W tym momencie najważniejsze rzeczy miałem już w zasadzie zrobione: posty zaimportowane wraz ze zdjęciami, szablon przygotowany, wszystko działa jak należy.

Pozostało jedynie utworzenie podstron “O mnie” oraz “Szkolenia”, które celowo pominąłem przy eksporcie (pisałem o tym wyżej). W Jekyllu mamy dwa sposoby na utworzenie takich podstron (więcej w dokumentacji).

Pierwszy z nich to umieszczenie odpowiednich plików w głównym katalogu projektu. W tym przypadku, nazwa pliku staje się jego adresem - na przykład plik o-mnie.md będzie dostępny pod adresem /o-mnie.

Drugi, bardziej odpowiadający mi sposób to trzymanie podstron w podkatalogu, który nazwałem pages. W takim przypadku, metadane każdego z plików podstron muszą zawierać właściwość permalink, która definiuje pod jakim adresem będzie dostępna dana podstrona. Dla przykładu, oto metadane podstrony o-mnie (plik about.md) na moim blogu:

---
layout: page
title: Więcej o mnie i o blogu
permalink: /o-mnie/
description: Na tej stronie przedstawiam parę słów o mnie. Skąd przychodzę, dokąd zmierzam... Dowiesz się z niej również co nieco o tym blogu!
---

Podsumowanie

To w zasadzie tyle jeśli chodzi o przeniesienie danych z Wordpressa do Jekylla. Tak jak napisałem na wstępie, w kolejnej części przedstawię, w jaki sposób skonfigurowałem deployment bloga na serwery Heroku.

P.S. Jeśli coś jest niejasne, opisane za mało szczegółowo albo coś ewidentnie pominąłem, daj znać w komentarzu, a postaram się uzupełnić braki!