reactql / kit

ReactQL starter kit (use the CLI)
https://reactql.org
228 stars 38 forks source link

Improvement- Help with Webpack configuration for React Storybook #66

Closed CaptainChemist closed 7 years ago

CaptainChemist commented 7 years ago

I have been working on integrating react storybook with the reactQL package. Storybook is a way to rapidly prototype react components and it has really been speeding up my development time. It also has automatic jest snapshot testing in place, which helps catch regressions that break the UI.

Here is a forked version that I almost have 100% operational (albeit the webpack.config file is not utilizing the lovely webpack config files already in place because of my ignorance of how to use them properly). The only issue I am having is in files where I am importing a .gql file because there is a mutation/query. I get the following error simply by having the import gql statement, even if I don’t try and use it in HOC with the react component.

ERROR in ./src/graphql/mutations/editMutation.gql
Module build failed: GraphQLError: Syntax Error GraphQL request (2:5) Unexpected Name "var"

1: 
2:     var doc = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"esanalyzerEditMicrogrid"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},"defaultValue":null},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"objectPath"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Array"}}},"defaultValue":null},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"num"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Number"}},"defaultValue":null},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"str"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}},"defaultValue":null}],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":null,"name":{"kind":"Name","value":"esanalyzerEditMicrogrid"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}},{"kind":"Argument","name":{"kind":"Name","value":"objectPath"},"value":{"kind":"Variable","name":{"kind":"Name","value":"objectPath"}}},{"kind":"Argument","name":{"kind":"Name","value":"num"},"value":{"kind":"Variable","name":{"kind":"Name","value":"num"}}},{"kind":"Argument","name":{"kind":"Name","value":"str"},"value":{"kind":"Variable","name":{"kind":"Name","value":"str"}}}],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":null,"name":{"kind":"Name","value":"id"},"arguments":[],"directives":[],"selectionSet":null}]}}]}}],"loc":{"start":0,"end":200}};
       ^
3:     doc.loc.source = {"body":"mutation editMutation($id: String!, $objectPath: Array!, $num: Number, $str: String) {\r\n  editMutation(id: $id, objectPath: $objectPath, num: $num, str: $str) {\r\n    id\r\n  }\r\n}\r\n","name":"GraphQL request","locationOffset":{"line":1,"column":1}};

    at syntaxError (C:\SVN\frontend\node_modules\graphql\error\syntaxError.js:31:15)
    at unexpected (C:\SVN\frontend\node_modules\graphql\language\parser.js:996:33)
    at parseDefinition (C:\SVN\frontend\node_modules\graphql\language\parser.js:155:9)
    at parseDocument (C:\SVN\frontend\node_modules\graphql\language\parser.js:109:22)
    at parse (C:\SVN\frontend\node_modules\graphql\language\parser.js:46:10)
    at parseDocument (C:\SVN\frontend\node_modules\graphql-tag\src\index.js:128:16)
    at gql (C:\SVN\frontend\node_modules\graphql-tag\src\index.js:161:10)
    at Object.module.exports (C:\SVN\frontend\node_modules\graphql-tag\loader.js:44:18)
 @ ./src/components/control_input/index.js 18:31-93
 @ ./src/components/control_input/index.stories.js
 @ ./src \.stories\.js$
 @ ./.storybook/config.js
 @ multi ./node_modules/@storybook/react/dist/server/config/polyfills.js ./node_modules/@storybook/react/dist/server/config/globals.js (webpack)-hot-middleware/client.js?reload=true ./.storybook/config.js

This has something to with how the graphql-tag/loader is working in the webpack.config file. I am curious if someone could suggest how I can modify my webpack.config file to match the functionality of reactQL’s webpack. Hopefully if we can get this working, this functionality can be added into the main repo because it really simplifies the component design lifecycle:

1) Design the query/mutation in graphiQL 2) Design the dumb component in storybook with all the states you can possibly need 3) Add the query/mutation as a @graphql() HOC to the component 4) Use something like storybook-addon-apollo-graphql to mock how the mutation will work with a fake grapnQL server 5) Put the working component into the real working app

That’s it! Anyway, thanks for your interest and help! I absolutely love the reactQL project and use it in the two main projects I am developing right now.

leebenson commented 7 years ago

Apologies for the delay in getting to this, @CaptainChemist

I've worked with Storybook before, pre-ReactQL. I wound up extending per full control mode -- as a means to extend, rather than replace, the Webpack config.

A big issue is that Storybook uses Webpack 2, whereas ReactQL uses Webpack 3. Trying to get the two environments to be perfectly in sync could be a tough act to balance - especially with the PostCSS plugins, many of which are now based entirely of Webpack 3's new config syntax. So you might fix this, but then find someone else has changed later.

Personally, I'm not a fan of hiding Webpack config behind a separate framework/CLI.

I'd instead recommend handling mocks by creating a /playground route in your app, where process.env.NODE_ENV === 'development', and simply mounting your components there.

You then have the full flexibility of ReactQL at your disposal -- Apollo, Redux, SSR, PostCSS/SASS/LESS, hot code reloading, etc -- and an environment that mimics production, without wrestling with different Webpack versions.

Storybook is unlikely to be added to core because it's another system to maintain that I feel ReactQL already does more flexibly, so I'll close this for now. But if you get this working and can see any use cases I'm missing, please feel free to discuss further.

leebenson commented 7 years ago

Also -> https://github.com/storybooks/storybook/issues/731#issuecomment-289725399