Search code examples
node.jsreactjsnpmpackagepublish

Using self made npm package in react. Failed to compile


I followed https://zellwk.com/blog/publish-to-npm/ to create my custom npm package (https://www.npmjs.com/package/demo-to-publish). The folder structure of my custom package is as follows:

  1. src -> index.js
  2. node_modules
  3. List item
  4. Lable.js
  5. package.json
  6. webpack.config.js

Content of my package.json is as follows:

{
  "name": "demo-to-publish",
  "version": "1.0.5",
  "description": "testing publishing to npm",
  "main": "./src/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open --mode development",
    "build": "webpack --mode production"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.8.4",
    "@babel/preset-env": "^7.8.4",
    "@babel/preset-es2015": "^7.0.0-beta.53",
    "@babel/preset-react": "^7.8.3",
    "babel-loader": "^8.0.6",
    "webpack": "^4.41.5",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.10.3"
  },
  "dependencies": {
    "babel-preset-es2015": "^6.24.1",
    "react": "^16.12.0"
  }
}

Contents of my index.js in src folder are as follows:

import React, { Component } from "react";

export default class Button extends Component {
  render() {
    return (
      <div>
        <button>Click me</button>
      </div>
    );
  }
}

Contents of my webpack.config.js are as follows:

module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "index.js"
  },
  module: {
    rules: [
      {
        test: /\.js$|jsx/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env","@babel/preset-react"]
          }
        }
      }
    ]
  }
};

After publishing it to npm I installed it using npm i demo-to-publish in my new react cra app. I wrote the following code to use this package.

import Button from "demo-to-publish";
<Button/>

The error I am facing is in the screenshot attached below.

enter image description here

How to resolve this issue? Help me out as this is my first time publishing an npm package.


Solution

  • Issue

    The issue is that your code is not transpiled and so it is not properly recognised by the browser and hence errors. By default, create-react-app does not transpiles node_modules.
    You can find more here in a github issue https://github.com/facebook/create-react-app/issues/3889

    The node module has no errors, just transpilation is the problem.


    Fix

    After going through the repo (https://github.com/prak-mtl/demo-to-publish), there are 2 possible fixes which can be done and are listed below. Recommended solution will be 2nd one but it requires you to do the build and then publish

    Solution 1

    For this you need to do some changes in the both CRA and npm repo. You need to add a configuration in the babel config to transpile the specific node module. Since, CRA config is not changeable (unless you ejected the code), you need to add a additional configuration using override option.

    - Do this step in the demo-to-publish repo

    Inside the package.json of the npm package (i.e. https://github.com/prak-mtl/demo-to-publish/blob/master/package.json), you need to change the main path since we will be transpiling the code to new folder lib. Change it to ./lib/src/index.js and republish the package.

    - Do these steps in the CRA app

    1. Create a file (<any-name>.js, here let's say babel_override.js)
    2. Add the following code in babel_override.js:
    module.exports = {
        overrides: [
            {
                test: ["./node_modules/demo-to-publish"],
                presets: ["@babel/preset-react"]
            }
        ]
    }
    

    This will be used to transpile the code inside demo-to-publish in the node_modules folder in the CRA app

    1. You should have @babel/preset-react installed. If not, then install it.

    2. Delete and reinstall the demo-to-publish package in CRA app.

    3. Before running the project, code needs to be transpiled, so run the following command in the terminal

    NODE_ENV=development ./node_modules/.bin/babel ./node_modules/demo-to-publish -d ./node_modules/demo-to-publish/lib --config-file ./babel_override.js
    
    • `NODE_ENV can be development, test or production
    • -d ./node_modules/demo-to-publish/lib will published the transpiled code inside lib folder
    • --config-file is the babel override config created in step 1. You should get success result of type: Successfully compiled 3 files with Babel.

      1. Run the project agian, it should now run fine

    Solution 2 (Recommended)

    This approach requires you to build the npm package. Since you already have the webpack, it shouldn't be a problem. The following steps needs to be done in demo-to-publish repo

    1. Add library target as commonjs2 in the output. The webpack config will become something like this:
    module.exports = {
      entry: "./src/index.js",
      output: {
        filename: "index.js",
        libraryTarget: 'commonjs2' //This one the most important line, others things will remain same
      },
      module: {
        //Other code
      }
    };
    

    This will be used to output the build in dist folder.

    1. In the package.json (https://github.com/prak-mtl/demo-to-publish/blob/master/package.json), we need to update the main attribute. Change its value from ./src/index.js to ./dist/index.js
    2. Run npm run build in the repo. It should create a new folder dist containing one index.js file inside it
    3. Publish the npm package now

    Then, in the CRA app, install the package and run normally. It should work fine.

    Hope it helps. Revert for any doubts.