Skip to content

Commit 9a2100e

Browse files
petetntakstuhl
authored andcommitted
Add loader for .graphql files (facebook#3909)
* Add graphql loader to webpack config Signed-off-by: petetnt <pete.a.nykanen@gmail.com> * Update README.md Signed-off-by: petetnt <pete.a.nykanen@gmail.com> * Update react-scripts README.md Signed-off-by: petetnt <pete.a.nykanen@gmail.com> * Add graphql jest transform Signed-off-by: petetnt <pete.a.nykanen@gmail.com> * Add integration tests, pin versions in package.json Signed-off-by: petetnt <pete.a.nykanen@gmail.com> * Tests expect regexp matchers Signed-off-by: petetnt <pete.a.nykanen@gmail.com> * Use strict equal test instead Signed-off-by: petetnt <pete.a.nykanen@gmail.com> * Escaping is hard Signed-off-by: petetnt <pete.a.nykanen@gmail.com> * Add comment for signifying a different file * Update docs * Fix jest config * Remove node_modules exclusion * Update README.md * Inline graphql jest transform Signed-off-by: petetnt <pete.a.nykanen@gmail.com> * Update copyright header Signed-off-by: petetnt <pete.a.nykanen@gmail.com> * Use .graphql extension only Signed-off-by: petetnt <pete.a.nykanen@gmail.com>
1 parent b5041a7 commit 9a2100e

File tree

11 files changed

+113
-1
lines changed

11 files changed

+113
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// @remove-on-eject-begin
2+
/**
3+
* Copyright (c) 2018-present, Facebook, Inc.
4+
* Copyright (c) 2016 Remind
5+
*
6+
* This source code is licensed under the MIT license found in the
7+
* LICENSE file in the root directory of this source tree.
8+
*/
9+
// @remove-on-eject-end
10+
'use strict';
11+
12+
const loader = require('graphql-tag/loader');
13+
14+
module.exports = {
15+
process(src) {
16+
return loader.call({ cacheable() {} }, src);
17+
},
18+
};

packages/react-scripts/config/webpack.config.dev.js

+5
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,11 @@ module.exports = {
278278
},
279279
],
280280
},
281+
// The GraphQL loader preprocesses GraphQL queries in .graphql files.
282+
{
283+
test: /\.(graphql)$/,
284+
loader: 'graphql-tag/loader',
285+
},
281286
// "file" loader makes sure those assets get served by WebpackDevServer.
282287
// When you `import` an asset, you get its (virtual) filename.
283288
// In production, they would get copied to the `build` folder.

packages/react-scripts/config/webpack.config.prod.js

+5
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,11 @@ module.exports = {
320320
),
321321
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
322322
},
323+
// The GraphQL loader preprocesses GraphQL queries in .graphql files.
324+
{
325+
test: /\.(graphql)$/,
326+
loader: 'graphql-tag/loader',
327+
},
323328
// "file" loader makes sure assets end up in the `build` folder.
324329
// When you `import` an asset, you get its filename.
325330
// This loader doesn't use a "test" so it will catch all modules

packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js

+10
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ describe('Integration', () => {
3131
);
3232
});
3333

34+
it('graphql files inclusion', async () => {
35+
const doc = await initDOM('graphql-inclusion');
36+
const children = doc.getElementById('graphql-inclusion').children;
37+
38+
// .graphql
39+
expect(children[0].textContent.replace(/\s/g, '')).to.equal(
40+
'{"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}}}}'
41+
);
42+
});
43+
3444
it('image inclusion', async () => {
3545
const doc = await initDOM('image-inclusion');
3646

packages/react-scripts/fixtures/kitchensink/src/App.js

+5
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ class App extends Component {
111111
this.setFeature(f.default)
112112
);
113113
break;
114+
case 'graphql-inclusion':
115+
import('./features/webpack/GraphQLInclusion').then(f =>
116+
this.setFeature(f.default)
117+
);
118+
break;
114119
case 'image-inclusion':
115120
import('./features/webpack/ImageInclusion').then(f =>
116121
this.setFeature(f.default)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* Copyright (c) 2018-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import React from 'react';
9+
import A from './assets/graphql.graphql';
10+
11+
export default () => (
12+
<p id="graphql-inclusion">
13+
<span>{JSON.stringify(A)}</span>
14+
</p>
15+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright (c) 2018-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import React from 'react';
9+
import ReactDOM from 'react-dom';
10+
import GraphQLInclusion from './GraphQLInclusion';
11+
12+
describe('graphql files inclusion', () => {
13+
it('renders without crashing', () => {
14+
const div = document.createElement('div');
15+
ReactDOM.render(<GraphQLInclusion />, div);
16+
});
17+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
test(test: "test") {
3+
test
4+
}
5+
}

packages/react-scripts/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
"find-pkg": "1.0.0",
4848
"fs-extra": "5.0.0",
4949
"globby": "7.1.1",
50+
"graphql": "0.12.3",
51+
"graphql-tag": "2.6.1",
5052
"html-webpack-plugin": "2.30.1",
5153
"identity-obj-proxy": "3.0.0",
5254
"jest": "22.1.2",

packages/react-scripts/scripts/utils/createJestConfig.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ module.exports = (resolve, rootDir, srcRoots) => {
3838
transform: {
3939
'^.+\\.(js|jsx|mjs)$': resolve('config/jest/babelTransform.js'),
4040
'^.+\\.css$': resolve('config/jest/cssTransform.js'),
41-
'^(?!.*\\.(js|jsx|mjs|css|json)$)': resolve(
41+
'^.+\\.(graphql)$': resolve('config/jest/graphqlTransform.js'),
42+
'^(?!.*\\.(js|jsx|mjs|css|json|graphql)$)': resolve(
4243
'config/jest/fileTransform.js'
4344
),
4445
},

packages/react-scripts/template/README.md

+29
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ You can find the most recent version of this guide [here](https://github.com/fac
2727
- [Post-Processing CSS](#post-processing-css)
2828
- [Adding a CSS Preprocessor (Sass, Less etc.)](#adding-a-css-preprocessor-sass-less-etc)
2929
- [Adding Images, Fonts, and Files](#adding-images-fonts-and-files)
30+
- [Adding GraphQL files](#adding-graphql-files)
3031
- [Using the `public` Folder](#using-the-public-folder)
3132
- [Changing the HTML](#changing-the-html)
3233
- [Adding Assets Outside of the Module System](#adding-assets-outside-of-the-module-system)
@@ -729,6 +730,34 @@ Please be advised that this is also a custom feature of Webpack.
729730
**It is not required for React** but many people enjoy it (and React Native uses a similar mechanism for images).<br>
730731
An alternative way of handling static assets is described in the next section.
731732

733+
## Adding GraphQL files
734+
735+
> Note: this feature is available with react-scripts@2.0.0 and higher.
736+
737+
If you are using GraphQL, you can **`import` GraphQL files in a JavaScript module**.
738+
739+
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.
740+
741+
Here is an example:
742+
743+
```js
744+
// query.graphql
745+
{
746+
githubStats(repository: "facebook/react") {
747+
stars
748+
}
749+
}
750+
751+
// foo.js
752+
753+
import query from './query.graphql';
754+
755+
console.log(query);
756+
// {
757+
// "kind": "Document",
758+
// ...
759+
```
760+
732761
## Using the `public` Folder
733762

734763
>Note: this feature is available with `react-scripts@0.5.0` and higher.

0 commit comments

Comments
 (0)