Saâd Yousfi
Saâd Yousfi

Reputation: 73

What can't I export JSX from a NPM Package

I'm writing a library that exposes some React Components as part of its API.

I'm going to make a few assumptions here :

1 - It is going to be used inside react projects.

2 - Those projects will bundle their dependencies at some point.

3 - Those react projects can use JSX as a way of describing the UI.

4 - Their bundler of choice, Webpack if it's a create-react-app, will use babel in order to parse and transpile that JSX into vanilla JS.

Following that logic, I should be able export some JSX from an external package, because the package's code will be bundled, transpiled alongside the app.

However, when I do so in a create-react-app project, I get the following error :


SyntaxError: /Users/someone/Desktop/someproject/dist/esm/index.js: Support for the experimental syntax 'jsx' isn't currently enabled (35:13):

Add @babel/preset-react (https://git.io/JfeDR) to the 'presets' section of your Babel config to enable transformation. If you want to leave it as-is, add @babel/plugin-syntax-jsx (https://git.io/vb4yA) to the 'plugins' section to enable parsing.


Yes, I could transpile the JSX, maybe I will. I just don't see any reason to, if it's going to be bundled anyway. I prefer leaving transpiling tweaking and optimisation to the user.

My concern is that if I transpile it myself, I have 2 choices.

import React in scope, and using babel to turn <MyComponent/> into React.createElement(), but this will rule out the possibility to use the new JSX transform

use the new JSX transform myself, and figure out whether or not my code will be compatible with react versions prior to 17. And increase my own bundle size because there is a lot of code added by babel to make that work.

At this point, I think I'm quite excited about this issue because frankly I have no idea why I can't just export plain JSX from my package. I know I'm probably missing something obvious, like a semi-colon or whatever, but I really want to understand.

If you want some code / rollup - babel configs feel free to ask.

Tanks !

Upvotes: 0

Views: 387

Answers (1)

Seth Lutske
Seth Lutske

Reputation: 10696

Your logic seems to make sense at first glance. But let's examine why this is a bad idea.

JSX is a special syntax that must be transpiled down to the lowest common demoninator to be understood in the browser, or by Nodejs. This is what bundlers do, and as you mentioned, anyone working with react in a node environment is almost certainly using a bundler to do this.

However, there are any number of wierd syntaxes that people may use in their code. When a bundler imports code from a node_module, if the code in those modules is not already transpiled, the bundler would need to transpile them as well. Considering un-transpiled modules may be in any number of strange syntaxes, each module would need its own transpilation instructions (think babel configuration). Having unique transpilation configurations for every node_module would be very unwieldy, not to mention having to transpile each node_module, potentially in a different way, would be bad for performance.

The generally accepted best practice for solve this problem is to simply build your package using a bunder which boils the code down to the lowest common denominator. This enables your package-user's bundler to just bring in the code in a node_module "as is".

While its probably possible to come up with some crazy babe/webpack/rollup instructions to custom-interperet your module as JSX, do you really want your library users to have to do that? Especially in the case of people using create-react-app, customizing the babel config of CRA is not natively supported, which means they will need to take extra-steps to get your library to work. Additionally, webpack defaults to excluding node_modules from js transpilations for obvious performance reasons, and CRA follows this convention. When publishing libraries, you want them to be universally useable as easy as possible to consume.

Transpiling, tweaking, and optimizing code is best left to the person who wrote it, which in the case of a react component library you're trying to publish, is you.

Upvotes: 2

Related Questions