- PVSM.RU - https://www.pvsm.ru -
Часть 1. Сервер [1]
Для реализации UI рассмотрим пример написания веб-клиента для нашего GraphQL-сервера. И коли уж мы решили не следовать старым добрым традициям, то и в UI этого делать, конечно же, не будем и напишем его на кастомных веб-компонентах с использованием замечательной библиотеки Polymer [2].
Почему для подключения к GraphQL-серверу была выбрана библиотека Apollo [3] сказать сложно, так как аналогов для работы с GraphQL я не встречал. Изначально библиотека, как и вся ее документация заточена под React, а вся информация об интеграции с Polymer ограничивается лишь ссылкой [4] на компонент в разделе Integrations. Таким образом, если вы работаете с React, вам и карты в руки. Все примеры, твики и хуки именно для него.
Готовый проект клиента можно посмотреть и скачать тут [5].
Данный шаг не несет целевой нагрузки, но, опять же, необходим для начала работы с GraphQL. Таким образом, если вы с веб-компонентами на "ты", то можете этот шаг смело пропускать.
Как и в случае с сервером, для начала поднимем environment. Как это сделать вы сможете найти в официальной документаци [6]. Уточню лишь, что из всех предлагаемых опций, нам потребуется создать пустой проект Polymer (опция "2) polymer-2-application"), остальные опции можно оставить по-умолчанию:
$> polymer init
? Which starter template would you like to use?
? Which starter template would you like to use? polymer-init-polymer-2-applicat
info: Running template polymer-2-application...
? Application name (graphql-client-demo)
? Application name graphql-client-demo
? Main element name (graphql-client-demo-app)
? Main element name graphql-client-demo-app
? Brief description of the application GraphQL Demo Client
? Brief description of the application GraphQL Demo Client
create bower.json
create index.html
create manifest.json
create polymer.json
create README.md
create srcgraphql-client-demo-appgraphql-client-demo-app.html
create testgraphql-client-demo-appgraphql-client-demo-app_test.html
Project generated!
Installing dependencies...
И сразу же запустим:
$> polymer serve
info: Files in this directory are available under the following URLs
applications: http://127.0.0.1:8081
reusable components: http://127.0.0.1:8081/components/graphql-client-demo/
… и оставим запущенным, т.к. все изменения подхватываются на лету (для меня, как backend-щика, изначально это было не до конца очевидно).
Модуль для работы с библиотекой Apollo с неплохой документацией [7].
$> npm install --save polymer-apollo apollo-client
К сожалению реальность такова, что работа с этим модулем происходит через webpack. С одной стороны это не так и плохо, ввиду того, что webpack упаковывает все наши скрипты так, чтоб всё работало быстрее и эффективнее. Но с другой стороны для полноценной работы с webpack необходимо использовать npm вместо Polymer CLI. Из-за этого в работе с Polymer могут возникать непредвиденные ситуации. Это происходит из-за того, что невозможно настроить некоторые функции мимо конфигурационного файла polymer.json. Но тут, скорее всего, проблема в кривых руках backend-щика, так что не минусуйте сильно, а лучше поделитесь способами конфигурации в комментариях.
Примечание. Хотя существует лоадер вебпака для полимера [8] от разработчика самого расширения polymer-apollo, но я, по правде сказать, особой пользы от этого лоадера не ощутил.
$ npm install -g webpack
Затем добавим в корень проекта 2 файла:
webpack.config.js — настойки упаковщика;
entry.js — список всех js-файлов для упаковки (будет наполняться по ходу разработки приложения).
webpack.config.js:
module.exports = {
entry: "./entry.js",
output: {
path: __dirname,
filename: "bundle.js"
}
};
После чего в index.html нужно будет подключить только упакованный файл:
<script src="bundle.js"></script>
Чтобы подобрать правильную последовательность подключения всех скриптов и компонентов мне пришлось потратить определенное количество времени, так что советую не тратить своё и посмотреть секцию <head>
индекса в репозитории к статье [5].
Определенной структуры на стороне frontend, как мне кажется, быть не может по той причине, что она, как правило, заточена под конкретный проект. Но два элемента нам всё же понадобятся:
Это директория src/models, которая будет хранить все (прямо таки все-все) GraphQL запросы и ничего кроме них, и в дальнейшем будут подключаться по мере необходимости к местам использования. И...
import ApolloClient, { createNetworkInterface, addTypename } from 'apollo-client';
// Создаем GraphQL клиент
export const apolloClient = new ApolloClient({
networkInterface: createNetworkInterface({
// здесь заменяем URL на необходимый
uri: 'http://graphql.server.demo/api/graphql',
transportBatching: true,
})
});
… и не забываем добавить его в entry.js:
import "src/client.js"
К понятию модель как таковому эти файлы никакого отношения не имеют. Это лишь библиотеки строковых констант с запросами, сгруппированные по конкретному функционалу. Не принципиально привязываться именно к сущности. Возможна разбивка по конкретным страницам или функциональным элементам. Все на усмотрение разработчика.
src/models/user.js:
// чтобы мы могли писать наши запросы подключаем
import gql from 'graphql-tag';
// несмотря на то, что это и не обязательно,
// важно писать именованные запросы
// (т.е. запросы с алиасом: query getUserInfo { ... })
// в дальнейшем это нам поможет при отладке
export const getUserInfoQuery = gql`
query getUserInfo {
user(id: 1) {
firstname
lastname
createDate(format: "d M, H:i")
addresses {
city {
name
}
}
}
addresses {
user {
firstname
}
}
}
`;
Для удобства вынесем js из нашего созданного полимером компонента в отдельный файл, и внесем в него изменения чтобы он сотрудничал с библиотекой Apollo.
src/graphql-client-demo-app/graphql-client-demo-app.js:
import { PolymerApolloMixin } from 'polymer-apollo';
import { apolloClient } from '../client';
// заимпортим все необходимые запросы
// (пока что он у нас один)
import { getUserInfoQuery } from '../models/user';
class GraphqlClientDemoApp extends PolymerApolloMixin({ apolloClient }, Polymer.Element) {
static get is() { return 'graphql-client-demo-app'; }
static get properties() {
return {
appName: {
type: String,
value: 'GraphQL Client Demo'
},
// ВАЖНО!!!
// постарайтесь хорошо запомнить,
// что имя property должно в
// точности соответствовать названию
// корнегово поля запроса
// т.е. в данном случае наш запрос
// будет выглядеть следующим образом:
// query { user { ... } }
user: {
type: Object,
value: {}
}
};
}
// ну а здесь и будут наши запросы из моделей
get apollo() {
return {
getUserInfo: {
// наш запрос, который мы
// заимпортили из моделей
// нужно понимать, что этот запрос
// дернется сразу же при инициализации
// компонента
// можно ли этого избежать,
// я пока не разобрался
// разве что вызовом отдельной функции
query: getUserInfoQuery
}
};
}
}
window.customElements.define(GraphqlClientDemoApp.is, GraphqlClientDemoApp);
… и снова не забываем добавить его в entry.js:
import "src/client.js"
Ну и собственно осталось посмотреть на всё то, что придет с сервера.
src/graphql-client-demo-app/graphql-client-demo-app.html:
<dom-module id="graphql-client-demo-app">
<template>
<style>
</style>
<!-- просто пример вывода property -->
<h1>[[appName]]</h1>
<!-- пытаемся подтянуть данные из того
что должно было вернуться с сервера -->
<p><b>Name:</b> [[user.firstname]] [[user.lastname]]!</p>
<p><b>Created date:</b> [[user.createDate]]</p>
<h2>Addresses:</h2>
<table>
<!-- перебор массива -->
<template is="dom-repeat" items="{{user.addresses}}">
<!-- к несчастью в этом примере
только одно поле, но ведь мы понимаем,
что их может быть больше -->
<tr>
<td>{{index}}</td>
<td>{{item.city.name}}</td>
</tr>
</template>
</table>
</template>
</dom-module>
К слову, во время разработки шаблона мое окно среды выглядит примерно следующим образом:
В левой части экрана я полностью вижу структуру запроса (которая идентична структуре ответа), и описываю ее в шаблоне необходимым мне образом. Удобно.
Для начала не забываем собрать webpack:
$> webpack
Во время разработки вам, к сожалению, придется это делать после каждого обновления js-скриптов. Этого можно избежать, если следовать туториалу, написанным самим разработчиком polymer-apollo, и использовать npm start, но повторюсь, что если работать мимо polymer CLI, у вас могут возникнуть проблемы с некоторыми компонентами Polymer и с деплоем (конкретно я столкнулся с проблемой некорректной работы iron-pages и lazy-import, которую здесь описывать не буду т.к., к сожалению, пока еще не до конца решил).
Открываем Chrome, переходим на адрес нашего уже поднятого клиента (адрес можно увидеть сразу после выполнения $ polymer serve
, как правило это http://127.0.0.1:8081/ [9]) и радуемся результатам, вернувшимся с нашего GraphQL сервера:
И снова я не могу нарадоваться тулзам для отладки. Ставим расширение для Chrome Apollo Client Developer Tools [10], открываем консоль, переходим на вкладку Apollo, откидываемся на спинку кресла и начинаем получать удовольствие:
Помните, мы задавали алиас нашему запросу? Так вот в этом списке будут отображаться запросы именно по этим алиасам (иначе просто номер). Запросы и мутации отображаются отдельными списками. Стоит отметить, что эта тулза не является полной заменой вкладке Network, т.к. она показывает только запросы, а вот ответы — нет. Правда любой запрос одним нажатием на кнопочку возле алиаса запроса (или мутации) можно тут же загрузить во встроенный в это же расширение GraphiQL.
В целом такой себе лаконичный инспектор, так что коли вы захотите все же посмотреть по хедерам и статусам, милости просим на старую добрую вкладку Network.
В следующей(их) части(ях) мы наконец рассмотрим мутации, рассмотрим один из способов серверной валидации, и конечно же сделаем выводы.
Автор: timur560
Источник [11]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/263219
Ссылки в тексте:
[1] Часть 1. Сервер: https://habrahabr.ru/post/336758/
[2] библиотеки Polymer: https://www.polymer-project.org/2.0/start/
[3] библиотека Apollo: http://dev.apollodata.com/
[4] ссылкой: http://dev.apollodata.com/core/polymer.html
[5] Готовый проект клиента можно посмотреть и скачать тут: https://github.com/timur560/graphql-client-demo
[6] официальной документаци: https://www.polymer-project.org/2.0/start/install-2-0
[7] Модуль для работы с библиотекой Apollo с неплохой документацией: https://github.com/aruntk/polymer-apollo
[8] лоадер вебпака для полимера: https://github.com/aruntk/wc-loader
[9] http://127.0.0.1:8081/: http://127.0.0.1:8081/
[10] Apollo Client Developer Tools: https://dev-blog.apollodata.com/apollo-client-developer-tools-ff89181ebcf
[11] Источник: https://habrahabr.ru/post/337044/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.