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

Resolve .jsx extension in webpack #200

Closed
7s4r opened this issue Nov 4, 2016 · 34 comments · Fixed by #3376
Closed

Resolve .jsx extension in webpack #200

7s4r opened this issue Nov 4, 2016 · 34 comments · Fixed by #3376

Comments

@7s4r
Copy link

7s4r commented Nov 4, 2016

It's recommended to use the .jsx file extension for React components.

So, wouldn't it be great to add .jsx extension in webpack?

This will also help with editors doing syntax highlighting & linting.

@domachine
Copy link

Interesting. Where did you get the information that .jsx is the recommended extension? I did a quick google search but couldn't find any official comments on this. I must admit that my google foo isn't the best.

@eezing
Copy link

eezing commented Nov 5, 2016

Yea, I prefer .jsx simply for auto language selection in editors.

@7s4r
Copy link
Author

7s4r commented Nov 5, 2016

From airbnb style guide which is actually the mostly used in JavaScript projects linting.

@domachine
Copy link

domachine commented Nov 6, 2016

@7s4r Ok, I know the airbnb style guide. What I was waiting for was a comment directly from facebook or babel. But sure the airbnb style guide is a good point. Maybe supporting both would be the right way to go. You already mentioned this in the description of the issue. So this gets a 👍 from me :).

@rossipedia
Copy link

Another point in favor of supporting the .jsx extension is that TypeScript compiles to that extension whenever you target ES6/ES2015

@foxhound87
Copy link

foxhound87 commented Dec 7, 2016

airbnb / eslint-plugin-react is complaining about react/jsx-filename-extension rule

@impronunciable
Copy link
Contributor

Now that the webpack config can be manipulated this is possible https://github.com/zeit/next.js#customizing-webpack-config

@AlteredConstants
Copy link

Is there an example for how to make this work using next.config.js? As far as I can tell, this would require overwriting at least four loaders produced by the framework (babel-loader, hot-self-accept-loader, react-hot-loader/webpack, and emit-file-loader) which those docs explicitly calls out as a bad idea and kind of defeats the purpose of the framework.

I'm fine with this not being supported if that's the official stance, but the above comment seems to suggest that it is.

@rossipedia
Copy link

rossipedia commented Jan 17, 2017

@AlteredConstants something like this:

module.exports = {
  webpack: (config, { dev }) => {
    config.resolve.extensions = ['', '.js', '.jsx'];
    return config;
  }
}

However, having just tried this, it looks like this approach does not work. I'll have to dig in to figure out why.

@AlteredConstants
Copy link

AlteredConstants commented Jan 17, 2017

@rossipedia, that will only allow Webpack to recognize imported modules with a .jsx extension when the extension is excluded from the import, e.g. import Foo from './Foo' instead of import Foo from './Foo.jsx'.

In order to get Webpack to correctly process those modules, you need to (presumably) add .jsx to the test property of the loaders mentioned above. That feels a bit heavy-handed and prone to error, and it doesn't handle the pre-rendered case according to the docs linked above. I'm also not sure the automatic page/ importing will even work in that case—that appears to happen outside of the Webpack process and/or perhaps as separate entry points?

Understandably, module resolution is more complicated in this framework than a simple Webpack config option. So again, unless I'm mistaken, the resolution to this issue seems to be "won't fix" more so than "workaround", and I just wanted to be clear on the team's stance. @impronunciable, any more insight?

@J-F-Liu
Copy link

J-F-Liu commented Feb 21, 2017

Should add this to FAQ.

module.exports = {
  webpack: (config) => {
    config.resolve.extensions = ['.js', '.jsx'];
    config.module.rules.push(
      {test: /\.(js|jsx)$/, use: 'babel-loader'}
    );
    return config;
  }
}

@foxhound87
Copy link

foxhound87 commented Feb 25, 2017

@J-F-Liu not working for me.

I'm getting Error: Cannot find module '../components/Page' or Module build failed: Error: Couldn't find preset "stage-3" relative to directory "/Users/cla/Projects/with-mobx/node_modules/styled-jsx"

Trying to setup next.js 2-beta + mobx + airbnb

Maybe I miss something? What's your .babelrc content?

It seems also pages extensions cannot be .jsx

@J-F-Liu
Copy link

J-F-Liu commented Feb 27, 2017

@foxhound87 yes, that doesn't work, I also give up.

@rossipedia
Copy link

rossipedia commented Feb 28, 2017

TypeScript 2.2 now supports "jsx": "react-native", which will output .js files but also preserve JSX. See here

@lzgrzebski
Copy link

same problem here :<, any ideas how to solve this?

@NotJustClarkKent
Copy link

NotJustClarkKent commented Mar 24, 2017

I ran into this while writing a bake-off as our company standard is to use .jsx for any files containing jsx markup. Understanding this is a webpack config and shouldn't impact performance, is there a reason specifically Next.js doesn't support jsx imports?

Edit:
As noted above, using the webpack config works well for importing components but files in /pages/ must have a .js extension to be routed correctly. As silly as this issue may seem, large teams must follow the standards/conventions put in place so this may block adoption of this great framework.

@omnibusinc
Copy link

I'm really liking everything about Next except for this, which unfortunately precludes our using it.
I'll check back in to see if any progress is made though.

@jasonszhao
Copy link

jasonszhao commented Apr 3, 2017

The issue seems to extend far deeper than Webpack and Babel; it is hardcoded in numerous places. :(

The only effort I've made so far is adding a line for "jsx" in server/resolve.js:34. I'm doing this through modifying files under my project's node_modules/next/dist/.

Making the modification outputs the below in the console. Note that the console now says Building page: /, rather than Client pings, but there's no entry for page: /.

 DONE  Compiled successfully in 12156ms                                                    8:34:44 PM

> Ready on http://localhost:3000
> Building page: /


 DONE  Compiled successfully in 10983ms                                                    8:34:58 PM

SyntaxError: Unexpected token m in JSON at position 0
    at JSON.parse (<anonymous>)
    at _callee$ (/Users/Jason/Repositories/radioapp/node_modules/next/dist/server/read-page.js:48:32)
    at tryCatch (/Users/Jason/Repositories/radioapp/node_modules/regenerator-runtime/runtime.js:64:40)
    at Generator.invoke [as _invoke] (/Users/Jason/Repositories/radioapp/node_modules/regenerator-runtime/runtime.js:299:22)
    at Generator.prototype.(anonymous function) [as next] (/Users/Jason/Repositories/radioapp/node_modules/regenerator-runtime/runtime.js:116:21)
    at step (/Users/Jason/Repositories/radioapp/node_modules/babel-runtime/helpers/asyncToGenerator.js:17:30)
    at /Users/Jason/Repositories/radioapp/node_modules/babel-runtime/helpers/asyncToGenerator.js:28:13

Edit:

This issue is actually bearable for me, because I simply created a server directory with a .eslintrc file:

{
  "parser": "espree",
  "parserOptions": {
    "ecmaVersion": 6,
  },

  "env": {
    "node": true
  },
}

In case it is helps anyone, you can configure different linter and also Sublime settings per directory. You can also create a public directory that contains your Next.js files and put the appropriate .eslintrc file there.

I'm using Sublime, with babel-sublime and SublimeLinter-contrib-eslint.

@arunoda
Copy link
Contributor

arunoda commented Apr 3, 2017

@jasonszhao I agree. But it's unlikely we are going to support .jsx support. Use .js extension.

@omnibusinc
Copy link

@arunoda That's a shame. Many of us can't use it because of this arbitrary design choice. Guess I'm uninstalling.

@jupl
Copy link

jupl commented Apr 8, 2017

Wouldn't it make more sense to make it configurable? Use next.config.js and have an option that defaults to ['.js'], or better yet a function that can filter things out such as .test.js or .spec.js for Jest.

EDIT: I'm trying to use .tsx as I cannot use the tsc approach in the TypeScript example as I'm trying to also run a custom server in TypeScript as well.

@treyhuffine
Copy link

Is .jsx still not supported? I'm also running into an issue that my company would block from using next.js since our standard is to use .jsx for React components.

@digitalmaster
Copy link

I know this one seems trivial but it's really making it difficult for our team to justify adopting Next :(

Would be awesome if someone from the core team could elaborate a bit on this seemingly non-consequential design decision.

@kunokdev
Copy link

+1 for .jsx extension support

@dzek69
Copy link

dzek69 commented May 31, 2017

You can easly add .jsx support but... not for SSR. You will get an error with that, but after changing something in the code and hot reload - you will see your page. F5 and boom, error.

Not sure how to fix that.

const originalJS = "/\\.js(\\?[^?]*)?$/";

config.resolve.extensions = [".js", ".jsx", ".json"];
config.module.rules.forEach((rule) => {
    if (String(rule.test) === originalJS) {
        rule.test = /\.jsx?(\?[^?]*)?$/;
    }
});

@ztolley
Copy link

ztolley commented Jun 1, 2017

Like many, I don't get why this can't happen.

Many people use a linter config that says use jsx, editors use it to help differentiate between regular js and jsx and ... well seriously is it that big a deal to add it? If I understood the code well enough I'd just do it myself but...

PLEEEEASE

@jmar777
Copy link

jmar777 commented Jun 8, 2017

Just throwing in some more support for the idea that .jsx can reasonably be expected to work "out of the box". The workaround is trivial once someone figures out what the problem is (and finds this issue), but in my experience it is a widely adopted convention (intentionally side-stepping "recommended" verbiage here) to use the .jsx extension for files that primarily export a React Component.

I'm about to simply swap extensions and continue on my way, but I'm struggling to understand why there's resistance to this. More importantly than this being a reasonable request, for many devs it's expected behavior, and (marginally) ratchets up the barrier to entry. And while I don't want to spin this off into a debate about the merits of .jsx as an extension in the first place, suffice it to say that it's not entirely unreasonable to only want valid JavaScript in .js files, and I would argue that's a sentiment that is held by many existing and potential next.js users.

Btw, just getting started, but loving things so far. Thanks for all the awesome work!

@oliviertassinari
Copy link
Contributor

oliviertassinari commented Jun 13, 2017

That's probably linked, I couldn't used a .md extension. I had to use the following trick to make it work on the server (.md.js):

next.config.js

// ...
          {
            test: /\.md\.js$/,
            loader: 'raw-loader',
          },
// ...

@zeiteisen
Copy link

zeiteisen commented Aug 9, 2017

I use eslint with airbnb and added another rule to silence the warning

{
    "extends": "airbnb",
    "rules": {
        "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }]
    }
}

@curran
Copy link
Contributor

curran commented Oct 18, 2017

Does anyone have a working example where .jsx files are

  • inside the pages directory,
  • working with server-side rendering, and
  • being imported as modules from another directory

?

This would make a great addition to the /examples directory.

@bdombro
Copy link
Contributor

bdombro commented Oct 31, 2017

+1 for adding jsx support.

@glemiere
Copy link

glemiere commented Mar 11, 2018

I fixed it by doing something similar to what @rossipedia was suggesting.

If it's not already there, create next.config.js at the root of the project.
Then simply push 'jsx' to the config.resolve.extensions array, it works just fine.

module.exports = {
  webpack: function (config, { isServer }) {
    config.resolve.extensions.push('.jsx');
    return config
  }
}

EDIT
Be careful, this modification seems to have a bad impact on performances. Going to investigate further.

@timneutkens
Copy link
Member

timneutkens commented Mar 11, 2018

If you’re using next v5 there is no need to change anything whatshowever, the .jsx extension is supported out of the box. If you’re seeing anything performance related try upgrading to next@canary.

@glemiere
Copy link

I noticed that, awesome!

@lock lock bot locked as resolved and limited conversation to collaborators May 16, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.