How To Setup GraphQL, Vue.js, and Phoenix 1.3 Part 2: The Frontend
In part 1, we covered how to setup an Elixir 1.4, Phoenix 1.3, and GraphQL backend. In this part 2, we setup the frontend of our Elixir & GraphQL & Vue.js project.
Now that you’ve setup and tested your Elixir backend, let’s create the frontend, using Vue’s single-file components feature, webpack, and Apollo to handle the GraphQL queries. I’m using Apollo 2.0+, Vue-apollo 3.0+, and Vue 2.5+.
Why This Stack?
- Vue: React used to have a scary patent/license grant, but that has since been cleared up for me, although some attorneys disagree. I’m not your lawyer. Vue is considered by many simpler than React, and backed by Alibaba. Vue’s rendering is lightning-fast, lightweight, and using single-file components is wonderful. React is also a perfectly acceptable framework, and both have really strong communities.
- Webpack: Phoenix ships with Brunch, but I had trouble getting Brunch configured to play nice with Vue single-file components, whereas there were many examples of Webpack config files for use with Vue.
- Vue-Apollo/GraphQL: The Vue-Apollo library makes integrating Apollo-Client features into Vue components trivial. I’m able to easily setup GraphQL queries, mutations, caching, polling, and everything else you’d want to have a snappy frontend.
Create The Frontend
- Since we generated the app without Brunch, there’s no “assets” folder to hold all of our frontend javascript, css, etc. Let’s create one, and seed it with a package.json that contains all of the libraries we want to use. Here’s the contents of package.json. I cribbed most of this from the Vue Apollo documentation, which is your go-to for a more in-depth understanding of this frontend approach generally.
2. You can now run `npm install` from the assets folder and install your frontend assets. If you’re in the root of your project you cancd assets && npm install && cd
to jump into the assets folder, install js assets, and jump back to the root of your project.
3. Since we’re using Webpack we need a webpack.config.js in the root of our new assets folder. Here’s the one I’m using, slightly modified from the Vue command line app to generate new vue-apollo apps. The important edits are to the “entry” and “output” keys at the top. It now instructs webpack to start compiling at ./src/app.js and to output the final file in appname/priv/static/js/app.js, which is where Phoenix expects to find the app.js file to serve.
4. We need to tell Phoenix that we’re using webpack, and tell Phoenix to fire up Webpack and watch it when we’re developing. Open up config/dev.exs, and update the watchers: line to read like so. This tells the Phoenix app to use Webpack and watch for the correct changes to hot-reload the assets in the dev environment.
5. Now we have the groundwork laid, let’s start constructing our app’s main app.js. This is where we instructed Webpack to begin compiling all of our frontend assets, and we use it to setup the big-picture parts of the app. In our next step we’ll create the App from ‘./App.vue’ to import.
6. Let’s now create the top-level Vue component, App.vue. This is our outermost container. Because we’re using single-file components in Vue, we can put the HTML, JS, and CSS/SCSS all in the same file and Webpack will know how to handle it. This is convenient for reasoning about the view logic on a component-level basis. Here’s the skeleton, including some custom styling lifted from the Vue welcome screen.
7. Ok, so we’ve got the Vue-specific stuff working, let’s make sure the GraphQL/Apollo is actually wired up correctly and talking to our server by constructing a simple query that asks for a user. We’ll hit the graphql resolver that we created in part 1. In App.vue, we can add an ‘apollo’ key for Apollo-specific directions, like GraphQL queries to execute, and Apollo will assign the result of the queries to the data object in our component. This is really useful because it allows each component to specify the data it needs, and Apollo can combine all of the data requirements into one request and then distribute the results back to the components, de-duplicating requests client-side.
In our App.vue, we first need to import the gql library to easily construct GraphQL queries. Then, under the ‘apollo’ key, we tell Apollo to execute a graphql query, and assign the result of that query to the data element called ‘user.’ I added the {{ user.name }} line to the HTML so we can see the result on our page. This will show us the “name” of the “user” data key as soon as it’s present.
8. Done! When you fire up the server with iex -S mix phx.server
and navigate to localhost:4000 you should see a “Welcome to your Vue.js and Phoenix and GraphQL App” followed by a “The following was loaded over Graphql: Fake User” line.
Next Steps & Further Reading
- Get the Vue devtools for your browser to easily inspect Vue apps: https://github.com/vuejs/vue-devtools.
- From late 2016, a good writeup of Absinthe/GraphQL/Elixir. 99% is still applicable: https://ryanswapp.com/2016/11/29/phoenix-graphql-tutorial-with-absinthe/.
- Vue-Apollo library for integrating Apollo with Vue: https://github.com/Akryum/vue-apollo
- Why GraphQL is better than REST: https://www.howtographql.com/basics/1-graphql-is-the-better-rest/. This is an example where both the end performance increases and developer happiness increases at the same time. Usually developer happiness and production quality are in tension.
- Handling Authentication in GraphQL: https://github.com/absinthe-graphql/absinthe/blob/master/guides/context-and-authentication.md
Bio
Grant Nelson is a developer, attorney, and cofounder of the “Uber for leftover food”, MEANS Database, although now he only sits on the board. MEANS is a platform for efficiently donating leftover food, and handles donations between 5 lbs and 50,000 lbs. His day job as an attorney gives him the opportunity to read & write code at times, and he spends much of his free time on side projects. Reach out if you want to help build something cool — there are many projects on his plate.