GraphQL with Go
There actually is a ready project for using GraphQL so it's quite simple to start using it on the backend side.I couldn't think of any really good topic to make so I wrote some Star Wars characters into a file and used those.
var personType = graphql.NewObject( graphql.ObjectConfig{ Name: "person", Fields: fields, }, )
There is only one type and it's definition is simple enough.
var queryType = graphql.NewObject(graphql.ObjectConfig{ Name: "RootQuery", Fields: graphql.Fields{ "person": &graphql.Field{ Type: personType, Args: args, Resolve: func(p graphql.ResolveParams) (interface{}, error) { return filterPerson(data, p.Args), nil }, }, "personList": &graphql.Field{ Type: graphql.NewList(personType), Resolve: func(p graphql.ResolveParams) (interface{}, error) { return data, nil }, }, }, })
Now, the query type includes two fields to make queries. Person field filters the data with a query parameter from the request. PersonList field just returns the whole data or list of Star Wars characters.
schema, _ = graphql.NewSchema( graphql.SchemaConfig{ Query: queryType, }, )
Schema defines the capabilities of the server with queryType.
func main() { err := importJSONDataFromFile(jsonDataFile) if err != nil { fmt.Printf("Error: %s\n", err.Error()) return } http.HandleFunc("/graphql", func(w http.ResponseWriter, r *http.Request) { result := executeQuery(r.URL.Query()["query"][0], schema) w.Header().Add("Access-Control-Allow-Origin", "*") json.NewEncoder(w).Encode(result) }) fs := http.FileServer(http.Dir("frontend/dist")) http.Handle("/", fs) fmt.Println("Now server is running on port 8000") http.ListenAndServe(":8000", nil) }
The main function of the server does four things. First, it gets the Star Wars character json and makes the personType "fields" and queryType "data" available. Second, it sets listening endpoint to /graphql for queries. Third, it defines a file server for static content for root "/" endpoint. And for last, it starts the server.
At this point, qraphql queries already work. If your start the server, and query it for example with:
curl http://localhost:8000/graphql?query={person(name:%22Darth%22){id,name,surname}}
You get an answer:
{ data: { person: { id: "1", name: "Darth", surname: "Vader" } } }
Vue.js
To really test what the difference is between using ordinary Rest APIs and GraphQL I set up a small front-end to fetch and show the data.I first set up the vue.js project under front-end directory, in production it would be delivered from there. In development it can be run separetily with hot reloading and the works.
cd frontend npm install -g vue-cli vue init webpack graphql-vue-example mv graphql-vue-example/* . rmdir graphql-vue-example npm install npm run dev
Now, this sets up an initial project, it needs some work to get all things like we want them. Almost everything that needs to be changed, is at "frontend/src/components/Persons.vue". It contains the html template, vue javascript for the page and scoped styles.
<template> <div class="personclass"> <h1>{{ msg }}</h1> <input id="personName" type="text" value="Darth" v-model="personName"></input> <button class="btn btn-primary" v-on:click="getPerson()">Get Star wars person</button> <h2>One fetched person</h2> <div>{{ person.person.id }} {{ person.person.name }} {{ person.person.surname }}</div> <h2>List of all</h2> <div v-for="value in persons.personList"> {{ value.id }} {{ value.name }} {{ value.surname }} </div> </div> </template>
If you write a name of a character to the input field and then click the button, it goes and fetches the character in question. Of course, only if there is a match. There also is the whole list, which is fetched immediately when the page is rendered.
<script> export default { name: 'personclass', data () { return { msg: 'Star Wars persons', person: {person: {id: '', name: '', surname: ''}}, persons: '' } }, mounted () { this.getPersons() }, methods: { getPerson () { console.log(this.personName) this.$http.get('http://localhost:8000/graphql?query=' +
encodeURIComponent('{person(name:"' + this.personName + '"){id,name,surname}}'))
.then(response => { this.person = JSON.parse(response.body).data }, response => { console.log(response) }) }, getPersons () { this.$http.get('http://localhost:8000/graphql?query=' +
encodeURIComponent('{personList{id,name,surname}}')).then(response => { this.persons = JSON.parse(response.body).data }, response => { console.log(response) }) } } } </script>
The Vue javascript part is simple enough. There are two methods, getPersons gets all the Star Wars characters and it's called when the page is mounted. Method getPerson is called from the html page when the button is clicked and it returns only the character which is being searched.
The whole example project in github: https://github.com/jelinden/graphql-vue-example
References
https://facebook.github.io/react/blog/2015/05/01/graphql-introduction.htmlhttps://github.com/graphql-go/graphql
https://vuejs.org/