expo / examples

Example projects that demonstrate how to use Expo APIs and integrate Expo with other popular tools
2.21k stars 862 forks source link

Storybook example broken after webpack 5 upgrade #422

Open Alex-McLean opened 1 year ago

Alex-McLean commented 1 year ago

Describe the bug The recent webpack 5 upgrade (https://github.com/expo/expo-cli/pull/3763), shipped with Expo 48, removed the withUnimodules method @expo/webpack-config and provides no alternative. withUnimodules is still erroneously referenced in the @expo/webpack-config README, and is also used in the with-storybook example in this repo.

To Reproduce Steps to reproduce the behavior:

  1. Clone this repo
  2. Attempt to run the with-storybook example

Expected behavior Storybook example works and provides a reference implementation for expo + storybook.

Screenshots

ERR! TypeError: withUnimodules is not a function
ERR!     at module.exports (~/expo-examples/with-storybook/.storybook/webpack.config.js:5:10)

Desktop (please complete the following information):

Smartphone (please complete the following information):

axelekwall commented 1 year ago

Having the same problem, did you find a solution @Alex-McLean?

Alex-McLean commented 1 year ago

I just had to do my best to reproduce at least the parts of withUnimodules that I needed for my use case, in a webpack 5 compatible way, ended up with:

const { DefinePlugin } = require("webpack");
const { withAlias } = require("@expo/webpack-config/addons");
const {
  getAliases,
  getConfig,
  validateEnvironment,
  getMode,
  getPaths,
  getPublicPaths,
  getModuleFileExtensions
} = require("@expo/webpack-config/env");
const { createBabelLoader } = require("@expo/webpack-config/loaders");

module.exports = function withUnimodules(baseConfig, projectRoot) {
  const webpackConfig = withAlias(baseConfig, getAliases(projectRoot));
  const env = { projectRoot, mode: webpackConfig.mode };

  const environment = validateEnvironment(env);
  const config = getConfig(environment);
  const mode = getMode(env);
  const locations = getPaths(environment.projectRoot, environment);

  const { platform = "web" } = env;
  const { build: buildConfig = {} } = config.web || {};
  const { babel: babelAppConfig = {} } = buildConfig;
  const babelProjectRoot = babelAppConfig.root || locations.root;

  const babelLoader = createBabelLoader({
    projectRoot: locations.root,
    mode,
    platform,
    babelProjectRoot,
    verbose: babelAppConfig.verbose,
    include: [
      ...(babelAppConfig.include || []),
      ...(env.babel?.dangerouslyAddModulePathsToTranspile || [])
    ],
    use: babelAppConfig.use
  });

  function reuseOrCreatePublicPaths() {
    if (webpackConfig.output && webpackConfig.output.publicPath) {
      const publicPath = webpackConfig.output.publicPath;
      return {
        publicPath,
        publicUrl: publicPath.endsWith("/")
          ? publicPath.slice(0, -1)
          : publicPath
      };
    }
    return getPublicPaths(environment);
  }

  const { publicPath } = reuseOrCreatePublicPaths();

  webpackConfig.mode = mode;

  webpackConfig.output = {
    ...webpackConfig.output,
    publicPath
  };

  webpackConfig.plugins.push(
    new DefinePlugin({
      __DEV__: process.env.NODE_ENV === "development"
    })
  );

  webpackConfig.module = {
    ...webpackConfig.module,
    rules: [...webpackConfig.module.rules, babelLoader]
  };

  webpackConfig.resolve = {
    ...webpackConfig.resolve,
    symlinks: false,
    extensions: getModuleFileExtensions("web")
  };

  return webpackConfig;
};
brookemitchell commented 1 year ago

I liked @Alex-McLean 's fix for webpack, nice! However are looking to move all our bundling to metro, trying out https://github.com/storybookjs/addon-react-native-web but haven't quite gotten to a working state yet....

jaronoff97 commented 10 months ago

Any updates here? this has broken my project and is preventing me from migrating to webpack 5.

schlosser commented 10 months ago

Also experiencing this! @EvanBacon maybe you have an idea for a possible workaround?