Project setup
To view this content, buy the book! 😃🙏
Or if you’ve already purchased.
Project setup
There are a few different things to set up when starting a new Node project. We’ve set them up in branch 0
of our server repo, github.com/GraphQLGuide/guide-api:
$ git clone https://github.com/GraphQLGuide/guide-api.git
$ cd guide-api/
$ git checkout 0_0.2.0
$ npm install
We now have these files:
.babelrc
.git/
.gitignore
.nvmrc
.prettierrc
node_modules/
package-lock.json
package.json
Let’s look at each to see what they’re for.
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "12.0.0"
}
}
]
],
"plugins": ["import-graphql"]
}
@babel/preset-env
transpiles JavaScript to work in the target environment—where we’ll be running the code. In chapter 6, that was the browser. For this chapter, the target environment is Node. We’ll target version 12.0.0
so that the transpiled code will work in that or higher versions.
.git/
: directory where git stores its data..gitignore
:
node_modules/
dist/
A list of which files and folders we don’t want committed to git. We don’t want node_modules/
as they’re added when we npm install
. And dist/
will be generated by the build script in our package.json
.
.nvmrc
:
12
The file that tells nvm which version of Node to use. 12
means the latest stable 12.*
version.
.prettierrc
:
singleQuote: true
semi: false
trailingComma: none
arrowParens: avoid
Because single quotes and no semicolons is the One True Way to style JavaScript.
Just kidding—there isn’t one right way to style code. This is just author Loren’s preference 😄.
And the last two settings were the Prettier default when this chapter was written.
node_modules/
: directory to which npm downloads all of the packages our code depends on.package-lock.json
: precise current versions of all the packages.package.json
:
{
"name": "guide-api",
"version": "0.1.0",
"description": "api.graphql.guide",
"scripts": {
"dev": "nodemon -e js,graphql --exec 'npm run update-graphql-imports && babel-node src/index.js'",
"start": "node dist/index.js",
"build": "babel src -d dist --ignore **/*.test.js",
"update-graphql-imports": "rm -rf ./node_modules/.cache/@babel"
},
"engines": {
"node": ">=12"
},
"dependencies": {
"@sentry/node": "5.15.5",
"apollo-datasource-mongodb": "0.2.6",
"apollo-datasource-rest": "0.8.1",
"apollo-server": "2.12.0",
"apollo-server-cache-redis": "1.1.6",
"apollo-server-testing": "2.12.0",
"aws-sdk": "2.666.0",
"casual": "1.6.2",
"datasource-sql": "1.3.0",
"date-fns": "2.12.0",
"dotenv": "8.2.0",
"graphql": "14.6.0",
"graphql-redis-subscriptions": "2.2.1",
"graphql-request": "1.8.2",
"graphql-tools": "4.0.8",
"ioredis": "4.16.3",
"join-monster": "2.1.1",
"join-monster-graphql-tools-adapter": "0.1.0",
"jsonwebtoken": "8.5.1",
"jwks-rsa": "1.8.0",
"knex": "0.21.1",
"lodash": "4.17.15",
"mongodb": "3.5.7",
"sqlite3": "4.2.0"
},
"devDependencies": {
"@babel/cli": "7.8.4",
"@babel/core": "7.9.6",
"@babel/node": "7.8.7",
"@babel/preset-env": "7.9.6",
"apollo-link": "1.2.14",
"apollo-link-http": "1.5.17",
"babel-plugin-import-graphql": "2.7.0",
"eslint": "6.8.0",
"eslint-plugin-node": "11.1.0",
"husky": "4.2.5",
"jest": "25.5.2",
"node-fetch": "2.6.0",
"nodemon": "2.0.3"
},
"homepage": "https://github.com/GraphQLGuide/guide-api",
"repository": {
"type": "git",
"url": "git+https://github.com/GraphQLGuide/guide-api"
},
"bugs": {
"url": "https://github.com/GraphQLGuide/guide-api/issues"
},
"private": true,
"author": "The GraphQL Guide <[email protected]> (https://graphql.guide)"
}
Let’s look at the scripts first:
"scripts": {
"dev": "nodemon -e js,graphql --exec 'npm run update-graphql-imports && babel-node src/index.js'",
"start": "node dist/index.js",
"build": "babel src -d dist --ignore **/*.test.js",
"update-graphql-imports": "rm -rf ./node_modules/.cache/@babel"
},
npm run dev
will watch our JS and GraphQL files, and whenever one of them changes, it will transpile them with Babel and run them with Node.npm start
will start our server in production using the transpiled version of our code located indist/
.npm run build
will transpile our code fromsrc/
todist/
(ignoring test files).npm update-graphql-imports
is used bynpm run dev
to clear the babel GraphQL plugin cache.
The engines
attribute, similar to preset-env
’s target
, describes where the code is meant to be run. For us, it’s meant to be run in any version 8 or higher of Node.
"engines": {
"node": ">=12"
},
All together, what we’ve got configured is:
- Git
- npm
- nvm
- Babel
- Prettier
Apollo Server
If you’re jumping in here,
git checkout 0_0.2.0
(tag 0_0.2.0, or compare 0...1)
It takes less than 20 lines of JavaScript to get a working GraphQL server up and running! 😃 We recommend the apollo-server
GraphQL server library, and here’s the basic setup:
import { ApolloServer, gql } from 'apollo-server'
const server = new ApolloServer({
typeDefs: gql`
type Query {
hello: String!
}
`,
resolvers: {
Query: {
hello: () => '🌍🌏🌎'
}
}
})
server
.listen({ port: 4000 })
.then(({ url }) => console.log(`GraphQL server running at ${url}`))
The main export of apollo-server
is ApolloServer
, and its two required parameters are:
typeDefs
: our schema, written in SDL (the GraphQL Schema Definition Language), created with thegql
template literal tag.resolvers
: an object of resolver functions that match our schema in structure. Each type—Query
,Mutation
,User
,Chapter
, etc.—is a top-level attribute, and the next level is that type’s field names.
The three main alternatives to Apollo Server are the official
express-graphql
with GraphQL.js, Nexus, and TypeGraphQL, which all define the schema in different ways in code instead of in SDL.
We start the server by calling .listen()
on a port. When it’s done starting up, the Promise is resolved with the URL—in our case, http://localhost:4000
.
We can test it out with our dev
script:
$ npm run dev
> [email protected] dev /guide-api
> babel-watch src/index.js
GraphQL server running at http://localhost:4000/
After a moment, the program gets to the last line of our code, which logs Server running at http://localhost:4000/
. When we edit src/index.js
—for instance by changing console.log
—the server gets restarted:
$ npm run dev
> [email protected] dev /guide-api
> babel-watch src/index.js
GraphQL server running at http://localhost:4000/
>>> RESTARTING <<<
GraphQL server running with new console.log statement at http://localhost:4000/
To stop the server, we can press the control-c
key combination.
So we’ve got the server running, but does it work? Let’s open up the URL in a browser:
By default Apollo Server loads GraphQL Playground, an IDE for writing GraphQL queries. We can see our tiny schema by clicking on “DOCS” on the right:
And we can test out our one query:
And it works!