Skip to content

Commit

Permalink
Add loader for .graphql files (facebook#3909)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
petetnt authored and gaearon committed Feb 3, 2018
1 parent 9db1c63 commit 38c81e0
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 1 deletion.
18 changes: 18 additions & 0 deletions 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 config/webpack.config.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,11 @@ module.exports = {
},
],
},
// The GraphQL loader preprocesses GraphQL queries in .graphql files.
{
test: /\.(graphql)$/,
loader: 'graphql-tag/loader',
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
Expand Down
5 changes: 5 additions & 0 deletions config/webpack.config.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,11 @@ module.exports = {
),
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
},
// The GraphQL loader preprocesses GraphQL queries in .graphql files.
{
test: /\.(graphql)$/,
loader: 'graphql-tag/loader',
},
// "file" loader makes sure assets end up in the `build` folder.
// When you `import` an asset, you get its filename.
// This loader doesn't use a "test" so it will catch all modules
Expand Down
10 changes: 10 additions & 0 deletions fixtures/kitchensink/integration/webpack.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ describe('Integration', () => {
);
});

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
5 changes: 5 additions & 0 deletions fixtures/kitchensink/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ class App extends Component {
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)
Expand Down
15 changes: 15 additions & 0 deletions fixtures/kitchensink/src/features/webpack/GraphQLInclusion.js
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>
);
17 changes: 17 additions & 0 deletions fixtures/kitchensink/src/features/webpack/GraphQLInclusion.test.js
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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
"find-pkg": "1.0.0",
"fs-extra": "5.0.0",
"globby": "7.1.1",
"graphql": "0.12.3",
"graphql-tag": "2.6.1",
"html-webpack-plugin": "2.30.1",
"identity-obj-proxy": "3.0.0",
"jest": "22.1.2",
Expand Down
3 changes: 2 additions & 1 deletion scripts/utils/createJestConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ module.exports = (resolve, rootDir, srcRoots) => {
transform: {
'^.+\\.(js|jsx|mjs)$': resolve('config/jest/babelTransform.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
29 changes: 29 additions & 0 deletions 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 @@ -729,6 +730,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 react-scripts@2.0.0 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 `react-scripts@0.5.0` and higher.
Expand Down

0 comments on commit 38c81e0

Please sign in to comment.