From c4d4fc73cc14ae104323934db32c3fcae9b97e35 Mon Sep 17 00:00:00 2001 From: Jon Saints Date: Wed, 14 Sep 2016 11:11:53 -0600 Subject: [PATCH 01/10] enable relay support and configure babel plugins --- config/babel.dev.js | 8 +++++++ config/babel.prod.js | 6 +++++ config/paths.js | 2 ++ config/relay/babelRelayPlugin.js | 6 +++++ config/relay/setup.js | 38 ++++++++++++++++++++++++++++++++ package.json | 2 ++ 6 files changed, 62 insertions(+) create mode 100644 config/relay/babelRelayPlugin.js create mode 100644 config/relay/setup.js diff --git a/config/babel.dev.js b/config/babel.dev.js index ee7d4fdf6db..b724aefbc02 100644 --- a/config/babel.dev.js +++ b/config/babel.dev.js @@ -11,6 +11,7 @@ var path = require('path'); var findCacheDir = require('find-cache-dir'); +var relaySetup = require('./relay/setup'); module.exports = { // Don't try to find .babelrc because we want to force this configuration. @@ -46,3 +47,10 @@ module.exports = { }] ] }; + +// optional relay support https://facebook.github.io/relay +if (relaySetup.relayIsEnabled()) { + + // relay QL babel transform needs to run before react https://facebook.github.io/relay/docs/guides-babel-plugin.html#react-native-configuration + module.exports.plugins.unshift(require.resolve('./relay/babelRelayPlugin')); +} diff --git a/config/babel.prod.js b/config/babel.prod.js index f53094ababd..9f7a316348b 100644 --- a/config/babel.prod.js +++ b/config/babel.prod.js @@ -47,3 +47,9 @@ module.exports = { // require.resolve('babel-plugin-transform-react-constant-elements') ] }; + +// optional relay support https://facebook.github.io/relay +if (relaySetup.relayIsEnabled()) { + // relay QL babel transform needs to run before react https://facebook.github.io/relay/docs/guides-babel-plugin.html#react-native-configuration + module.exports.plugins.unshift(require.resolve('./relay/babelRelayPlugin')); +} diff --git a/config/paths.js b/config/paths.js index 9fbb4ecbc56..8c96033d621 100644 --- a/config/paths.js +++ b/config/paths.js @@ -38,6 +38,7 @@ module.exports = { appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), testsSetup: resolveApp('src/setupTests.js'), + relaySchema: resolveApp('src/schema.json'), appNodeModules: resolveApp('node_modules'), ownNodeModules: resolveApp('node_modules'), nodePaths: nodePaths @@ -55,6 +56,7 @@ module.exports = { appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), testsSetup: resolveApp('src/setupTests.js'), + relaySchema: resolveApp('src/schema.json'), appNodeModules: resolveApp('node_modules'), // this is empty with npm3 but node resolution searches higher anyway: ownNodeModules: resolveOwn('../node_modules'), diff --git a/config/relay/babelRelayPlugin.js b/config/relay/babelRelayPlugin.js new file mode 100644 index 00000000000..f9a47d3744f --- /dev/null +++ b/config/relay/babelRelayPlugin.js @@ -0,0 +1,6 @@ +var paths = require('../paths'); +var getbabelRelayPlugin = require('babel-relay-plugin'); + +var schema = require(paths.relaySchema); + +module.exports = getbabelRelayPlugin(schema.data); diff --git a/config/relay/setup.js b/config/relay/setup.js new file mode 100644 index 00000000000..bd239d94472 --- /dev/null +++ b/config/relay/setup.js @@ -0,0 +1,38 @@ +// @remove-on-eject-begin +/** + * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @relay + */ +// @remove-on-eject-end + +var paths = require('../paths'); + +/** + * relay requires 'react-relay' install and in package.json, GRAPHQL_URL env variable set to retrieve local copy of schema.json resulting from `npm run fetchRelaySchema` + */ +var relayIsEnabled = function() { + var appPackageJson = require(paths.appPackageJson); + if (appPackageJson && appPackageJson.dependencies && appPackageJson.dependencies['react-relay']) { + + if (!process.env.GRAPHQL_URL) { + throw new Error("Relay requires a url to your graphql server\nSpecifiy this in a GRAPHQL_URL environment variable.\n\n"); + } + + if (!paths.relaySchema) { + throw new Error("babel-relay-plugin requires a local copy of your graphql schema\nRun 'npm run fetchRelaySchema' to fetch it from the GRAPHQL_URL environment variable.\n\n"); + } + + return true; + } + + return false +} + +module.exports = { + relayIsEnabled: relayIsEnabled, +}; diff --git a/package.json b/package.json index 631b9618de8..f114c861082 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "babel-plugin-transform-runtime": "6.15.0", "babel-preset-latest": "6.14.0", "babel-preset-react": "6.11.1", + "babel-relay-plugin": "0.9.3", "babel-runtime": "6.11.6", "case-sensitive-paths-webpack-plugin": "1.1.4", "chalk": "1.1.3", @@ -69,6 +70,7 @@ "path-exists": "3.0.0", "postcss-loader": "0.11.1", "promise": "7.1.1", + "react-relay": "0.9.3", "recursive-readdir": "2.0.0", "rimraf": "2.5.4", "strip-ansi": "3.0.1", From e909b218238eeb2f408bcfad7a4c5daca464c64d Mon Sep 17 00:00:00 2001 From: Maxwell O'Roark Date: Wed, 14 Sep 2016 11:50:30 -0600 Subject: [PATCH 02/10] added introspection query for graphQL schema --- package.json | 7 +++++-- scripts/fetchRelaySchema.js | 39 +++++++++++++++++++++++++++++++++++++ scripts/init.js | 3 ++- 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 scripts/fetchRelaySchema.js diff --git a/package.json b/package.json index f114c861082..0542789c691 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "create-react-app": "tasks/cra.sh", "e2e": "tasks/e2e.sh", "start": "node scripts/start.js", - "test": "node scripts/test.js --env=jsdom" + "test": "node scripts/test.js --env=jsdom", + "fetchRelaySchema": "node scripts/fetchRelaySchema.js" }, "files": [ "PATENTS", @@ -59,18 +60,20 @@ "filesize": "3.3.0", "find-cache-dir": "^0.1.1", "fs-extra": "0.30.0", + "graphql": "0.7.0", "gzip-size": "3.0.0", "html-loader": "0.4.3", "html-webpack-plugin": "2.22.0", "http-proxy-middleware": "0.17.1", "jest": "15.1.1", "json-loader": "0.5.4", + "node-fetch": "1.6.1", "object-assign": "4.1.0", "opn": "4.0.2", "path-exists": "3.0.0", "postcss-loader": "0.11.1", "promise": "7.1.1", - "react-relay": "0.9.3", + "react-relay": "0.9.3", "recursive-readdir": "2.0.0", "rimraf": "2.5.4", "strip-ansi": "3.0.1", diff --git a/scripts/fetchRelaySchema.js b/scripts/fetchRelaySchema.js new file mode 100644 index 00000000000..d54dbbbc621 --- /dev/null +++ b/scripts/fetchRelaySchema.js @@ -0,0 +1,39 @@ +var fetch = require('node-fetch'); +var fs = require('fs'); +var graphQlutilities = require('graphql/utilities'); + +var buildClientSchema = graphQlutilities.buildClientSchema; +var introspectionQuery = graphQlutilities.introspectionQuery; +var printSchema = graphQlutilities.printSchema; + +var path = require('path'); +var paths = require('../config/paths') +var SERVER = process.env.GRAPHQL_URL; +console.log(SERVER) +// Save JSON of full schema introspection for Babel Relay Plugin to use +fetch(`${SERVER}`, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({'query': introspectionQuery}), +}) +.then(res => res.json()).then(schemaJSON => { + console.log(`${paths.appSrc}/schema.json`) + fs.writeFileSync( + `${paths.appSrc}/schema.json`, + JSON.stringify(schemaJSON, null, 2) + ); + + // Save user readable type system shorthand of schema + var graphQLSchema = buildClientSchema(schemaJSON.data); + fs.writeFileSync( + `${paths.appSrc}/schema.graphql`, + printSchema(graphQLSchema) + ); +}) +.catch((err)=>{ + console.log(err) + console.log(err.stack) +}) diff --git a/scripts/init.js b/scripts/init.js index 0b5282ae1df..186856d2c67 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -27,7 +27,8 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { 'start': 'react-scripts start', 'build': 'react-scripts build', 'test': 'react-scripts test --env=jsdom', - 'eject': 'react-scripts eject' + 'eject': 'react-scripts eject', + 'fetchRelaySchema': 'react-scripts fetchRelaySchema' }; // explicitly specify ESLint config path for editor plugins From c957fff980509cb7c501c07dc302bb6c3a549fe0 Mon Sep 17 00:00:00 2001 From: Jon Saints Date: Wed, 14 Sep 2016 13:27:57 -0600 Subject: [PATCH 03/10] basic support for relay no readme or nice errors yet --- .gitignore | 1 + bin/react-scripts.js | 1 + config/babel.dev.js | 3 +-- config/babel.prod.js | 1 + config/paths.js | 5 +++-- config/relay/setup.js | 2 +- scripts/fetchRelaySchema.js | 13 ++++++------- 7 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index f19abba4284..f0e2e564c38 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ build *.tgz my-app* template/src/__tests__/__snapshots__/ +schema.* diff --git a/bin/react-scripts.js b/bin/react-scripts.js index 58381833957..e771b044f92 100755 --- a/bin/react-scripts.js +++ b/bin/react-scripts.js @@ -8,6 +8,7 @@ case 'build': case 'eject': case 'start': case 'test': +case 'fetchRelaySchema': var result = spawn.sync( 'node', [require.resolve('../scripts/' + script)].concat(args), diff --git a/config/babel.dev.js b/config/babel.dev.js index b724aefbc02..0053ed25b06 100644 --- a/config/babel.dev.js +++ b/config/babel.dev.js @@ -49,8 +49,7 @@ module.exports = { }; // optional relay support https://facebook.github.io/relay -if (relaySetup.relayIsEnabled()) { - +if (relaySetup.relayIsEnabled()) { // relay QL babel transform needs to run before react https://facebook.github.io/relay/docs/guides-babel-plugin.html#react-native-configuration module.exports.plugins.unshift(require.resolve('./relay/babelRelayPlugin')); } diff --git a/config/babel.prod.js b/config/babel.prod.js index 9f7a316348b..768258ce577 100644 --- a/config/babel.prod.js +++ b/config/babel.prod.js @@ -10,6 +10,7 @@ // @remove-on-eject-end var path = require('path'); +var relaySetup = require('./relay/setup'); module.exports = { // Don't try to find .babelrc because we want to force this configuration. diff --git a/config/paths.js b/config/paths.js index 8c96033d621..c46fdd64d4a 100644 --- a/config/paths.js +++ b/config/paths.js @@ -38,7 +38,7 @@ module.exports = { appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), testsSetup: resolveApp('src/setupTests.js'), - relaySchema: resolveApp('src/schema.json'), + relaySchema: resolveApp('schema.json'), appNodeModules: resolveApp('node_modules'), ownNodeModules: resolveApp('node_modules'), nodePaths: nodePaths @@ -56,7 +56,7 @@ module.exports = { appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), testsSetup: resolveApp('src/setupTests.js'), - relaySchema: resolveApp('src/schema.json'), + relaySchema: resolveApp('schema.json'), appNodeModules: resolveApp('node_modules'), // this is empty with npm3 but node resolution searches higher anyway: ownNodeModules: resolveOwn('../node_modules'), @@ -71,6 +71,7 @@ module.exports = { appPackageJson: resolveOwn('../package.json'), appSrc: resolveOwn('../template/src'), testsSetup: resolveOwn('../template/src/setupTests.js'), + relaySchema: resolveOwn('../schema.json'), appNodeModules: resolveOwn('../node_modules'), ownNodeModules: resolveOwn('../node_modules'), nodePaths: nodePaths diff --git a/config/relay/setup.js b/config/relay/setup.js index bd239d94472..c978ded3c44 100644 --- a/config/relay/setup.js +++ b/config/relay/setup.js @@ -22,7 +22,7 @@ var relayIsEnabled = function() { if (!process.env.GRAPHQL_URL) { throw new Error("Relay requires a url to your graphql server\nSpecifiy this in a GRAPHQL_URL environment variable.\n\n"); } - +console.log(paths.relaySchema); if (!paths.relaySchema) { throw new Error("babel-relay-plugin requires a local copy of your graphql schema\nRun 'npm run fetchRelaySchema' to fetch it from the GRAPHQL_URL environment variable.\n\n"); } diff --git a/scripts/fetchRelaySchema.js b/scripts/fetchRelaySchema.js index d54dbbbc621..6443e017f0c 100644 --- a/scripts/fetchRelaySchema.js +++ b/scripts/fetchRelaySchema.js @@ -20,18 +20,17 @@ fetch(`${SERVER}`, { body: JSON.stringify({'query': introspectionQuery}), }) .then(res => res.json()).then(schemaJSON => { - console.log(`${paths.appSrc}/schema.json`) fs.writeFileSync( - `${paths.appSrc}/schema.json`, + `${paths.relaySchema}`, JSON.stringify(schemaJSON, null, 2) ); // Save user readable type system shorthand of schema - var graphQLSchema = buildClientSchema(schemaJSON.data); - fs.writeFileSync( - `${paths.appSrc}/schema.graphql`, - printSchema(graphQLSchema) - ); + // var graphQLSchema = buildClientSchema(schemaJSON.data); + // fs.writeFileSync( + // `${paths.relaySchema}/schema.graphql`, + // printSchema(graphQLSchema) + // ); }) .catch((err)=>{ console.log(err) From 474ca70d3e237b148e709302309ca18472345a8a Mon Sep 17 00:00:00 2001 From: Maxwell O'Roark Date: Wed, 14 Sep 2016 14:40:50 -0600 Subject: [PATCH 04/10] first draft of documentation for relay support --- README.md | 2 ++ template/README.md | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/README.md b/README.md index 978b6a6eaf1..f91b2cff7a6 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,8 @@ The [User Guide](https://github.com/facebookincubator/create-react-app/blob/mast - [Updating to New Releases](https://github.com/facebookincubator/create-react-app/blob/master/template/README.md#updating-to-new-releases) - [Folder Structure](https://github.com/facebookincubator/create-react-app/blob/master/template/README.md#folder-structure) - [Available Scripts](https://github.com/facebookincubator/create-react-app/blob/master/template/README.md#available-scripts) +- [Relay +Support](https://github.com/facebookincubator/create-react-app/blob/master/template/README.md#relay-support) - [Displaying Lint Output in the Editor](https://github.com/facebookincubator/create-react-app/blob/master/template/README.md#displaying-lint-output-in-the-editor) - [Installing a Dependency](https://github.com/facebookincubator/create-react-app/blob/master/template/README.md#installing-a-dependency) - [Importing a Component](https://github.com/facebookincubator/create-react-app/blob/master/template/README.md#importing-a-component) diff --git a/template/README.md b/template/README.md index 05ef2b43aa9..8e03cc14cfe 100644 --- a/template/README.md +++ b/template/README.md @@ -13,6 +13,8 @@ You can find the most recent version of this guide [here](https://github.com/fac - [npm test](#npm-test) - [npm run build](#npm-run-build) - [npm run eject](#npm-run-eject) + - [npm run fetchRelaySchema](#fetch-relay-schema) +- [Relay & GraphQL Support](#relay-support) - [Displaying Lint Output in the Editor](#displaying-lint-output-in-the-editor) - [Installing a Dependency](#installing-a-dependency) - [Importing a Component](#importing-a-component) @@ -141,6 +143,26 @@ Instead, it will copy all the configuration files and the transitive dependencie You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. +### `npm run fetchRelaySchema` + +See documentation on [Relay Support](#relay-support) before running this command. + +Fetches schema from an [introspection](http://graphql.org/learn/introspection/) query to your graphQL server. This query will require your `GRAPHQL_URL=` env variable to be set. + +## Relay Support + +You can create a [Relay](https://facebook.github.io/relay/) application with create-react-app. You will need a GraphQL server1 to connect to and an environment variable that points to its location. The environment variable needs to be named `GRAPHQL_URL`. + +1[CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) enabled, most likely. + +Assuming you have set your environment variable, created your react application, and are in the root directory of your newly created `create-react-app` application run the following commands: + + `npm install react-relay --save` + `npm run fetchRelaySchema` + `npm start` + +For development, any changes made to the GraphQL schema can be updated locally by running `npm run fetchRelaySchema` + ## Displaying Lint Output in the Editor >Note: this feature is available with `react-scripts@0.2.0` and higher. From bcfa494bac579e043804194932dad224f84139e2 Mon Sep 17 00:00:00 2001 From: Maxwell O'Roark Date: Wed, 14 Sep 2016 14:52:03 -0600 Subject: [PATCH 05/10] fixed a couple of typos in the readme.md --- template/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/template/README.md b/template/README.md index 377908f7dc8..eb091e2a680 100644 --- a/template/README.md +++ b/template/README.md @@ -13,7 +13,7 @@ You can find the most recent version of this guide [here](https://github.com/fac - [npm test](#npm-test) - [npm run build](#npm-run-build) - [npm run eject](#npm-run-eject) - - [npm run fetchRelaySchema](#fetch-relay-schema) + - [npm run fetchRelaySchema](#npm-run-fetchrelayschema) - [Relay & GraphQL Support](#relay-support) - [Displaying Lint Output in the Editor](#displaying-lint-output-in-the-editor) - [Installing a Dependency](#installing-a-dependency) @@ -147,7 +147,7 @@ You don’t have to ever use `eject`. The curated feature set is suitable for sm See documentation on [Relay Support](#relay-support) before running this command. -Fetches schema from an [introspection](http://graphql.org/learn/introspection/) query to your graphQL server. This query will require your `GRAPHQL_URL=` env variable to be set. +Fetches schema from an [introspection](http://graphql.org/learn/introspection/) query and writes it to a `schema.json` file in the root directory of your create-react-app application. ## Relay Support From d066591d32d033139a8542370930d50098f6a2ab Mon Sep 17 00:00:00 2001 From: Maxwell O'Roark Date: Wed, 14 Sep 2016 14:54:46 -0600 Subject: [PATCH 06/10] added bold to important clause --- template/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/README.md b/template/README.md index eb091e2a680..575b74cc27c 100644 --- a/template/README.md +++ b/template/README.md @@ -145,7 +145,7 @@ You don’t have to ever use `eject`. The curated feature set is suitable for sm ### `npm run fetchRelaySchema` -See documentation on [Relay Support](#relay-support) before running this command. +**Note: see documentation on [Relay Support](#relay-support) before running this command.** Fetches schema from an [introspection](http://graphql.org/learn/introspection/) query and writes it to a `schema.json` file in the root directory of your create-react-app application. From b05429e5713ede97dddde37a530e6719af7b6b82 Mon Sep 17 00:00:00 2001 From: Jon Saints Date: Thu, 15 Sep 2016 13:32:47 -0600 Subject: [PATCH 07/10] rename so env variable can be used client side --- config/relay/setup.js | 7 +-- template/README.md | 101 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 97 insertions(+), 11 deletions(-) diff --git a/config/relay/setup.js b/config/relay/setup.js index c978ded3c44..166eb7d3cf7 100644 --- a/config/relay/setup.js +++ b/config/relay/setup.js @@ -19,10 +19,11 @@ var relayIsEnabled = function() { var appPackageJson = require(paths.appPackageJson); if (appPackageJson && appPackageJson.dependencies && appPackageJson.dependencies['react-relay']) { - if (!process.env.GRAPHQL_URL) { - throw new Error("Relay requires a url to your graphql server\nSpecifiy this in a GRAPHQL_URL environment variable.\n\n"); + if (!process.env.REACT_APP_GRAPHQL_URL) { + throw new Error("Relay requires a url to your graphql server\nSpecifiy this in a REACT_APP_GRAPHQL_URL environment variable.\n\n"); } -console.log(paths.relaySchema); + + // FIXME if (!paths.relaySchema) { throw new Error("babel-relay-plugin requires a local copy of your graphql schema\nRun 'npm run fetchRelaySchema' to fetch it from the GRAPHQL_URL environment variable.\n\n"); } diff --git a/template/README.md b/template/README.md index 575b74cc27c..1dfe7abde5b 100644 --- a/template/README.md +++ b/template/README.md @@ -14,7 +14,7 @@ You can find the most recent version of this guide [here](https://github.com/fac - [npm run build](#npm-run-build) - [npm run eject](#npm-run-eject) - [npm run fetchRelaySchema](#npm-run-fetchrelayschema) -- [Relay & GraphQL Support](#relay-support) +- [Relay](#relay-support) - [Displaying Lint Output in the Editor](#displaying-lint-output-in-the-editor) - [Installing a Dependency](#installing-a-dependency) - [Importing a Component](#importing-a-component) @@ -151,17 +151,102 @@ Fetches schema from an [introspection](http://graphql.org/learn/introspection/) ## Relay Support -You can create a [Relay](https://facebook.github.io/relay/) application with create-react-app. You will need a GraphQL server1 to connect to and an environment variable that points to its location. The environment variable needs to be named `GRAPHQL_URL`. +You can create a [Relay](https://facebook.github.io/relay/) application with create-react-app. You will need a standalone GraphQL server ([CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) enabled, most likely) for your create-react-app to connect to. The steps for setting up the standalone GraphQL server are outside the scope of these docs. -1[CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) enabled, most likely. +To enable Relay in your create-react-app, create an app with create-react-app as you would normally: -Assuming you have set your environment variable, created your react application, and are in the root directory of your newly created `create-react-app` application run the following commands: +```cmd +create-react-app my-app +cd my-app +``` + +Then inside `my-app` and define an environment variable `REACT_APP_GRAPHQL_URL` with a value is the URL to your graphql server (`REACT_APP_GRAPHQL_URL=http://localhost:3001/graphql` for example). See [environment variables](#adding-custom-environment-variables) for more information. + +With your REACT_APP_GRAPHQL_URL environment variable set, run the following commands in the `my-app` directory: + +```cmd +npm install react-relay --save +npm run fetchRelaySchema +npm start +``` + +This will install the necessary packages for Relay support and configure the `babel-relay-plugin` for you. Woo! + +Next, add Relay to `my-app/src/index.js`. Setting the `DefaultNetworkLayer` is important. Here is an example: + +```js +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; +import './index.css'; +import Relay from 'react-relay'; +import { applyRouterMiddleware, Router, Route, /*Link,*/ browserHistory } from 'react-router'; +import useRelay from 'react-router-relay'; + + +const ViewerQueries = { + viewer: () => Relay.QL`query { viewer }` +}; + +Relay.injectNetworkLayer( + new Relay.DefaultNetworkLayer(process.env.REACT_APP_GRAPHQL_URL) +); + +ReactDOM.render( + + + + , + document.getElementById('root') +); +``` + +Next, add Components and Relay containers to your app. Here is an example of `my-app/src/App.js`. + +```js +import React, { Component } from 'react'; +import logo from './logo.svg'; +import './App.css'; +import Relay from 'react-relay'; + +class App extends Component { + render() { + return ( +
+
+ logo +

Welcome to React

+
+

+ To get started, edit src/App.js and save to reload. +

+

This came from Relay {this.props.viewer.id}

+
+ ); + } +} + +export default Relay.createContainer(App, { + fragments: { + viewer: () => Relay.QL` + fragment on User { + id + } + `, + }, +}); +``` - `npm install react-relay --save` - `npm run fetchRelaySchema` - `npm start` +>Note: Each time your the schema changes in your GrapQL server, you need to update your local copy of the schema by running `npm run fetchRelaySchema` -For development, any changes made to the GraphQL schema can be updated locally by running `npm run fetchRelaySchema` ## Displaying Lint Output in the Editor From 36e49c73fb6d6697e84235f1872718acbc9a8b7a Mon Sep 17 00:00:00 2001 From: Jon Saints Date: Thu, 15 Sep 2016 13:36:41 -0600 Subject: [PATCH 08/10] rename link to relay docs --- template/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/README.md b/template/README.md index 1dfe7abde5b..2e8e128274c 100644 --- a/template/README.md +++ b/template/README.md @@ -14,7 +14,6 @@ You can find the most recent version of this guide [here](https://github.com/fac - [npm run build](#npm-run-build) - [npm run eject](#npm-run-eject) - [npm run fetchRelaySchema](#npm-run-fetchrelayschema) -- [Relay](#relay-support) - [Displaying Lint Output in the Editor](#displaying-lint-output-in-the-editor) - [Installing a Dependency](#installing-a-dependency) - [Importing a Component](#importing-a-component) @@ -51,6 +50,7 @@ You can find the most recent version of this guide [here](https://github.com/fac - [Modulus](#modulus) - [Now](#now) - [Surge](#surge) +- [Relay & GraphQL Support](#relay-support) - [Something Missing?](#something-missing) ## Updating to New Releases From 56e2d92880c0e3fd4e898e6e6678bb1a8e941be4 Mon Sep 17 00:00:00 2001 From: Jon Saints Date: Fri, 16 Sep 2016 17:04:38 -0600 Subject: [PATCH 09/10] prep for pull request move relay to plugins --- bin/react-scripts.js | 1 - config/babel.dev.js | 6 +- config/babel.prod.js | 6 +- config/paths.js | 3 + config/relay/babelRelayPlugin.js | 6 - config/relay/setup.js | 39 ------ package.json | 4 +- plugins/relay/babelRelayPlugin.js | 18 +++ plugins/relay/index.js | 153 +++++++++++++++++++++++ scripts/build.js | 39 +++--- scripts/eject.js | 6 +- scripts/fetchRelaySchema.js | 38 ------ scripts/init.js | 3 +- scripts/start.js | 17 ++- scripts/utils/plugins.js | 29 +++++ template/README.md | 194 +++++++++++++++--------------- 16 files changed, 349 insertions(+), 213 deletions(-) delete mode 100644 config/relay/babelRelayPlugin.js delete mode 100644 config/relay/setup.js create mode 100644 plugins/relay/babelRelayPlugin.js create mode 100644 plugins/relay/index.js delete mode 100644 scripts/fetchRelaySchema.js create mode 100644 scripts/utils/plugins.js diff --git a/bin/react-scripts.js b/bin/react-scripts.js index e771b044f92..58381833957 100755 --- a/bin/react-scripts.js +++ b/bin/react-scripts.js @@ -8,7 +8,6 @@ case 'build': case 'eject': case 'start': case 'test': -case 'fetchRelaySchema': var result = spawn.sync( 'node', [require.resolve('../scripts/' + script)].concat(args), diff --git a/config/babel.dev.js b/config/babel.dev.js index 0053ed25b06..91a539464d8 100644 --- a/config/babel.dev.js +++ b/config/babel.dev.js @@ -11,7 +11,7 @@ var path = require('path'); var findCacheDir = require('find-cache-dir'); -var relaySetup = require('./relay/setup'); +var relayPlugin = require('../plugins/relay'); module.exports = { // Don't try to find .babelrc because we want to force this configuration. @@ -49,7 +49,7 @@ module.exports = { }; // optional relay support https://facebook.github.io/relay -if (relaySetup.relayIsEnabled()) { +if (relayPlugin.isEnabled()) { // relay QL babel transform needs to run before react https://facebook.github.io/relay/docs/guides-babel-plugin.html#react-native-configuration - module.exports.plugins.unshift(require.resolve('./relay/babelRelayPlugin')); + module.exports.plugins.unshift(require.resolve('../plugins/relay/babelRelayPlugin')); } diff --git a/config/babel.prod.js b/config/babel.prod.js index 768258ce577..6cf95ca7c3d 100644 --- a/config/babel.prod.js +++ b/config/babel.prod.js @@ -10,7 +10,7 @@ // @remove-on-eject-end var path = require('path'); -var relaySetup = require('./relay/setup'); +var relayPlugin = require('../plugins/relay'); module.exports = { // Don't try to find .babelrc because we want to force this configuration. @@ -50,7 +50,7 @@ module.exports = { }; // optional relay support https://facebook.github.io/relay -if (relaySetup.relayIsEnabled()) { +if (relayPlugin.isEnabled()) { // relay QL babel transform needs to run before react https://facebook.github.io/relay/docs/guides-babel-plugin.html#react-native-configuration - module.exports.plugins.unshift(require.resolve('./relay/babelRelayPlugin')); + module.exports.plugins.unshift(require.resolve('../plugins/relay/babelRelayPlugin')); } diff --git a/config/paths.js b/config/paths.js index c46fdd64d4a..61aaca1ab70 100644 --- a/config/paths.js +++ b/config/paths.js @@ -41,6 +41,7 @@ module.exports = { relaySchema: resolveApp('schema.json'), appNodeModules: resolveApp('node_modules'), ownNodeModules: resolveApp('node_modules'), + plugins: resolveApp('plugins'), nodePaths: nodePaths }; @@ -60,6 +61,7 @@ module.exports = { appNodeModules: resolveApp('node_modules'), // this is empty with npm3 but node resolution searches higher anyway: ownNodeModules: resolveOwn('../node_modules'), + plugins: resolveApp('plugins'), nodePaths: nodePaths }; // @remove-on-eject-end @@ -74,6 +76,7 @@ module.exports = { relaySchema: resolveOwn('../schema.json'), appNodeModules: resolveOwn('../node_modules'), ownNodeModules: resolveOwn('../node_modules'), + plugins: resolveOwn('../plugins'), nodePaths: nodePaths }; // @remove-on-publish-end diff --git a/config/relay/babelRelayPlugin.js b/config/relay/babelRelayPlugin.js deleted file mode 100644 index f9a47d3744f..00000000000 --- a/config/relay/babelRelayPlugin.js +++ /dev/null @@ -1,6 +0,0 @@ -var paths = require('../paths'); -var getbabelRelayPlugin = require('babel-relay-plugin'); - -var schema = require(paths.relaySchema); - -module.exports = getbabelRelayPlugin(schema.data); diff --git a/config/relay/setup.js b/config/relay/setup.js deleted file mode 100644 index 166eb7d3cf7..00000000000 --- a/config/relay/setup.js +++ /dev/null @@ -1,39 +0,0 @@ -// @remove-on-eject-begin -/** - * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @relay - */ -// @remove-on-eject-end - -var paths = require('../paths'); - -/** - * relay requires 'react-relay' install and in package.json, GRAPHQL_URL env variable set to retrieve local copy of schema.json resulting from `npm run fetchRelaySchema` - */ -var relayIsEnabled = function() { - var appPackageJson = require(paths.appPackageJson); - if (appPackageJson && appPackageJson.dependencies && appPackageJson.dependencies['react-relay']) { - - if (!process.env.REACT_APP_GRAPHQL_URL) { - throw new Error("Relay requires a url to your graphql server\nSpecifiy this in a REACT_APP_GRAPHQL_URL environment variable.\n\n"); - } - - // FIXME - if (!paths.relaySchema) { - throw new Error("babel-relay-plugin requires a local copy of your graphql schema\nRun 'npm run fetchRelaySchema' to fetch it from the GRAPHQL_URL environment variable.\n\n"); - } - - return true; - } - - return false -} - -module.exports = { - relayIsEnabled: relayIsEnabled, -}; diff --git a/package.json b/package.json index 0542789c691..b8befb611a9 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "bin", "config", "scripts", - "template" + "template", + "plugins" ], "bin": { "react-scripts": "./bin/react-scripts.js" @@ -73,7 +74,6 @@ "path-exists": "3.0.0", "postcss-loader": "0.11.1", "promise": "7.1.1", - "react-relay": "0.9.3", "recursive-readdir": "2.0.0", "rimraf": "2.5.4", "strip-ansi": "3.0.1", diff --git a/plugins/relay/babelRelayPlugin.js b/plugins/relay/babelRelayPlugin.js new file mode 100644 index 00000000000..491e858bde0 --- /dev/null +++ b/plugins/relay/babelRelayPlugin.js @@ -0,0 +1,18 @@ +// @remove-on-eject-begin +/** + * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @relay + */ +// @remove-on-eject-end + +var paths = require('../../config/paths'); +var getbabelRelayPlugin = require('babel-relay-plugin'); + +var schema = require(paths.relaySchema); + +module.exports = getbabelRelayPlugin(schema.data); diff --git a/plugins/relay/index.js b/plugins/relay/index.js new file mode 100644 index 00000000000..10182920e0a --- /dev/null +++ b/plugins/relay/index.js @@ -0,0 +1,153 @@ +// @remove-on-eject-begin +/** + * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @relay + */ +// @remove-on-eject-end + +var paths = require('../../config/paths'); +var chalk = require('chalk'); +var fetch = require('node-fetch'); +var graphQlutilities = require('graphql/utilities'); +var fs = require('fs'); + +/** + * relay requires 'react-relay' install and in package.json, GRAPHQL_URL env variable set to retrieve local copy of schema.json resulting from `npm run fetchRelaySchema` + */ +var isEnabled = function() { + var appPackageJson = require(paths.appPackageJson); + if (appPackageJson && appPackageJson.dependencies && appPackageJson.dependencies['react-relay']) { + + return true; + } + + return false +} + +var requireGraphQlConfig = function() { + return new Promise((resolve, reject) => { + //TODO we could use graphql-config package here instead + + // check that required env var REACT_APP_GRAPHQL_URL is setup + if (!process.env.REACT_APP_GRAPHQL_URL) { + // console.log(chalk.red('Relay requires a url to your graphql server')); + // console.log('Specifiy this in a ' + chalk.cyan('REACT_APP_GRAPHQL_URL') + ' environment variable.'); + // console.log(); + // process.exit(1); + + var errorMessage = chalk.red('Relay requires a url to your graphql server\n') + + 'Specifiy this in a ' + chalk.cyan('REACT_APP_GRAPHQL_URL') + ' environment variable.'; + reject(new Error(errorMessage)); + } + + console.log("Relay support - graphql configured successfully"); + resolve(); + }) +} + +var validateSchemaJson = function() { + return new Promise((resolve, reject) => { + // check that schema.json is there and is readable + try { + var schemaFileContents = fs.readFileSync(paths.relaySchema); + } catch (err) { + // console.log(chalk.red('babel-relay-plugin requires a local copy of your graphql schema')); + // console.log('Run ' + chalk.cyan('npm run fetchRelaySchema') + ' to fetch it from the ' + chalk.cyan('REACT_APP_GRAPHQL_URL') + ' environment variable.'); + // console.log(); + // console.error(err); + // console.log(); + // process.exit(1) + var errorMessage = chalk.red('babel-relay-plugin requires a local copy of your graphql schema\n') + + 'Run ' + chalk.cyan('npm run fetchRelaySchema') + ' to fetch it from the ' + chalk.cyan('REACT_APP_GRAPHQL_URL') + ' environment variable.'; + reject(new Error(errorMessage)); + } + + // check that schema.json is valid json + try { + var schemaJSON = JSON.parse(schemaFileContents); + } catch (err) { + // console.log(chalk.red('JSON parsing of the contents of ' + chalk.cyan(paths.relaySchema) + ' failed.')); + // console.log('Check the contents of ' + chalk.cyan(paths.relaySchema) + '. It does not appear to be valid json'); + // console.log('Also try running ' + chalk.cyan('npm run fetchRelaySchema') + ' to re-fetch the schema.json from the ' + chalk.cyan('REACT_APP_GRAPHQL_URL') + ' environment variable.'); + // console.log(); + // console.error(err); + // console.log(); + // process.exit(1) + var errorMessage = chalk.red('JSON parsing of the contents of ' + chalk.cyan(paths.relaySchema) + ' failed.\n') + + 'Check the contents of ' + chalk.cyan(paths.relaySchema) + '. It does not appear to be valid json\n' + + 'Also try running ' + chalk.cyan('npm run fetchRelaySchema') + ' to re-fetch the schema.json from the ' + chalk.cyan('REACT_APP_GRAPHQL_URL') + ' environment variable.'; + reject(new Error(errorMessage)); + } + + // check contents of schema.json has valid graphql schema + try { + var graphQLSchema = graphQlutilities.buildClientSchema(schemaJSON.data); + } catch (err) { + // console.log(chalk.red('Could not parse the contents of schema.json into a valid graphql schema that is compatiable with this version of Relay and babel-relay-plugin')); + // console.log('Upgrading graphql library on your server may be a solution.'); + // console.log(); + // console.error(err); + // console.log(); + // process.exit(1) + var errorMessage = chalk.red('Could not parse the contents of schema.json into a valid graphql schema that is compatiable with this version of Relay and babel-relay-plugin\n') + + 'Upgrading graphql library on your server may be a solution.'; + reject(new Error(errorMessage)); + } + + console.log('Relay support - schema.json is found and valid'); + resolve(); + }); +} + +// retreive JSON of graaphql schema via introspection for Babel Relay Plugin to use +var fetchRelaySchema = function() { + return fetch(process.env.REACT_APP_GRAPHQL_URL, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({'query': graphQlutilities.introspectionQuery}), + }) + .then(res => res.json()).then(schemaJSON => { + // verify that the schemaJSON is valid a graphQL Schema + var graphQLSchema = graphQlutilities.buildClientSchema(schemaJSON.data); + // Save relay compatible schema.json + fs.writeFileSync(paths.relaySchema, JSON.stringify(schemaJSON, null, 2)); + + // Save user readable schema.graphql + fs.writeFileSync(paths.relaySchema.replace('.json','.graphql'), graphQlutilities.printSchema(graphQLSchema)); + + console.log('Relay support - fetch schema.json from ' + chalk.cyan(process.env.REACT_APP_GRAPHQL_URL)); + }); +} + +// build does not fetch the relay schema, only uses local copy of shema.js. +// this helps, but does not guaruntee that builds, dev, and tests use the same version of the schema. +var build = function() { + return requireGraphQlConfig() + .then(validateSchemaJson) + .then(() => { + console.log(chalk.green('Relay support built successfully!')); + }) +} + +var start = function() { + return requireGraphQlConfig() + .then(fetchRelaySchema) + .then(validateSchemaJson) + .then(() => { + console.log(chalk.green('Relay support enabled successfully!')); + }) +} + +module.exports = { + isEnabled: isEnabled, + build: build, + start: start +}; diff --git a/scripts/build.js b/scripts/build.js index e60b554466f..b981b04773c 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -23,6 +23,7 @@ var config = require('../config/webpack.config.prod'); var paths = require('../config/paths'); var recursive = require('recursive-readdir'); var stripAnsi = require('strip-ansi'); +var plugins = require('./utils/plugins'); // Input: /User/dan/app/build/static/js/main.82be8.js // Output: /static/js/main.js @@ -51,23 +52,31 @@ function getDifferenceLabel(currentSize, previousSize) { // First, read the current file sizes in build directory. // This lets us display how much they changed later. -recursive(paths.appBuild, (err, fileNames) => { - var previousSizeMap = (fileNames || []) - .filter(fileName => /\.(js|css)$/.test(fileName)) - .reduce((memo, fileName) => { - var contents = fs.readFileSync(fileName); - var key = removeFileNameHash(fileName); - memo[key] = gzipSize(contents); - return memo; - }, {}); +plugins.build() + .then(() => { + recursive(paths.appBuild, (err, fileNames) => { + var previousSizeMap = (fileNames || []) + .filter(fileName => /\.(js|css)$/.test(fileName)) + .reduce((memo, fileName) => { + var contents = fs.readFileSync(fileName); + var key = removeFileNameHash(fileName); + memo[key] = gzipSize(contents); + return memo; + }, {}); - // Remove all content but keep the directory so that - // if you're in it, you don't end up in Trash - rimrafSync(paths.appBuild + '/*'); + // Remove all content but keep the directory so that + // if you're in it, you don't end up in Trash + rimrafSync(paths.appBuild + '/*'); - // Start the webpack build - build(previousSizeMap); -}); + // Start the webpack build + build(previousSizeMap); + }); + }) + .catch((err) => { + console.error(err); + console.log(); + process.exit(1) + }); // Print a detailed summary of build files. function printFileSizes(stats, previousSizeMap) { diff --git a/scripts/eject.js b/scripts/eject.js index 3e5e18af387..58080c47493 100644 --- a/scripts/eject.js +++ b/scripts/eject.js @@ -46,7 +46,9 @@ prompt( path.join('scripts', 'start.js'), path.join('scripts', 'utils', 'chrome.applescript'), path.join('scripts', 'utils', 'prompt.js'), - path.join('scripts', 'utils', 'WatchMissingNodeModulesPlugin.js') + path.join('scripts', 'utils', 'WatchMissingNodeModulesPlugin.js'), + path.join('plugins', 'relay', 'index.js'), + path.join('plugins', 'relay', 'babelRelayPlugin.js') ]; // Ensure that the app folder is clean and we won't override any files @@ -68,6 +70,8 @@ prompt( fs.mkdirSync(path.join(appPath, 'config', 'jest')); fs.mkdirSync(path.join(appPath, 'scripts')); fs.mkdirSync(path.join(appPath, 'scripts', 'utils')); + fs.mkdirSync(path.join(appPath, 'plugins')); + fs.mkdirSync(path.join(appPath, 'plugins', 'relay')); files.forEach(function(file) { console.log('Copying ' + file + ' to ' + appPath); diff --git a/scripts/fetchRelaySchema.js b/scripts/fetchRelaySchema.js deleted file mode 100644 index 6443e017f0c..00000000000 --- a/scripts/fetchRelaySchema.js +++ /dev/null @@ -1,38 +0,0 @@ -var fetch = require('node-fetch'); -var fs = require('fs'); -var graphQlutilities = require('graphql/utilities'); - -var buildClientSchema = graphQlutilities.buildClientSchema; -var introspectionQuery = graphQlutilities.introspectionQuery; -var printSchema = graphQlutilities.printSchema; - -var path = require('path'); -var paths = require('../config/paths') -var SERVER = process.env.GRAPHQL_URL; -console.log(SERVER) -// Save JSON of full schema introspection for Babel Relay Plugin to use -fetch(`${SERVER}`, { - method: 'POST', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({'query': introspectionQuery}), -}) -.then(res => res.json()).then(schemaJSON => { - fs.writeFileSync( - `${paths.relaySchema}`, - JSON.stringify(schemaJSON, null, 2) - ); - - // Save user readable type system shorthand of schema - // var graphQLSchema = buildClientSchema(schemaJSON.data); - // fs.writeFileSync( - // `${paths.relaySchema}/schema.graphql`, - // printSchema(graphQLSchema) - // ); -}) -.catch((err)=>{ - console.log(err) - console.log(err.stack) -}) diff --git a/scripts/init.js b/scripts/init.js index ce708690571..e440a830699 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -27,8 +27,7 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { 'start': 'react-scripts start', 'build': 'react-scripts build', 'test': 'react-scripts test --env=jsdom', - 'eject': 'react-scripts eject', - 'fetchRelaySchema': 'react-scripts fetchRelaySchema' + 'eject': 'react-scripts eject' }; fs.writeFileSync( diff --git a/scripts/start.js b/scripts/start.js index 32f20c25fcf..fff81d9c394 100644 --- a/scripts/start.js +++ b/scripts/start.js @@ -23,6 +23,7 @@ var detect = require('detect-port'); var prompt = require('./utils/prompt'); var config = require('../config/webpack.config.dev'); var paths = require('../config/paths'); +var plugins = require('./utils/plugins'); // Tools like Cloud9 rely on this. var DEFAULT_PORT = process.env.PORT || 3000; @@ -180,7 +181,7 @@ function onProxyError(proxy) { ' from ' + chalk.cyan(host) + ' to ' + chalk.cyan(proxy) + '.' ); console.log( - 'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' + + 'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' + chalk.cyan(err.code) + ').' ); console.log(); @@ -190,7 +191,7 @@ function onProxyError(proxy) { if (res.writeHead && !res.headersSent) { res.writeHead(500); } - res.end('Proxy error: Could not proxy request ' + req.url + ' from ' + + res.end('Proxy error: Could not proxy request ' + req.url + ' from ' + host + ' to ' + proxy + ' (' + err.code + ').' ); } @@ -304,8 +305,16 @@ function runDevServer(port, protocol) { function run(port) { var protocol = process.env.HTTPS === 'true' ? "https" : "http"; - setupCompiler(port, protocol); - runDevServer(port, protocol); + plugins.start() + .then(() => { + setupCompiler(port, protocol); + runDevServer(port, protocol); + }) + .catch((err) => { + console.error(err); + console.log(); + process.exit(1) + }); } // We attempt to use the default port but if it is busy, we offer the user to diff --git a/scripts/utils/plugins.js b/scripts/utils/plugins.js new file mode 100644 index 00000000000..62ac66b3494 --- /dev/null +++ b/scripts/utils/plugins.js @@ -0,0 +1,29 @@ +// @remove-on-eject-begin +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +// @remove-on-eject-end + +var relayPlugin = require('../../plugins/relay'); + +var start = function() { + return Promise.all([ + (relayPlugin.isEnabled()) ? relayPlugin.start() : false, + ]) +} + +var build = function() { + return Promise.all([ + (relayPlugin.isEnabled()) ? relayPlugin.build() : false, + ]) +} + +module.exports = { + start: start, + build: build, +} diff --git a/template/README.md b/template/README.md index 2e8e128274c..1369d116a91 100644 --- a/template/README.md +++ b/template/README.md @@ -149,105 +149,6 @@ You don’t have to ever use `eject`. The curated feature set is suitable for sm Fetches schema from an [introspection](http://graphql.org/learn/introspection/) query and writes it to a `schema.json` file in the root directory of your create-react-app application. -## Relay Support - -You can create a [Relay](https://facebook.github.io/relay/) application with create-react-app. You will need a standalone GraphQL server ([CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) enabled, most likely) for your create-react-app to connect to. The steps for setting up the standalone GraphQL server are outside the scope of these docs. - -To enable Relay in your create-react-app, create an app with create-react-app as you would normally: - -```cmd -create-react-app my-app -cd my-app -``` - -Then inside `my-app` and define an environment variable `REACT_APP_GRAPHQL_URL` with a value is the URL to your graphql server (`REACT_APP_GRAPHQL_URL=http://localhost:3001/graphql` for example). See [environment variables](#adding-custom-environment-variables) for more information. - -With your REACT_APP_GRAPHQL_URL environment variable set, run the following commands in the `my-app` directory: - -```cmd -npm install react-relay --save -npm run fetchRelaySchema -npm start -``` - -This will install the necessary packages for Relay support and configure the `babel-relay-plugin` for you. Woo! - -Next, add Relay to `my-app/src/index.js`. Setting the `DefaultNetworkLayer` is important. Here is an example: - -```js -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; -import './index.css'; -import Relay from 'react-relay'; -import { applyRouterMiddleware, Router, Route, /*Link,*/ browserHistory } from 'react-router'; -import useRelay from 'react-router-relay'; - - -const ViewerQueries = { - viewer: () => Relay.QL`query { viewer }` -}; - -Relay.injectNetworkLayer( - new Relay.DefaultNetworkLayer(process.env.REACT_APP_GRAPHQL_URL) -); - -ReactDOM.render( - - - - , - document.getElementById('root') -); -``` - -Next, add Components and Relay containers to your app. Here is an example of `my-app/src/App.js`. - -```js -import React, { Component } from 'react'; -import logo from './logo.svg'; -import './App.css'; -import Relay from 'react-relay'; - -class App extends Component { - render() { - return ( -
-
- logo -

Welcome to React

-
-

- To get started, edit src/App.js and save to reload. -

-

This came from Relay {this.props.viewer.id}

-
- ); - } -} - -export default Relay.createContainer(App, { - fragments: { - viewer: () => Relay.QL` - fragment on User { - id - } - `, - }, -}); -``` - ->Note: Each time your the schema changes in your GrapQL server, you need to update your local copy of the schema by running `npm run fetchRelaySchema` - - ## Displaying Lint Output in the Editor >Note: this feature is available with `react-scripts@0.2.0` and higher. @@ -1006,6 +907,101 @@ Install the Surge CLI if you haven't already by running `npm install -g surge`. Note that in order to support routers that use html5 `pushState` API, you may want to rename the `index.html` in your build folder to `200.html` before deploying to Surge. This [ensures that every URL falls back to that file](https://surge.sh/help/adding-a-200-page-for-client-side-routing). +## Relay Support + +You can create a [Relay](https://facebook.github.io/relay/) application with create-react-app. You will need a standalone GraphQL server ([CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) enabled, most likely) for your create-react-app to connect to. The steps for setting up the standalone GraphQL server are outside the scope of these docs. + +To enable Relay in your create-react-app, install `react-relay` + +```cmd +npm install react-relay --save +``` + +Then define an environment variable `REACT_APP_GRAPHQL_URL` with a value that is the URL to your graphql server (for example `REACT_APP_GRAPHQL_URL=http://localhost:3001/graphql`). See [environment variables](#adding-custom-environment-variables) for more information. + +With your REACT_APP_GRAPHQL_URL environment variable defined, start your app. This could be as simple as: + +```cmd +REACT_APP_GRAPHQL_URL=http://localhost:3001/graphql npm start +``` + +This will configure the `babel-relay-plugin` for you and fetch your graphql schema. Woo! + +Next, add Relay to `my-app/src/index.js`. Setting the `DefaultNetworkLayer` is important. Here is an example: + +```js +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; +import './index.css'; +import Relay from 'react-relay'; +import { applyRouterMiddleware, Router, Route, /*Link,*/ browserHistory } from 'react-router'; +import useRelay from 'react-router-relay'; + + +const ViewerQueries = { + viewer: () => Relay.QL`query { viewer }` +}; + +Relay.injectNetworkLayer( + new Relay.DefaultNetworkLayer(process.env.REACT_APP_GRAPHQL_URL) +); + +ReactDOM.render( + + + + , + document.getElementById('root') +); +``` + +Next, add Components and Relay containers to your app. Here is an example of `my-app/src/App.js`. + +```js +import React, { Component } from 'react'; +import logo from './logo.svg'; +import './App.css'; +import Relay from 'react-relay'; + +class App extends Component { + render() { + return ( +
+
+ logo +

Welcome to React

+
+

+ To get started, edit src/App.js and save to reload. +

+

This came from Relay {this.props.viewer.id}

+
+ ); + } +} + +export default Relay.createContainer(App, { + fragments: { + viewer: () => Relay.QL` + fragment on User { + id + } + `, + }, +}); +``` + +>Note: Each time your the schema on your remote graphql server changes, you need to restart your local development server with `npm start`. This will fetch the latest version of your graphql schema so `babel-relay-plugin` can transform Relay.QL queries in your components. + ## Something Missing? If you have ideas for more “How To” recipes that should be on this page, [let us know](https://github.com/facebookincubator/create-react-app/issues) or [contribute some!](https://github.com/facebookincubator/create-react-app/edit/master/template/README.md) From 2774df0ba251bdeddb646168440c23493a39f321 Mon Sep 17 00:00:00 2001 From: Jon Saints Date: Mon, 19 Sep 2016 11:03:55 -0600 Subject: [PATCH 10/10] plugins need to be included on eject --- scripts/eject.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/eject.js b/scripts/eject.js index 58080c47493..86c7692f253 100644 --- a/scripts/eject.js +++ b/scripts/eject.js @@ -46,6 +46,7 @@ prompt( path.join('scripts', 'start.js'), path.join('scripts', 'utils', 'chrome.applescript'), path.join('scripts', 'utils', 'prompt.js'), + path.join('scripts', 'utils', 'plugins.js'), path.join('scripts', 'utils', 'WatchMissingNodeModulesPlugin.js'), path.join('plugins', 'relay', 'index.js'), path.join('plugins', 'relay', 'babelRelayPlugin.js')