Skip to content

Commit

Permalink
Add loader for .graqhql files
Browse files Browse the repository at this point in the history
  • Loading branch information
patrick91 authored and yoiang committed May 2, 2018
1 parent 4324ef1 commit 983002c
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 42 deletions.
18 changes: 18 additions & 0 deletions packages/react-scripts/config/jest/graphqlTransform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// @remove-on-eject-begin
/**
* Copyright (c) 2018-present, Facebook, Inc.
* Copyright (c) 2016 Remind
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// @remove-on-eject-end
'use strict';

const loader = require('graphql-tag/loader');

module.exports = {
process(src) {
return loader.call({ cacheable() {} }, src);
},
};
5 changes: 5 additions & 0 deletions packages/react-scripts/config/webpack.config.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ module.exports = {
},
],
},
// The GraphQL loader preprocesses GraphQL queries in .graphql files.
{
test: /\.(graphql)$/,
loader: 'graphql-tag/loader',
},
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ describe('Integration', () => {
).to.match(/#feature-css-inclusion\{background:.+;color:.+}/);
});

it('graphql files inclusion', async () => {
const doc = await initDOM('graphql-inclusion');
const children = doc.getElementById('graphql-inclusion').children;

// .graphql
expect(children[0].textContent.replace(/\s/g, '')).to.equal(
'{"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","variableDefinitions":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"test"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"test"},"value":{"kind":"StringValue","value":"test","block":false}}],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"test"},"arguments":[],"directives":[]}]}}]}}],"loc":{"start":0,"end":40,"source":{"body":"{\\ntest(test:\\"test\\"){\\ntest\\n}\\n}\\n","name":"GraphQLrequest","locationOffset":{"line":1,"column":1}}}}'
);
});

it('image inclusion', async () => {
const doc = await initDOM('image-inclusion');

Expand Down
101 changes: 62 additions & 39 deletions packages/react-scripts/fixtures/kitchensink/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,114 +52,137 @@ class App extends Component {
const feature = window.location.hash.slice(1);
switch (feature) {
case 'array-destructuring':
import(
'./features/syntax/ArrayDestructuring'
).then(f => this.setFeature(f.default));
import('./features/syntax/ArrayDestructuring').then(f =>
this.setFeature(f.default)
);
break;
case 'array-spread':
import('./features/syntax/ArraySpread').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'async-await':
import('./features/syntax/AsyncAwait').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'class-properties':
import('./features/syntax/ClassProperties').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'computed-properties':
import(
'./features/syntax/ComputedProperties'
).then(f => this.setFeature(f.default));
import('./features/syntax/ComputedProperties').then(f =>
this.setFeature(f.default)
);
break;
case 'css-inclusion':
import('./features/webpack/CssInclusion').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'custom-interpolation':
import(
'./features/syntax/CustomInterpolation'
).then(f => this.setFeature(f.default));
import('./features/syntax/CustomInterpolation').then(f =>
this.setFeature(f.default)
);
break;
case 'default-parameters':
import('./features/syntax/DefaultParameters').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'destructuring-and-await':
import(
'./features/syntax/DestructuringAndAwait'
).then(f => this.setFeature(f.default));
import('./features/syntax/DestructuringAndAwait').then(f =>
this.setFeature(f.default)
);
break;
case 'file-env-variables':
import('./features/env/FileEnvVariables').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'generators':
import('./features/syntax/Generators').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'graphql-inclusion':
import('./features/webpack/GraphQLInclusion').then(f =>
this.setFeature(f.default)
);
break;
case 'image-inclusion':
import('./features/webpack/ImageInclusion').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'json-inclusion':
import('./features/webpack/JsonInclusion').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'linked-modules':
import('./features/webpack/LinkedModules').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'node-path':
import('./features/env/NodePath').then(f => this.setFeature(f.default));
break;
case 'no-ext-inclusion':
import('./features/webpack/NoExtInclusion').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'object-destructuring':
import(
'./features/syntax/ObjectDestructuring'
).then(f => this.setFeature(f.default));
import('./features/syntax/ObjectDestructuring').then(f =>
this.setFeature(f.default)
);
break;
case 'object-spread':
import('./features/syntax/ObjectSpread').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'promises':
import('./features/syntax/Promises').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'public-url':
import('./features/env/PublicUrl').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'rest-and-default':
import('./features/syntax/RestAndDefault').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'rest-parameters':
import('./features/syntax/RestParameters').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'shell-env-variables':
import('./features/env/ShellEnvVariables').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'svg-inclusion':
import('./features/webpack/SvgInclusion').then(f =>
this.setFeature(f.default));
this.setFeature(f.default)
);
break;
case 'template-interpolation':
import(
'./features/syntax/TemplateInterpolation'
).then(f => this.setFeature(f.default));
import('./features/syntax/TemplateInterpolation').then(f =>
this.setFeature(f.default)
);
break;
case 'unknown-ext-inclusion':
import(
'./features/webpack/UnknownExtInclusion'
).then(f => this.setFeature(f.default));
import('./features/webpack/UnknownExtInclusion').then(f =>
this.setFeature(f.default)
);
break;
case 'expand-env-variables':
import('./features/env/ExpandEnvVariables').then(f =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import A from './assets/graphql.graphql';

export default () => (
<p id="graphql-inclusion">
<span>{JSON.stringify(A)}</span>
</p>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import ReactDOM from 'react-dom';
import GraphQLInclusion from './GraphQLInclusion';

describe('graphql files inclusion', () => {
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<GraphQLInclusion />, div);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
test(test: "test") {
test
}
}
2 changes: 2 additions & 0 deletions packages/react-scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
"file-loader": "0.11.2",
"fork-ts-checker-webpack-plugin": "^0.2.8",
"fs-extra": "3.0.1",
"graphql": "0.12.3",
"graphql-tag": "2.6.1",
"html-webpack-plugin": "2.29.0",
"jest": "22.1.4",
"object-assign": "4.1.1",
Expand Down
3 changes: 2 additions & 1 deletion packages/react-scripts/scripts/utils/createJestConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ module.exports = (resolve, rootDir, isEjecting) => {
: resolve('config/jest/babelTransform.js'),
'^.+\\.tsx?$': resolve('config/jest/typescriptTransform.js'),
'^.+\\.css$': resolve('config/jest/cssTransform.js'),
'^(?!.*\\.(js|jsx|mjs|css|json)$)': resolve(
'^.+\\.(graphql)$': resolve('config/jest/graphqlTransform.js'),
'^(?!.*\\.(js|jsx|mjs|css|json|graphql)$)': resolve(
'config/jest/fileTransform.js'
),
},
Expand Down
33 changes: 31 additions & 2 deletions packages/react-scripts/template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ You can find the most recent version of this guide [here](https://github.com/fac
- [Post-Processing CSS](#post-processing-css)
- [Adding a CSS Preprocessor (Sass, Less etc.)](#adding-a-css-preprocessor-sass-less-etc)
- [Adding Images, Fonts, and Files](#adding-images-fonts-and-files)
- [Adding GraphQL files](#adding-graphql-files)
- [Using the `public` Folder](#using-the-public-folder)
- [Changing the HTML](#changing-the-html)
- [Adding Assets Outside of the Module System](#adding-assets-outside-of-the-module-system)
Expand Down Expand Up @@ -299,7 +300,7 @@ In the WebStorm menu `Run` select `Edit Configurations...`. Then click `+` and s
Start your app by running `npm start`, then press `^D` on macOS or `F9` on Windows and Linux or click the green debug icon to start debugging in WebStorm.

The same way you can debug your application in IntelliJ IDEA Ultimate, PhpStorm, PyCharm Pro, and RubyMine.
The same way you can debug your application in IntelliJ IDEA Ultimate, PhpStorm, PyCharm Pro, and RubyMine.

## Formatting Code Automatically

Expand Down Expand Up @@ -695,6 +696,34 @@ Please be advised that this is also a custom feature of Webpack.
**It is not required for React** but many people enjoy it (and React Native uses a similar mechanism for images).<br>
An alternative way of handling static assets is described in the next section.

## Adding GraphQL files

> Note: this feature is available with [email protected] and higher.
If you are using GraphQL, you can **`import` GraphQL files in a JavaScript module**.

By importing GraphQL queries instead of using a [template tag](https://github.com/apollographql/graphql-tag), they are preprocessed at build time. This eliminates the need to process them on the client at run time. It also allows you to separate your GraphQL queries from your code. You can put a GraphQL query in a file with a `.graphql` extension.

Here is an example:

```js
// query.graphql
{
githubStats(repository: "facebook/react") {
stars
}
}

// foo.js

import query from './query.graphql';

console.log(query);
// {
// "kind": "Document",
// ...
```

## Using the `public` Folder

>Note: this feature is available with `[email protected]` and higher.
Expand Down Expand Up @@ -1961,7 +1990,7 @@ If you’re using [Apache HTTP Server](https://httpd.apache.org/), you need to c
RewriteRule ^ index.html [QSA,L]
```
It will get copied to the `build` folder when you run `npm run build`.
It will get copied to the `build` folder when you run `npm run build`.
If you’re using [Apache Tomcat](http://tomcat.apache.org/), you need to follow [this Stack Overflow answer](https://stackoverflow.com/a/41249464/4878474).
Expand Down

0 comments on commit 983002c

Please sign in to comment.