ZarahioN Presents

Answering why

Backend

GraphQL + Apollo + Express = ? [Pt. 1 — Installation adventure]

Заглянув таки пару минут назад на страницу с установкой аполло, я слегка ужаснулся..
тому, насколько давно я с ним не сталкивался.

Я как-то работал на проекте, у которого уже был базовый функционал и работал граф(кюэль? я продолжу называть GraphQL — граф а GraphiQL — графи, так проще, не спрашивай). Это был недолгий опыт, но именно тогда я по-настоящему влюбился в граф (и аполло) и все ждал возможности поиграть с ними еще немного.

Такая возможность наконец пришла и я оказался на удивление смел и решил создать пустенький проект самостоятельно, вместо привычного поиска готового шаблона.
(Спойлер: это оказалось приятной ошибкой и теперь я пишу эту запись, чтобы не повторять ее)

Конечно же я помнил все необходимые библиотеки (express, apollo-server, duh) и быстро установив их задумался, «А как его вообще подключать?». По дороге я вспомнил, что мне слишком лень настраивать еще и клиента и будет неплохо подумать над будущей моделью имея интерактив графи без необходимости начинать корячить само приложение. Оказавшись в тупике я ушел в гугл и быстро вернулся со страничкой гитхаба, где было описано, как подключить графи (с самим аполло я же влегкую справлюсь, да?)

Первая проблема бросилась в глаза быстро — аполло ставится под конкретный фреймворк (surprise!) а чистый apollo-server скорее всего предназначен для чистого Node.js сервера либо кастомной настройки. Откатываем установку apollo-server, ставим apollo-server-express…

И вспоминаем что синтаксис запуска экспресса я с коленки тоже не помню… Ладно, гугл, сайт экспресса, ctrl+c, ctrl+v.

Так, экспресс поставили, графи подключили, кажется все?

Нет.. нужно запустить сам граф, чтобы было что проверять (surprise! x2). Процесс знаешь? Не угадал, страница гитхаба про аполло и графи лежит в репо самого аполло и.. прямо на главной странице для самых умелых они разместили полный шаблон для старта экспресс-сервера с аполло, графи и граф-ом (оригинал можно найти по ссылке). Моя полноценная копия:

[cc lang=»javascript»]
import express from ‘express’;
import bodyParser from ‘body-parser’;
import { graphqlExpress, graphiqlExpress } from ‘apollo-server-express’;

const app = express();

app.get(‘/’, (req, res) => res.send(‘Bye-bye World!’))

app.use(‘/graphql’, bodyParser.json(), graphqlExpress({ schema: myGraphQLSchema }));
app.get(‘/graphiql’, graphiqlExpress({ endpointURL: ‘/graphql’ }));

const port = 81;
app.listen(port, () => console.log(‘Example app listening on port ‘ + port))
[/cc]

yarn start — and fail.
Мораль сей басни? Мы (я) забыли схему, точнее просто отвлеклись на погоню за облаками.

Импортируем будущую схему и собираем ее через небольшую утилиту (или пишем ручками, кому как нравится):

[cc lang=»javascript»]
@index.js
..
import myGraphQLSchema from ‘./schema’;

@schema.js
import { makeExecutableSchema } from ‘graphql-tools’;

import typeDefs from ‘./types’;
import resolvers from ‘./resolvers’;

const schema = makeExecutableSchema({
typeDefs,
resolvers,
});

export default schema;

@types.js
const Recipe = `
type Recipe {
id: Int!
message: String
author: String
}
`;

const Query = `
type Query {
recipies: [Recipe]
}
`

export default [Query, Recipe];

@resolvers.js
export default {
Query: {
recipies: () => [’empty’,’empty’,’empty’,]
}
}

[/cc]

Все? Все, не учитывая ленивый и пустой обработчик (resolver), но это на будущее.

Что мы сегодня узнали? Дети, используйте готовые шаблоны или придется писать технически бесполезные блог-посты. Ситуация не так уж и пичальна, впрочем — экспресс запущен, аполло «настроен» и все практически работает.

Ссылки на документацию для самых интересующихся (и тех, кто использует koa, hapi, restify, lambda, micro, azure-functions, adonis и хочет особенного отношения):
Apollo main doc
Apollo GraphiQL
How to Apollo GraphQL Schema
Express blank (Bye World) app

SymLinks to the rescue! Использование одной темы на нескольких WordPress сайтах

Вроде бы странное желание, делать одинаково выглядящие сайты, не так ли? Но тем не менее, у меня появилась такая нужда.

Дело в том, что на данный момент дизайном и созданием нескольких тем у нас заниматься некому, а у сайта издательства есть «неплохая» доработанная нами ранее тема (склеенная и немного перекрашенная Rambo от Webriti + капелька функционала сверху). И в начале я думал (и собственно попробовал) просто скопировать ее, но быстро понял, что если я внезапно решу подправить что-то где-то, придется страдать и копировать туда-сюда, и не дай Ишвар сделать разные изменения в одних и тех же файлах одновременно.

Поэтому мне в голову пришло гениальное решение. Почему бы не вынести тему в отдельную общую директорию? Придумано, найдено, сделано. У WP есть встроенный функционал для добавления новых директорий под темы (и не только)

Но немного не получилось, WP по глупости своей пытается подставить полный физический путь в возврат get_stylesheet_directory_uri или get_template_directory_uri вместо стандартного wp-content/themes/theme-name.

Почему? Все достаточно просто, этот функционал (скорее всего) предназначен для добавления файлов темы плагинам, к примеру, чтобы переписать часть темы или что-нибудь такое. Таким образом любой загружаемый через собранную из  get_template_directory_uri или get_stylesheet_directory_uri функций файл будет иметь некорректный путь. Мне же нужна одна общая для двух установок директория из которой они одновременно берут файлы одной темы.

Что же делать?

В начале я подумал подключить общую директорию дополнительным под-доменом и брать файлы оттуда заменив вызовы get_stylesheet_directory_uri  на get_stylesheet, который дает название темы, но я быстро понял, что это будет не очень надежный путь и все можно сделать куда проще.

Убираем register_theme_directory и идем в терминал, пора потрудиться.

Для справки, на момент написания статьи у нас стандартная установка apache на виртуальной ubuntu настроенная через sites-available файлы-конфиги виртуальных хостов, каждый сайт имеет свою директорию под /var/www/<site-name>, общая директория имеет структуру /var/www/shared/themes/<theme-name>.

Думаю, имевшие дело с Linux и пару извращенцев старательно чистившие чрезмерно маленький системный раздел на Win знают о таком интересном инструменте как Symbolic (или Hard) Link. Это по сути возможность создать ссылку, которую система и практически все современные программы будут «считать» реальным файлом или директорией — смогут пройти по ней и читать-редактировать-удалять файл или директорию на которую ссылается ссылка.

Итак, какой план? Вместо калупания конфигурации WP и изменений темы, (http-)ссылок и прочего, мы используем доступный функционал системы (благо апач успешно путешествует по ссылкам, разве что надо будет глянуть, какие угрозы безопасности это может сулить) и сделаем небольшие ссылки на нужную (каждую) нам тему:

ln -d -s /var/www/shared/themes/rambo-child /var/www/dev/wp-content/themes/rambo-child

Что создаст ln символьную -s ссылку dev/wp-content/themes/rambo-child, которая указывает на директорию -d shared/themes/rambo-child.

Проверяем, успех!

Паттерн комманды ln получается таким:

ln <target> <from>

(Мне казалось цель и откуда должны быть наборот, ну да ладно).

Полную справку можно почитать через man ln, а мы, пожалуй, завершаем наше небольшое путешествие.

Recap, to say. Мы (после долгого введения) вынесли необходимую тему в отдельную директорию, доступную апачу, убрали оригинал этой директории из wp-content/themes и создали вместо нее символьную ссылку на директорию, ссылающуюся на созданную нами копию темы.

Думаю, весь процесс достаточно прост, однако могут возникнуть проблемы, если у апача нет доступа к созданной директории или если он не может путешествовать по ссылкам (я, кажется, припоминаю такую настройку).
Плюс нужно учитывать проблему менеджмента — если кто-то запорит (ну или просто поменяет) тему на одном сайте, она меняется везде.

Но на этом, пора прощаться.