2

I'm trying to extract certain compoennts in my React Application to a separate reusable component library.

What I've done, is cloned this project: https://rinsejs.io/ and subsequently referenced the github repo in my main projects package.json

entry in package json of core project

 "react-sharedlib": "git+ssh://git@github.com/myrepos/react-sharedlib.git#master",

Webpack.config inside react-sharedlib

// Path is in Node for free and will make simple resolving of directories no
// matter which part of your file system your library lives in
const path = require('path');

// Webpack is just a bunch of keys on module.exports!
module.exports = {
    // This is where our app starts. This is why we hnpm install --save-dev babel-core@6.4.5ave done all this importing
    // and exporting, to get to here
    entry: './src/index.js',
    // module (I know it's a bit weird to hanpm install --snpm install --save-dev babel-preset-es2015@6.3.13ave-dev babel-loader@6.2.1ve module.exports.module) is where we
    // define all the rules for how webpack will deal with thing.
    module: {
        // rules takes an array, each item containing the respective rules
        rules: [
            {
                // First up, our JavaScript rules.
                // If you want to use the .jsx extension, you can change this line to
                // test: /\.jsx?$/,
                // The ? in the regex just means "optional"
                test: /\.js$/,
                // Don't bother spending time transpiling your installed packages
                // exclude: /node_modules/,
                // This is where we tell webpack to use babel to transpile our JS.
                // The configuration can go here, but in this case it's in ./babelrc.js
                use: {
                    loader: 'babel-loader',
                },
            },
            {
                // I haven't used SCSS in the base example, but it's here for you if you
                // want! If you want to use CSS, you can change this next like's regex to
                // /\.(css|scss)$/ or even just /\.css$/
                test: /\.scss$/,
                use: [
                    // These three libraries are commonly used together to turn Sass into
                    // CSS, then be able to load the CSS directly with imports. From there
                    // It gets put in the DOM for you.
                    { loader: 'style-loader' },
                    { loader: 'css-loader' },
                    { loader: 'sass-loader' },
                ],
            },
            {
                // Some image formats so you can import images
                test: /\.(png|gif|jpg|svg)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 50000,
                    },
                },
            },
        ],
    },
    // Here we define explicitly the file types we intend to deal with
    resolve: {
        extensions: ['.scss', '.js', '.json', '.png', '.gif', '.jpg', '.svg'],
    },
    // This is where we define how everything gets output.
    // dist is a common output folder, and it should be gitignored. The build can
    // be run after publishing so you don't wind up with it in source control
    output: {
        path: path.resolve(__dirname, 'dist/'),
        publicPath: '',
        // You can do fun things here like use the [hash] keyword to generate unique
        // filenames, but for this purpose rinse.js is fine. This file and path will
        // be what you put in package.json's "main" field
        filename: 'rinse.js',
        // This field determines how things are importable when installed from other
        // sources. UMD may not be correct now and there is an open issue to fix this,
        // but until then, more reading can be found here:
        // https://webpack.js.org/configuration/output/#output-librarytarget
        libraryTarget: 'umd',
    },
};

Babel config inside shared-lib:

{
    "presets": ["@babel/env", "@babel/preset-react", "es2015", "react"],
    "plugins": ["@babel/plugin-syntax-dynamic-import"]
 }

Package.JSON inside shared-lib:

{
  "name": "react-sharedlib",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",
  "dependencies": {
    "@babel/preset-react": "^7.0.0",
    "babel-core": "^6.4.5",
    "babel-loader": "^6.2.1",
    "babel-preset-es2015": "^6.3.13"
  },
  "devDependencies": {
    "@babel/plugin-syntax-dynamic-import": "^7.2.0",
    "babel-preset-react": "^6.3.13"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/myrepos/react-sharedlib.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/myrepos/react-sharedlib/issues"
  },
  "homepage": "https://github.com/myrepos/react-sharedlib#readme"
}

When I try to build my project I get this error. (Which looks like a problem with babel in some capacity, not being able to reference the JSX syntax or needing a loader configured. Anyone any idea what I'm doing wrong here, or what other things to try? As you can see from my dependencies I've had a go at installing Babel loaders, but to no avail. I assume I may just be missing a piece of configuration somewhere to get it to recognise the HTML inside the JS file.

ERROR in /Users/moi/git/usersection/user-section/node_modules/react-sharedlib/src/components/Button/Button.js 23:8
Module parse failed: Unexpected token (23:8)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|       // along without changing any of the contents. This is basically just creating
|       // a copy to pass along
>       return <ButtonWrapper {...props}>{props.children}</ButtonWrapper>;
| }
| 
 @ /Users/moi/git/usersection/user-section/node_modules/react-sharedlib/src/components/Button/index.js 2:0-30 4:15-21
 @ /Users/moi/git/usersection/user-section/node_modules/react-sharedlib/src/index.js
 @ ./app/App.js
 @ ./index.js

Latest version of React btw. Webpack 4.29.6

Update: ** Following on from the answer posted below, my shared library webpack.config.js file now contains this entry which unfortunately made no difference.

  rules: [
        {
            // First up, our JavaScript rules.
            // If you want to use the .jsx extension, you can change this line to
            // test: /\.jsx?$/,
            // The ? in the regex just means "optional"
            test: /\.js$/,
            // Don't bother spending time transpiling your installed packages
            // exclude: /node_modules/,
            // This is where we tell webpack to use babel to transpile our JS.
            // The configuration can go here, but in this case it's in ./babelrc.js
            use: {
                loader: 'babel-loader',
                options: {
                    babelrcRoots: [".", "node_modules/react-sharedlib"]
                }
            },
        }

CORE PROJECT .babelrc:

{
   "presets": ["@babel/env", "@babel/preset-react"],
   "plugins": ["@babel/plugin-syntax-dynamic-import"]
}

SHARED PROJECT .babelrc:

{
    "presets": ["@babel/env", "@babel/preset-react", "es2015", "react"],
    "plugins": ["@babel/plugin-syntax-dynamic-import"]
 }
Squiggs.
  • 4,299
  • 6
  • 49
  • 89

1 Answers1

1

By default, Babel assumes that .babelrc files in node_modules are ignored, because they were probably published on accident, and usually they reference plugins and presets that are in their devDependencies and thus probably aren't installed. The config could even be for a different version of Babel, so even if they were all installed, they still might not work.

This means you need to either:

  • Tell Babel explicitly that node_modules/react-sharedlib is safe to load the config for.
  • Configure your application's Babel config to compile that specific node_modules/react-sharedlib.

The first can be accomplished by specifying:

babelrcRoots: [".", "node_modules/react-sharedlib"],

in babel-loader's options.

The second would require using a babel.config.js config file in your application, and exporting your project-wide plugins there, so that they apply to any file you pass to Babel.

The Babel docs for config files are also a good place to review.

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • Tried specifying that in the shared library config (assume that is where you meant?) didn't seem to make a difference to the project. See update to query. – Squiggs. Oct 01 '19 at 08:43
  • @Squiggs. I'm not sure I understand. Why do both your shared library and application have webpack configs? Normally you'd have one webpack config for the final application, with a bunch of common modules with no webpack configs. – loganfsmyth Oct 01 '19 at 12:28
  • https://github.com/cwlsn/rinse-react - this is the shared library (which seems to have a webpack config attached to it) perhaps that is where I'm going wrong! My assumption was that the shared component library needs to be able to build in its own right. Which I assume needs the webpack file to do so. – Squiggs. Oct 01 '19 at 12:41
  • There's only one webpack config used when making a bunch. A shared library could have a its own config if you were bundling it up before publishing it/committing changes to it, but that would not be used automatically by some other module using your share library. – loganfsmyth Oct 01 '19 at 13:16
  • I'm so confused I *think* that's what I'm doing. End goal Shared library pulled in via github into a node_modules folder, referenced via the node modules folder in a core project. Does the core project provide the bundling then? in its webpack config? I may go read a bit more, or explore some other examples. – Squiggs. Oct 01 '19 at 14:14
  • Unless you're explicitly running Webpack twice every time you change one of the library's files (once to compile the shared library, and then once to compile the overall application), then a config in the shared library would do nothing. An easy way to check would be to throw an exception inside the config file. – loganfsmyth Oct 01 '19 at 22:45