diff --git a/packages/react-scripts/config/jest/graphqlTransform.js b/packages/react-scripts/config/jest/graphqlTransform.js new file mode 100644 index 00000000000..5b70f07d6f2 --- /dev/null +++ b/packages/react-scripts/config/jest/graphqlTransform.js @@ -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); + }, +}; diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index bd5d218cc8d..398b8bf53b7 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -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. diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js index 6c9a879e851..7b73dd787cd 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -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 diff --git a/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js b/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js index e479be4b81a..bba497c49f3 100644 --- a/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js +++ b/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js @@ -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'); diff --git a/packages/react-scripts/fixtures/kitchensink/src/App.js b/packages/react-scripts/fixtures/kitchensink/src/App.js index 750f8a90b98..c45ef2a38e8 100644 --- a/packages/react-scripts/fixtures/kitchensink/src/App.js +++ b/packages/react-scripts/fixtures/kitchensink/src/App.js @@ -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) diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/GraphQLInclusion.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/GraphQLInclusion.js new file mode 100644 index 00000000000..728b7a2847d --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/GraphQLInclusion.js @@ -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 () => ( +
+ {JSON.stringify(A)} +
+); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/GraphQLInclusion.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/GraphQLInclusion.test.js new file mode 100644 index 00000000000..914ce241bdd --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/GraphQLInclusion.test.js @@ -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(