TLDR: Detailed step by step guide
A couple things have changed since the writing of the tutorial namely the following are the breaking changes, unless listed otherwise the other steps in the tutorial are the same:
You will need to download and use the babel-cli
in order to get your custom "lib" script command to work:
npm install --save-dev @babel/cli
You will also need to download and use the @babel/plugin-transform-react-jsx
plugin within your custom "lib" script command to compile and transform your React code since Babel 6 and up no longer have any native transforms for React. This is necessary for when you want to share your custom component with only native JavaScript on npmjs for others.
npm install --save-dev @babel/plugin-transform-react-jsx
Update your "lib" script command to use the babel's JSX transforming plugin listed in step 2:
"scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"lib": "babel --plugins @babel/transform-react-jsx src/node_modules --out-dir lib --copy-files",
"test": "node scripts/test.js"
},
Note: You also don't need the .babelrc
file listed in the tutorial as we will edit the webpack.config.js
file to properly transpile JSX
later on.
Steps 1 - 3 will allow you to publish and share your component with others, but you will still have to make adjustments for your local development and I will describe those steps below:
For your custom component's package.json
remove the .js
extension for the "main"
entry point as this will cause the following issue. For example, here is my custom component's package.json
:
{
"private": true,
"name": "YourComponent",
"main": "./YourComponent"
}
Now if you try to compile and run your application locally, using your custom component, it will throw an error complaining about your custom component's JSX
syntax:
SyntaxError: YourComponent.js: Unexpected token (6:6)
3 | render() {
4 | return (
> 5 | <div>
| ^
6 | { this.props.children }
7 | </div>
8 | )
This is because you need to edit your webpack.config.js
file to use the @babel/preset-env
and @babel/preset-react
babel presets. So you want to add this line:
presets: ['@babel/preset-env', '@babel/preset-react'],
to your babel loader for your application's code.
For reference, here is the relevant section of my code (starts on line 329):
...
// Process application JS with Babel.
// The preset includes JSX, Flow, TypeScript, and some ESnext features.
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
customize: require.resolve(
'babel-preset-react-app/webpack-overrides'
),
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
[
require.resolve('babel-plugin-named-asset-import'),
{
loaderMap: {
svg: {
ReactComponent: '@svgr/webpack?-svgo,+ref![path]',
},
},
},
],
],
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
cacheCompression: isEnvProduction,
compact: isEnvProduction,
},
},
...
Now if you run locally it should work: npm run start
Those were the major steps that helped fix my JSX
complaint for running locally as well as sharing my custom component with others on npmjs. I created a public git repo with my code and a detailed step by step guide to help others, it can be found here.
Hopefully that helps!