Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Storybook integration example #1026

Closed
larixer opened this issue Feb 8, 2019 · 15 comments · Fixed by #1093
Closed

React Storybook integration example #1026

larixer opened this issue Feb 8, 2019 · 15 comments · Fixed by #1093

Comments

@larixer
Copy link
Member

larixer commented Feb 8, 2019

spinjs supports Storybook now, check this code to integrate it:
https://github.com/sysgears/spinjs/blob/master/docs/programmatic.md
It will let storybook to utilize the same Webpack config used by the kit. So one will be able to import container components in storybook stories as well as presentational components. There still be a need to mock backend, but we can do it the same way as in the tests, that mocking code should work for storybook stories too.

@eric-burel
Copy link
Contributor

eric-burel commented Jun 3, 2019

Hi, I am trying to setup Storybook, here is my current process:

  • Follow the Slow start guide, using yarn. Apollo Universal Starter Kit won't work with npx or npm
  • Storybook must be installed in your packages/client folder, because it is only meant to be used with the React app. For React Native to my best knowledge the config of Storybook is slightly different, so I'd advise a fully separate setup.

Now you need to improve the Storybook webpack build to take our own build context into account (mostly handle TypeScript).

  • In the script provided by @Vlasenko , I needed a few updates: replace spinjs with @larix/zen Edit: actually the updated doc is here
  • The config object is not completely valid: the mode must be lower cases (it is uppercased). It also generates a second config in the .config fields. I don't know what to do with this, I needed to remove it in order to get things to work (Webpack does not tolerate unexpected fields) and it seems incomplete (does not support .tsx).

Right now I get this code for webpack.config.js:

const createConfig = require('@larix/zen').createConfig;

module.exports = function (baseConfig, configType) {
  const webpackConfig =  createConfig({
    cmd: configType === 'DEVELOPMENT' ? 'watch' : 'build',
    builderOverrides: { stack: ['storybook'] },
    genConfigOverrides: Object.assign({ merge: { entry: 'replace', output: 'replace' } }, baseConfig)
  });
  // FIXES:
  webpackConfig.mode = webpackConfig.mode.toLowerCase()
  delete webpackConfig.config
  return webpackConfig
};

Sadly it does not reckognize .jsx files so I must be wrong somewhere. Still working on it.

Also storybook needs to be ignored somehow otherwise build will fail.

@eric-burel
Copy link
Contributor

Hi, it does not seem to work with  ts files after your PR #1093. I've tested with the ClientCounterView component and the interface keyboard is not accepted. Can we configure Storybook so it gets a config similar to the client package?

@larixer
Copy link
Member Author

larixer commented Jun 11, 2019

@eric-burel Hi it actually uses the same config as client and you can see that index.stories.tsx is obviously written in TypeScript, so it should support both ES6 and TS

@eric-burel
Copy link
Contributor

You are right for the index itself but it fails when I import a tsx component.
Eg:

import React from 'react';

import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';
import { ClientCounterView } from '@gqlapp/counter-client-react/clientCounter/components/ClientCounterView';

const { Button, Welcome } = require('@storybook/react/demo');

interface Foo {
  bar: String
}

storiesOf('Counter test', module)
  .add('Counter', () => (
    <ClientCounterView text="hello">
      <div>Children</div>
    </ClientCounterView>
  ));

const bar :Foo = {bar:"hello"}
console.log(bar)

Using TS is ok in the index but it fails to parse ClientCounterView though, I get this error:

ERROR in /code/vos-talents-dexperts/node_modules/@gqlapp/counter-client-react/clientCounter/components/ClientCounterView.tsx 11:0
client: Module parse failed: The keyword 'interface' is reserved (11:0)
client: You may need an appropriate loader to handle this file type.

@eric-burel
Copy link
Contributor

eric-burel commented Jun 11, 2019

It behaves as if story build was using a different loader (eg jsx) than the top level import + stories import which will correctly us TypeScript. It fails as soon as I try to use ClientCounterView, be it in a console.log or a add().
You are right that it seems to use the same config as client though, I have stuffs related to TS in the config and the index story loads correctlty.

@eric-burel
Copy link
Contributor

Note that I get a different error if I don't use the @gqlapp "shortcut" (import { ClientCounterView } from '../../../modules/counter/client-react/clientCounter/components/ClientCounterView'; ), then it seems to fail on JSX too:

ERROR in my-app/node_modules/@gqlapp/look-client-react/ui-bootstrap/components/Alert.jsx 10:4
Module parse failed: Unexpected token (10:4)
You may need an appropriate loader to handle this file type.
|   }
|   return (
>     <RSAlert {...props} color={color}>
|       {children}
|     </RSAlert>
ERROR in my-app/node_modules/@gqlapp/module-client-react/BaseModule.ts 10:7
Module parse failed: Unexpected token (10:7)
You may need an appropriate loader to handle this file type.
|  * Common module interface for React and React Native feature modules
|  */
> export interface BaseModuleShape extends GraphQLModuleShape {
|   // Redux reducers list
|   reducer?: ReducersMapObject[];

....

@larixer
Copy link
Member Author

larixer commented Jun 11, 2019

@eric-burel Should be fixed via:
9c125ec

@eric-burel
Copy link
Contributor

Awesome! It's fixed, thanks a lot.

@eric-burel
Copy link
Contributor

Storybook works but now my app itself won't build. Here are the errors:

webDll-webpack error ModuleNotFoundError: Module not found: Error: Can't resolve 'child_process' in '/home/my-app//packages/client/node_modules/cross-spawn'
    at factory.create (/home/my-app//node_modules/webpack/lib/Compilation.js:823:10)
    at factory (/home/my-app//node_modules/webpack/lib/NormalModuleFactory.js:397:22)
    at resolver (/home/my-app//node_modules/webpack/lib/NormalModuleFactory.js:130:21)
    at asyncLib.parallel (/home/my-app//node_modules/webpack/lib/NormalModuleFactory.js:224:22)
    at /home/my-app//node_modules/neo-async/async.js:2825:7
    at /home/my-app//node_modules/neo-async/async.js:6886:13
    at normalResolver.resolve (/home/my-app//node_modules/webpack/lib/NormalModuleFactory.js:214:25)
    at doResolve (/home/my-app//node_modules/enhanced-resolve/lib/Resolver.js:184:12)
    at hook.callAsync (/home/my-app//node_modules/enhanced-resolve/lib/Resolver.js:238:5)
    at _fn0 (eval at create (/home/my-app//node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)

zen error Error: Build error
    at webpackReporter (/home/my-app//node_modules/@larix/zen/src/executor.ts:120:11)
    at reporter (/home/my-app//node_modules/@larix/zen/src/executor.ts:800:50)
    at finalCallback (/home/my-app//node_modules/webpack/lib/Compiler.js:220:39)
    at onCompiled (/home/my-app//node_modules/webpack/lib/Compiler.js:228:20)
    at hooks.make.callAsync.err (/home/my-app//node_modules/webpack/lib/Compiler.js:620:21)
    at _err0 (eval at create (/home/my-app//node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)
    at _addModuleChain (/home/my-app//node_modules/webpack/lib/Compilation.js:1083:13)
    at processModuleDependencies.err (/home/my-app//node_modules/webpack/lib/Compilation.js:1006:25)
    at asyncLib.forEach.err (/home/my-app//node_modules/webpack/lib/Compilation.js:920:13)
    at /home/my-app//node_modules/neo-async/async.js:2825:7
Error: Cannot find module 'core-js/modules/es6.function.name'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:571:15)
    at Function.Module._load (internal/modules/cjs/loader.js:497:25)
    at Module.require (internal/modules/cjs/loader.js:626:17)
    at require (internal/modules/cjs/helpers.js:20:18)
    at Object.<anonymous> (/home/eric-burel/Development_2018/vos-talents-dexperts/node_modules/extract-files/lib/index.js:7:1)
    at Module._compile (internal/modules/cjs/loader.js:678:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
    at Module.load (internal/modules/cjs/loader.js:589:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
    at Function.Module._load (internal/modules/cjs/loader.js:520:3)


In particular the core-js error appears after I install the storybook packages. @larix/zen itself, apollo-upload-client and extract-files updates seems ok

@larixer
Copy link
Member Author

larixer commented Jun 11, 2019

@eric-burel webDll-webpack error ModuleNotFoundError: Module not found: Error: Can't resolve 'child_process' in '/home/my-app//packages/client/node_modules/cross-spawn' this message means some node module which uses child_process is included into web bundle. You shoulld not have node dependencies in your packages/client/package.json->dependencies

@eric-burel
Copy link
Contributor

eric-burel commented Jun 11, 2019

Hi here are reproduction steps:

Steps:

# On a fresh install
yarn -W add @larix/zen@0.1.22 # OK
cd packages/client

# OK
yarn add apollo-upload-client@10.0.0 extract-files@5.0.0 # still OK
yarn add babel-loader@8.0.6 # still OK

# First error with cross-env
yarn add cross-env@5.1.3 # KO child_process error on yarn watch
# Errors with storybook
yarn add @storybook/react@5.1.3 # KO Error: Cannot find module 'core-js/modules/es6.function.name

Minimal repro: https://github.com/lbke/apollo-universal-starter-kit/tree/storybook-stable

I understand that those are dependencies issues but the problem is that they come from the underlying packages (eg packages that don't provide a built version, server-side only etc...).
Is that doable to have dependencies like storybook ignored?

The problem here is that indeed we are mixing 2 applications, a pure client side app and a client/server application Storybook. It seems that the build is based on all dependencies but does not necessarily detect unused ones (from the web app point of view, so Storybook related dependencies) that should be ignored.

@larixer
Copy link
Member Author

larixer commented Jun 11, 2019

Why do you add cross-env into dependencies of packages/client, it should be in devDependencies instead

@eric-burel
Copy link
Contributor

Hmmm ok I added them as dependencies instead of devDependencies... not used to yarn. I'll try tomorrow I hope it was just that.

@larixer
Copy link
Member Author

larixer commented Jun 11, 2019

@larix/zen tries to put everything in packages/client/package.json->dependencies into web DLL to speed up webpack compilation and when some node module is in there the compilation breaks.

@eric-burel
Copy link
Contributor

eric-burel commented Jun 11, 2019

Ok got it eventually. What seems to happen is that if I "yarn add" the package in packages/client with a new version, it will add the latest version. But if I run yarn at the root of the project, it will respect the lock and install the old version.

So from the beginning I thought apollo-upload-client and extract-files were up to date, but they were not. Running yarn upgrade apollo-update-client and the same for extract-files at the root fixed it.

Now it works as expected. Thanks for the support, Storybook is a huge improvement for our productivity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants