react-cosmos: Webpack error with brand new Expo project

What’s wrong?

Based on the docs I was given the impression Cosmos can be used across React Native and web in an Expo project but using Cosmos in an Expo project yields webpack errors.

Steps to reproduce

  1. Clone https://github.com/tomparkp/react-cosmos-expo-bug
  2. yarn install and yarn cosmos
  3. See webpack error.
ERROR in ./test.fixture.js 4:15
Module parse failed: Unexpected token (4:15)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| import React from "react";
| 
> export default <Text>Hello World</Text>;
| 
 @ ./node_modules/react-cosmos/dist/plugins/webpack/client/userDeps.js 7:22-76
 @ ./node_modules/react-cosmos/dist/plugins/webpack/client/index.js
 @ multi ./node_modules/react-cosmos/dist/plugins/webpack/client/reactDevtoolsHook.js ./node_modules/@skidding/webpack-hot-middleware/client.js?reload=true&overlay=false ./node_modules/react-cosmos/dist/plugins/webpack/client/index.js

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 16 (6 by maintainers)

Most upvoted comments

ok, it was my mistake twice:

  1. I had a mismatching RN version
  2. My test fixture was hidden behind the “camera” on the simulator so I was staring at a blank screen (🤦‍♂️)

I’d also like to use Cosmos in a web + iOS Expo project, although it makes sense that it would be a lot for one person to maintain all these different configurations.

In case it helps someone else out, I did the following to get mirroring working on Expo SDK 44 :

  1. Run expo customize:web to generate a webpack.config.js. (If this is exiting without making a config file, make sure you read the instructions - I was tripped up by the UI here.)
  2. The patch above is close to working, but needed two updates: (1) The env passed to createExpoWebpackConfigAsync doesn’t accept a string anymore - it expects an object of this shape; and (2) the HtmlWebpackPlugin requires a projectRoot in its options (not sure what is different about running via Cosmos that omits this).

Putting that all together, I modified the webpack.config.js to look like this:

const createExpoWebpackConfigAsync = require('@expo/webpack-config');

module.exports = async function (env, argv) {
  // HACK: figure out if this is being invoked with Cosmos to decide whether to
  // apply the configuration overrides
  const isCosmos = argv != null && argv['$0'] != null && argv['$0'].includes('cosmos');

  if (typeof env === 'string') {
    env = {
      mode: env,
      projectRoot: __dirname,
      platform: 'web',
    };
  }
  const config = await createExpoWebpackConfigAsync(env, argv);
  
  // Modify html-webpack-plugin
  if (isCosmos) {
    const htmlPlugin = config.plugins.find(p => p.constructor && p.constructor.name === 'HtmlWebpackPlugin');
    if (htmlPlugin) {
      htmlPlugin.options.projectRoot = __dirname;
      htmlPlugin.options.filename = '_renderer.html';
    }

    // Remove ManifestPlugin because it requires specific entrypoints that are
    // replaced by Cosmos
    config.plugins = config.plugins.filter(p =>
      !p.constructor || p.constructor.name !== 'ManifestPlugin'
    );
  }

  return config;
};

As stated above, this will probably break when Expo updates. I’m using a managed Expo project; here are the relevant(?) dependency versions that I’m working with:

I have only used this briefly in iOS/web development so far; I haven’t tried exporting.