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

Build problems with babel 7 for react-native(-web) dependencies using flow #5288

Closed
msand opened this issue Sep 25, 2018 · 17 comments
Closed
Labels
good first issue Easy to fix issues, good for newcomers

Comments

@msand
Copy link

msand commented Sep 25, 2018

Bug report

Using react-native dependencies which contain Flow code is broken with Next.js 7.0.0

Describe the bug

Depending on e.g. react-native-tab-view worked fine with Next.js 6.1.2 / React 16.4.2 / RNW ^0.8.8 / Babel 6
But is giving very strange behaviour with Next.js 7.0.0 / React 16.5.2 / RNW ^0.9.0 / Babel 7

A clear and concise description of what the bug is.
Build error, which when worked around produces very strangely behaving components.

To Reproduce

git clone https://github.com/msand/repro-native-web-bug.git
cd repro-native-web-bug
yarn
yarn dev
open localhost:3000

see build error:

Failed to compile
./node_modules/react-native-tab-view/src/index.js
Module build failed (from ./node_modules/next/dist/build/webpack/loaders/next-babel-loader.js):
SyntaxError: /Users/jannegylling/Micke/repro-native-web-bug/node_modules/react-native-tab-view/src/index.js: Support for the experimental syntax 'exportDefaultFrom' isn't currently enabled (12:8):

  10 | export { default as SceneMap } from './SceneMap';
  11 | 
> 12 | export type { Route } from './TypeDefinitions';
     |        ^
  13 | export type { Scene } from './TypeDefinitions';
  14 | export type { NavigationState } from './TypeDefinitions';
  15 | export type { SceneRendererProps } from './TypeDefinitions';

Add @babel/plugin-proposal-export-default-from (https://git.io/vb4yH) to the 'plugins' section of your Babel config to enable transformation.
This error occurred during the build time and cannot be dismissed.
  1. add require("@babel/preset-flow"), to beginning of the presets property of the returned babel config in node_modules/next/dist/build/babel/preset.js

  2. restart next, open the page, no more build error, instead the content is spinning
    screen shot 2018-09-25 at 23 09 13

  3. add a newline to index.js or mutate it somehow to cause next.js to hot reload the content

  4. see the components in almost fully functional state, but styles are broken
    screen shot 2018-09-25 at 23 13 23

Expected behavior

The code builds without error, allowing to style react-native components
Expected looks can be seen in the initial commit (second commit only upgrades deps and babel conf to reproduce the bugs)
screen shot 2018-09-25 at 23 14 46

System information

  • OS: macOS
  • Browser: chrome
  • Version of Next.js: 7.0.0
@msand
Copy link
Author

msand commented Sep 25, 2018

While investigating this, I've found that if I add this prepare step (available from the "workaround" branch of the repo):
msand/repro-native-web-bug@d1258cd#diff-b9cfc7f2cdf78a7f4b91a753d10865a2R7
"prepare": "npx babel node_modules/react-native-tab-view/ --out-dir react-native-tab-view --presets=@babel/preset-react,@babel/preset-flow --plugins=@babel/plugin-proposal-class-properties,@babel/plugin-proposal-object-rest-spread"

And, import the built version of the dependency, it works as expected and without touching the Next.js internals. Thus eliminating the babel, react-native-web and react version changes as potential candidates for causing the symptoms.

Thus, the error most likely resides in the babel/webpack/Next.js configuration of the setup. Could anyone give suggestions for what to try next? Thanks!

@timneutkens

@timneutkens
Copy link
Member

Using react-native dependencies which contain Flow code is broken with Next.js 7.0.0

How would this not be broken in v6 🤔 We never transpiled node_modules

@msand
Copy link
Author

msand commented Sep 25, 2018

@steida Have you seen/solved any similar issue? Seems Este hasn't upgraded to v7 of Next.js and Babel yet, nor have any dependencies on react-native libraries, but thought you might know quite a lot about Flow + Babel and Next.js and similar setups to this.

@msand
Copy link
Author

msand commented Sep 25, 2018

@timneutkens I have a custom next.config.js to compile the dependency, I thought this was the standard way to achieve this with Next.js:
https://github.com/msand/repro-native-web-bug/blob/dd191684a2c936bd389c62b21f84eec01a0ed5f7/next.config.js#L1-L32

@timneutkens
Copy link
Member

I guess that would probably work 🤔

@msand
Copy link
Author

msand commented Sep 25, 2018

Found a different workaround: msand/repro-native-web-bug@70d4198

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [["react-native-web", { "commonjs": true }]]
}

next.config.js

// Update these to match your package scope name.
const internalNodeModulesRegExp = /(?:react-native-tab-view)(?!.*node_modules)/;
const externalNodeModulesRegExp = /node_modules(?!\/(?:react-native-tab-view)(?!.*node_modules))/;

module.exports = {
  webpack: (config, { dev, isServer, defaultLoaders }) => {
    config.resolve.symlinks = false;
    config.externals = config.externals.map(external => {
      if (typeof external !== 'function') return external;
      return (ctx, req, cb) =>
        internalNodeModulesRegExp.test(req) ? cb() : external(ctx, req, cb);
    });
    config.module.rules.push({
      test: /\.+(js|jsx)$/,
      use: {
        loader: 'next-babel-loader',
        options: {
          presets: ['module:metro-react-native-babel-preset'],
          plugins: [
            ['react-native-web', { commonjs: true }],
          ],
        },
      },
      include: [internalNodeModulesRegExp],
    });
    config.resolve.alias = {
      ...config.resolve.alias,
      'react-native$': 'react-native-web',
    };
    config.resolve.extensions = ['.web.js', '.js'];
    return config;
  },
  webpackDevMiddleware: config => {
    config.watchOptions.ignored = [
      ...config.watchOptions.ignored,
      externalNodeModulesRegExp,
    ];
    return config;
  },
};

@timneutkens Is this the correct way to handle this?

@bfreis
Copy link

bfreis commented Sep 26, 2018

I was about to report a similar problem. That is, flow types not being removed; I'm not using react-native(-web) though.

I haven't used next.js before v7 in monorepos, but I'm trying and I cannot import files from other packages in my Yarn Workspaces that use flow types.

No matter what I do, I cannot seem to have the strip-flow-types plugin be applied. I tried manually creating the .babelrc file, I tried applying the transpileModules config key and the next-plugin-transpile-modules plugin.

EDIT: I tried using the configuration example above, adapting it to my own packages, with no luck. I also tried to debug it a bit - it seems like the config.externals array is empty. Also, during my debug, I could see that Next.js is properly loading my custom .babelrc that includes the transform-flow-strip-types plugin. Tried multiple import paths of the plugin btw. Also, I tested just writing garbage in my custom .babelrc to verify that it is indeed being used, and it is (ie, garbage in babel config breaks the build completely).

@steida
Copy link
Contributor

steida commented Sep 26, 2018

@msand I just updated http://github.com/este/este, and it seems it works.

@bfreis
Copy link

bfreis commented Sep 28, 2018

Good news.

After investigating this a bit further, I think I found a solution to the issue -- at least as it was happening to me.

What I have is a Yarn Workspace with 2 packages -- one is a "web" package using Next.js, the other is just a library. I added flow type annotations to the library. This would make impossible to import the library in the web package -- it would complain about the type Xxx = {...} definitions.

I tried using the "withTranspileModule" plugin, tried using configuration based on the snippet above shared by @msand , tried customizing my .babelrc to include the @babel/transform-flow-strip-types plugin, tried using a bunch of different presets. Nothing seemed to solve the problem.

Now, the solution I found was to change the defaultLoaders.babel in the Next config file, and include the @babel/transform-flow-strip-types plugin in the .options.plugins field.

Also, I have no idea if this would break any other parts of the build. In a tiny little test scenario it seems to be working OK.

Below is the final version of my next.config.js file that is working just fine -- hope it might help others. Also, might be nice to make sure that there's an example/ that shows (and can be used as a test case) how to setup Yarn Workspaces + Flow across multiple packages. Today, in the examples there's one showing that Yarn Workspaces can be set up, and another one that shows Flow being set up. But no example showed Yarn Workspaces + Flow at the same time.

Here's the next.config.js that works for me. Btw, I have very limited knowledge on Webpack configuration, so I have no clue what the "externals" thing is; I just copied it from the snippet above. It seems like if I remove it, it breaks the config again.

const internalNodeModulesRegExp = /(?:mylib)(?!.*node_modules)/;
const externalNodeModulesRegExp = /node_modules(?!\/(?:mylib)(?!.*node_modules))/;

module.exports = {
  webpack: (config, { dev, isServer, defaultLoaders }) => {
    // This is the fix that worked for me:
    if (!defaultLoaders.babel.options.plugins) {
      defaultLoaders.babel.options.plugins = []
    }
    defaultLoaders.babel.options.plugins.push("@babel/transform-flow-strip-types")

    config.resolve.symlinks = false;

    // No idea why we use config.externals here, copied from snippet above.
    // Without it, the build fails.
    config.externals = config.externals.map(external => {
      console.log('external', JSON.stringify(external, null, 2))
      if (typeof external !== 'function') return external;
      return (ctx, req, cb) =>
        internalNodeModulesRegExp.test(req) ? cb() : external(ctx, req, cb);
    });

    // Adding the rule to match my library
    config.module.rules.push({
      test: /\.+(js|jsx)$/,
      use: defaultLoaders.babel,
      include: [internalNodeModulesRegExp]
    });

    return config;
  },

  // Not sure why we add the "external" regexp to the middleware, but keeping
  // it from the snippet above.
  webpackDevMiddleware: config => {
    config.watchOptions.ignored = [
      ...config.watchOptions.ignored,
      externalNodeModulesRegExp,
    ];
    return config;
  },
};

@jasonbarry
Copy link

I'm seeing this too — I'm using yarn workspaces and flow for a web project (not react native). I was using flow in this project with Next 5 and Next 6, but am now encountering this issue while upgrading to Next 7.

Syntax Error: SyntaxError: ./src/store.js: Unexpected token, expected "," (18:38)

18 > export const initStore = (initialState: Object = {}) => {
     |                                     ^

Interestingly, I'm able to work around the error by renaming my package.json file (not the one in the root dir, but rather the one that corresponds to my monorepo's subpackage) to something else. Perhaps a package.json deeper in the project tree is interfering with Next and the flow strip types babel plugin?

@martpie
Copy link
Contributor

martpie commented Oct 3, 2018

I think this is a more generic bug (feature?). It seems .babelrc is not being found/applied.

cf martpie/next-transpile-modules#1 (comment)

I am not sure who is responsible for this change (Babel, Next.js...)

@ptomasroos
Copy link
Contributor

I'm experiencing this as well after upgrading to 7.0.2 its clearly a regression @timneutkens

@ptomasroos
Copy link
Contributor

Moving to the babel.config.js with the exact same setup works for me. Hence the .babelrc are not being picked up correctly.

@colincclark
Copy link

Looks like RNW does not support Babel 7 yet? necolas/react-native-web#1191

@steida
Copy link
Contributor

steida commented Jan 17, 2019

@timneutkens timneutkens added help wanted good first issue Easy to fix issues, good for newcomers labels Mar 9, 2019
@Timer
Copy link
Member

Timer commented Dec 23, 2019

Closing as this is the intended behavior of Babel 7 (upgraded from Babel 6). You'll have to use next-transpile-modules if you need this behavior.

Also, be sure to add flow syntax support to your .babelrc.

@Timer Timer closed this as completed Dec 23, 2019
@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Jan 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
good first issue Easy to fix issues, good for newcomers
Projects
None yet
Development

No branches or pull requests

10 participants