reactjswebpackcraco

Craco, webpack and library creation


I am creating a small reactjs app which in the end will generate a single .js file (it's basically a chatbot frontend application, which talks to a backend). I have created a react app using npx create-react-app, and I have designed everything without problems.

Also I have created a webpack powered proof of concept to generate the js file, and that was working too. Long story short, it was all about specifying the output in the webpack.config.js file:

output: {

        path: path.resolve(__dirname, "public"),
        library: "StewieWidget",
        libraryTarget: "umd",
        umdNamedDefine: true,
        filename: "[name].js"
    }

Now, the generated app uses react-scripts under the hoods, and not webpack explicitly, to the best of my understanding. So, I don't know how to make it "emerge" and pass the above configuration. Also, while digging on Google, I have found that I could potentially use craco, and that's what I did. After reading its configuration, I have seen that, potentially, the webpack documentation can be injected like this:

const path = require('path');


module.exports = {
    style: {
        postcss: {
            plugins: [
                require('tailwindcss'),
                require('autoprefixer'),
            ],
        },
    },
    webpack: {
        configure: (webpackConfig, { env, paths }) => {
            webpackConfig.entry = {
                "mylib": './src/index.js'
            }

            webpackConfig.output = {
                path: path.resolve(__dirname, "public"),
                library: "mylib",
                libraryTarget: "umd",
                umdNamedDefine: true,
                filename: "[name].js"
            }
            console.log(webpackConfig);
            return webpackConfig;
        }
    },
    devServer: {
        port: 3000,
        open: false
    }
}

which is clearly not working, and if I launch the app with npm run start --verbose I see that it hangs like this:

enter image description here

which is not very helpful. The start command simply executes craco start.

So, my questions are:

  1. is craco che best way to handle this ?
  2. should I go straight on webpack usage ? If so, what's a good tutorial for something like I need to do (as a backend dev, webpack is always been a tough topic)

Thanks for help !


Solution

  • if you want to modify webpack.config.js in a react project created with npx create-react-app craco is a good solution https://www.npmjs.com/package/@craco/craco .

    after the installation you need to replace some lines of your package.json

    from

    ...
      "scripts": {
        "start": "react-script start",
        "build": "react-script build",
        "test": "react-script test",
        "eject": "react-script eject"
      },
    ...
    

    to

    ...
      "scripts": {
        "start": "craco start",
        "build": "craco build",
        "test": "craco test",
        "eject": "craco eject"
      },
    ...
    

    after that, in your root project add a file called craco.config.js

    inside the file you can add the code you want.. here just an example of my craco.config.js file I normally use (I added additional optional plugins like craco-alias and craco-plugin-scoped-css.. you don't need them, it's just an example)..

    module.exports = {
      plugins: [
        {
          plugin: require('craco-plugin-scoped-css'),
        },
        {
          plugin: require("craco-alias"),
          options: {
            source: "options",
            baseUrl: "./",
            aliases: {
              "@components": "./src/components",
              "@context": "./src/context",
              "@utils": "./src/utils"
            }
          }
        }
      ],
      webpack: {
        configure: {
          resolve: {
            fallback: {
              path: require.resolve("path-browserify"),
              crypto: require.resolve("crypto-browserify"),
              stream: require.resolve("stream-browserify"),
            },
          },
        },
        configure: {
          output: {
            publicPath: 'myAppUrl/'
          }
        }
      }
    }