Thursday, February 2, 2017

Vote App (VoteMon) dengan GaphQl dan ReactJS [Bagian 1]


haigan kali ini kita akan membahas React dan temen-temennya, bagi kamu yang ngikutin terus dunia javascript khususnya react, pasti pernah denger graphQl, jika belum kamu bisa buka graphql.org, dan bagi yang mau belajar langsung graphql silahkan ikuti panduannya disini learngraphql by khadira.
Kamu masih belum tahu reactjs? kayanya kamu kurang bergaul deh, rajin baca-baca codepolitan aja ya.
Iya, kita mulai sekarang.
Pertama kita mulai dengan graphQl server.
Aplikasi yang dibutuhkan:
  • Nodejs, npm atau yarn
  • text editor
Text diawali dengan tanda adalah perintah terminal.
Buka terminalmu,
$ mkdir votemon-server
$ touch server.js
$ yarn init
silahkan kamu atur nama aplikasinya, author dan repo kamu.
untuk nodejs framework kita akan menggunakan express, jadi silahkan install beberapa dependecies di bawah:
$ yarn add body-parser cors express lodash
kamu bisa mempelajari masing-masing package di atas sendiri, sekarang kita tambahkan dependecies graphql server.
$ yarn add graphql graphql-server-express graphql-subscriptions graphql-tools subscriptions-transport-ws
Aku juga belum begitu mengerti graphql subscriptions, silahkan kamu pelajari postingannya di Medium.
Sekarang kita tambahkan beberapa Development Dependencies, seperti babel, eslint dan nodemon.
$ yarn add babel-cli babel-core babel-eslint babel-plugin-inline-import babel-pol
yfill babel-preset-es2015 babel-preset-react babel-preset-stage-0 eslint eslint-config-airbnb e
slint-plugin-import eslint-plugin-react nodemon --dev
Akhiran --dev digunakan sebagai devDependencies di yarn, seperti -D kalau menggunakan npm, silahkan buka file package.json kamu. Di sana kamu  tambahkan elsint config setelah devDependencies
"eslintConfig": {
"parser": "babel-eslint",
"extends": [
"airbnb/base",
"plugin:import/errors"
],
"rules": {
"no-use-before-define": 0,
"arrow-body-style": 0,
"dot-notation": 0,
"no-console": 0
},
"env": {
"mocha": true
}
}
view raweslint-package.json hosted with ❤ by GitHub
Kamu bisa melihat keseluruhan package.json di sini
buat file .babelrc, copy code di bawah
{
"passPerPreset": true,
"presets": [
"react",
"es2015",
"stage-0"
],
"plugins": [
"babel-plugin-inline-import"
]
}
view raw.babelrc hosted with ❤ by GitHub
Sebenernya kita tidak akan menggunakan react di votemon-server, kita akan memisahkan client dan graphql servernya.
sekarang buka file server.js mu dengan text-editor lalu copy code berikut
import express from 'express';
import { graphqlExpress, graphiqlExpress } from 'graphql-server-express';
import bodyParser from 'body-parser';
import cors from 'cors';
import { createServer } from 'http';
import { SubscriptionServer } from 'subscriptions-transport-ws';
import { printSchema } from 'graphql/utilities/schemaPrinter';
import { subscriptionManager } from './data/subscriptions';
import schema from './data/schema';
const GRAPHQL_PORT = 8080;
const WS_PORT = 8090;
const graphQLServer = express().use('*', cors());
graphQLServer.use('/graphql', bodyParser.json(), graphqlExpress({
schema,
context: {},
}));
graphQLServer.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
}));
graphQLServer.use('/schema', (req, res) => {
res.set('Content-Type', 'text/plain');
res.send(printSchema(schema));
});
graphQLServer.listen(GRAPHQL_PORT, () => console.log(
`GraphQL Server is now running on http://localhost:${GRAPHQL_PORT}/graphql`
));
// WebSocket server for subscriptions
const websocketServer = createServer((request, response) => {
response.writeHead(404);
response.end();
});
websocketServer.listen(WS_PORT, () => console.log( // eslint-disable-line no-console
`Websocket Server is now running on http://localhost:${WS_PORT}`
));
// eslint-disable-next-line
new SubscriptionServer(
{ subscriptionManager },
websocketServer
);
view rawserver.js hosted with ❤ by GitHub
 Code diatas adalah graphql server kita, jika kamu pernah menggunakan expressjs sebelumnya pasti cuma sedikit hal baru yang kamu liat, selain beberapa package yang sudah kita import coba perhatikan dua baris code ini:
import { subscriptionManager } from './data/subscriptions'; 
import schema from './data/schema';
Kita mengimport dua file subcriptions.js dan schema.js keduanya adalah inti dari graphql server kita. Gak familiar dengan codingan diatas? sudah belajar es6? bagi kamu yang belum menggunakan es6 silahkan pelajari di sini.
Buat folder di dalam directory votemon-server
$ mkdir data && cd data
$ touch schema.js subscriptions.js
lalu kamu copy masing-masing code di bawah:
Schemajs file:
import { makeExecutableSchema } from 'graphql-tools';
import resolvers from './resolvers';
const schema = `
type Type {
id: Int! # the ! means that every author object _must_ have an id
title: String
pokemons: [Pokemon] # the list of Posts by this author
}
type Pokemon {
id: Int!
name: String
image: String
type: Type
votes: Int
}
# the schema allows the following query:
type Query {
pokemons: [Pokemon]
}
# this schema allows the following mutation:
type Mutation {
upvotePokemon (
pokemonId: Int!
): Pokemon
}
type Subscription {
pokemonUpvoted: Pokemon
}
`;
export default makeExecutableSchema({
typeDefs: schema,
resolvers,
});
view rawschema.js hosted with ❤ by GitHub

Subscriptionsjs file
import { PubSub, SubscriptionManager } from 'graphql-subscriptions';
import schema from './schema';
const pubsub = new PubSub();
const subscriptionManager = new SubscriptionManager({
schema,
pubsub,
});
export { subscriptionManager, pubsub };
view rawsubscriptions.js hosted with ❤ by GitHub
Subscription code di atas adalah default, tapi sebelum itu kamu bisa lihat file schema js, di sana kita mengimport file resolvers js. File ini digunakan untuk menghubungkan data baik itu dari database, json maupun REST API.
Buat file baru dalam folder data 
$ touch resolvers.js
dan copy code di bawah ini:
import { find, filter } from 'lodash';
import { pubsub } from './subscriptions';
const types = [
{ id: 1, title: 'Water' },
{ id: 2, title: 'Electric' },
];
const pokemons = [
{ id: 1, typeId: 1, name: 'Squirtle', image: 'https://img.pokemondb.net/artwork/squirtle.jpg', votes: 2 },
{ id: 2, typeId: 2, name: 'Pikachu', image: 'https://img.pokemondb.net/artwork/pikachu.jpg', votes: 3 },
{ id: 3, typeId: 2, name: 'Raichu', image: 'https://img.pokemondb.net/artwork/raichu.jpg', votes: 1 },
];
const resolveFunctions = {
Query: {
pokemons() {
return pokemons;
},
},
Mutation: {
upvotePokemon(_, { pokemonId }) {
const pokemon = find(pokemons, { id: pokemonId });
if (!pokemon) {
throw new Error(`Couldn't find post with id ${pokemonId}`);
}
pokemon.votes += 1;
pubsub.publish('pokemonUpvoted', pokemon);
return pokemon;
},
},
Subscription: {
pokemonUpvoted(pokemon) {
return pokemon;
},
},
Type: {
pokemons(type) {
return filter(pokemons, { typeId: type.id });
},
},
Pokemon: {
type(pokemon) {
return find(types, { id: pokemon.typeId });
},
},
};
export default resolveFunctions;
view rawresolvers.js hosted with ❤ by GitHub
Uhuyy selesai juga graphql server kita, sebelum kita coba tambahkan scripts di file package.json kamu.
  "name": "votemon-server",
  "version": "0.1.0",
  "description": "graphql server votemon",
  "scripts": {
    "start": "nodemon ./server.js --exec babel-node",
    "test": "echo \"Error: no test specified\" && exit 1",
    "lint": "eslint ."
  },
  "main": "server.js",
sekarang ketika kita menggunakan perintah npm start di terminal, maka server graphql kita akan berjalan.
$ npm start
lalu buka link http://localhost:8080/graphiql di browser kamu, graphiql adalah web ui untuk query graphql kamu, untuk production kamu bisa menonaktifkannya.

screen shot 2016-11-05 at 2.12.12 pm
graphql query votemon-server

No comments:
Write komentar

Category