External React component library JSX Babel wont compile - javascript

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"]
}

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.

Related

How to transpile a node_module with webpack in a web worker?

I am trying to include a node module (primitive-ellipsoid) in my wepback project. The module is not transpiled to es5 so throws an error when used in the browser:
Uncaught Error: Module parse failed: /Users/kevzettler/code/crashgiants/node_modules/primitive-ellipsoid/index.js Unexpected token (8:4)
You may need an appropriate loader to handle this file type.
| // Default to an oblate spheroid
| const { latSegments = 32, lngSegments = 64, rx = 2, ry = 1, rz = 1 } = {
| ...options
| };
|
This project is an older create-react-app webpack that is ejected.
"webpack": "3.5.1",
"webpack-dev-server": "2.8.2",
"webpack-manifest-plugin": "1.2.1",
It is using babel and babel-loader and worker-loader I have a webpack.config.dev.js with rules like:
rules: [
{
// "oneOf" will traverse all following loaders until one will
// match the requirements. When no loader matches it will fall
// back to the "file" loader at the end of the loader list.
oneOf: [
// Process JS with Babel.
{
test: /\.(js|jsx)$/,
include: [
paths.appSrc,
],
exclude: /\.worker.js$/,
loader: require.resolve('babel-loader'),
options: {
// 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,
},
},
{
test: /\.worker.js$/,
exclude: /node_modules/,
use: [
'worker-loader',
require.resolve('babel-loader'),
]
}
]
I have babel configured in package.json with:
"babel": {
"plugins": [
"babel-plugin-transform-decorators-legacy"
],
"presets": [
[
"env",
{
"targets": "defaults"
}
],
"flow",
"react-app"
]
},
I have tried messing around with includes and excludes in the webpack.config.json to no success. I am confused if I need to focus on the worker-loader rule because it also uses the babel-loader or if the top level babel-loader gets applied as well.
UPDATE I only want to transpile the specific node_module/primitive-ellipsoid if I transpile the entire node_modules there is a bunch of other issues. I have tried
{
test: /\.(js|jsx)$/,
include: [
'node_modules/primitive-ellipsoid',
paths.appSrc,
],
exclude: /\.worker.js$/,
loader: require.resolve('babel-loader'),
options: {
// 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,
},
},
But this has the same error.
Your first rule isn't finding primitive-ellipsoid. As mentioned in the comments above, try removing the include from your first build rule:
{
test: /\.(js|jsx)$/,
exclude: /\.worker.js$/,
loader: require.resolve('babel-loader'),
options: {
// 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,
},
},
If that doesn't work, try adding another rule that will catch anything else as a fallback and see if it finds your library.

Unable to load stage-3 javascript file using babel-loader from webpack

Overview
Following the Auth0 documentation, they have a JavaScript file that has field variables (stage-3). When running my app, I get the following error:
ERROR in ./src/auth/AuthService.js
Module parse failed: Unexpected token (7:16)
You may need an appropriate loader to handle this file type.
|
| export default class AuthService {
| authenticated = this.isAuthenticated();
| authNotifier = new EventEmitter();
|
Above, the unexpected token is the first = sign after authenticated.
Diagnosing the Error
Downloading and running the sample project from Auth0's Github works successfully.
Running the following command using babel-cli parses the file successfully:
$ node node_modules\babel-cli\bin\babel.js src\auth\AuthService.js --presets stage-3
It is only when I run the application that the error is thrown, so I suspect there's something fishy in the webpack config.
My Configuration
The following is my .babelrc config:
{
"presets": [
["env", { "modules": false }],
"stage-3"
],
"plugins": ["transform-runtime"]
}
I've only included the relevant parts of my webpack config, but can provide the full file if necessary:
var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
rules: [
// ...
{
test: /\.js$/,
loader: 'babel-loader',
include: [path.join(__dirname, '..', 'src')],
},
// ...
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json'],
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
performance: {
hints: false
},
devtool: '#eval-source-map'
}
// ...
Dependencies Info
The following are the babel/webpack dependency versions in my project:
"babel-core": "^6.26.0",
"babel-eslint": "^8.2.2",
"babel-loader": "^7.1.4",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.0",
"babel-preset-stage-3": "^6.24.1",
"webpack": "^3.6.0",
With All That Said
How can I further figure out what is causing the error to be thrown? It's pretty specific, but it's clear that babel can process the file just fine using the babel-cli. After spending many hours researching this issue, trying different options in the webpack config, using .babelrc and forcing webpack to not use it, using stage-2 instead of stage-3, I feel like I've tried everything.
My configuration isn't much different than the one in Auth0's sample project. Copying and pasting their .babelrc file into mine as well as their js webpack rules didn't seem to have an effect either; I just can't get it to work with my project.
I've found that most people that have had webpack problems (after ruling out the loader issue) have the issue because there is something incorrect setup in your webpack config.
For my webpack config, I needed to change this:
module: {
rules: [
// ...
{
test: /\.js$/,
loader: 'babel-loader',
include: [path.join(__dirname, '..', 'src')],
},
// ...
]
},
to this:
module: {
rules: [
// ...
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
// ...
]
},
Because my webpack.config.js file existed under src, so the issue might've been that the .. argument in my include property wasn't pointing to the right folder to look for .js files in.
I needed to exclude node_modules because it would otherwise try to parse files in that directory.

Node JS Webpack Babel with async

When trying to compile my server-side code, I get the following error:
Module parse failed: (...babel-loader-path)?{"presets":["es2015-node4","es2015"]} (...) Unexpected token (86:6)
You may need an appropriate loader to handle this file type.
This error seems to be caused by an Async function that I am trying to import. Do I need to change my webpack configuration?
My webpack config file:
const webpack = require('webpack');
module.exports = {
target: 'node',
entry: ['./server/index.js', './node_modules/webpack/hot/poll?1000'],
output: {
path: './dist',
filename: 'server.bundle.js',
libraryTarget: 'commonjs',
},
resolve: {
extensions: ['', '.js', '.jsx'],
},
externals: [/^[a-z]/],
module: {
loaders: [{
test: /\.jsx$/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015-node4', 'es2015'],
},
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015-node4', 'es2015'],
},
}
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
devtool: 'source-map',
};
If you are using Webpack to compile your Node code, then that is not a good approach. You should simply use babel-node which is an amazing way to transpile your node code.
For that in your package.json do the following
"scripts": {
"dev": "node_modules/.bin/nodemon --exec babel-node server/index.js",
"prestart": "node_modules/.bin/babel server --out-dir dist",
"start": "node dist/index.js"
},
"devDependencies": {
"#babel/cli": "^7.0.0-beta.40",
"#babel/core": "^7.0.0-beta.40",
"#babel/node": "^7.0.0-beta.40",
"#babel/preset-env": "^7.0.0-beta.40",
"#babel/preset-stage-2": "^7.0.0-beta.40",
"nodemon": "^1.11.0"
}
In your .babelrc file, do the following.
{
"presets": [
"#babel/preset-env",
"#babel/preset-stage-2"
]
}
Then in your project directory create a folder called server and in that folder create a file called index.js which creates your node http server.
For a reference have a look at Babel-Node Documentation
Or have a look at this amazing small tutorial kind of example created by the awesome folks at Babel Example Node Server Using Babel-Node
P.S: In the package.json file the npm run dev watches your code and npm start commands compiles your code ready to be shipped for production.
There seems to be a mis-understanding with regard to the babel preset usage. The preset you want is not the target version of javascript you want to output. For that you need to set target appropriately. Instead you needed the preset that corresponds to the version of javascript you are writing in. The presets are collections of transformers that instruct babel how to deal with specific javascript constructs.
In babel <=6 you need either: es2017 or transform-async-to-generator presets to use the async keyword. After babel 7 the recommendation is to use:
{
"presets": ["#babel/preset-env"]
}
This allows babel to support all modern java-script syntax's that have been finalized. It will then transpile to whatever syntax your target setting indicates. I personally would use a browserslist query in package.json for this so other tools like postcss automatically pick up the same target information.

How to use webpack with babel-loader and flow

I'm struggling with what I feel shouldn't be too hard of a setup.
I want these three technologies to work together:
webpack to bundle code
babel so that I'm able to write modern JavaScript
flow because type checking is helpful just like tests and linter
I've already gone trough several setups of this but none of the articles I've found on the web appears to be helpful.
I've defined 3 scripts in my package.json, run, flow and build.
Typechecking with yarn run flow works perfectly, and so does executing the script trough babel-node using yarn run start.
But when I execute yarn run build the following error appears trough webpack:
$ ./node_modules/webpack/bin/webpack.js
Hash: 207d42dac5784520fc99
Version: webpack 3.10.0
Time: 49ms
Asset Size Chunks Chunk Names
bundle.js 2.65 kB 0 [emitted] main
[0] ./src/main.js 181 bytes {0} [built] [failed] [1 error]
ERROR in ./src/main.js
Module parse failed: Unexpected token (3:5)
You may need an appropriate loader to handle this file type.
| // #flow
|
| type Foo = {
| foo: string,
| };
error Command failed with exit code 2.
It appears to me that the type annotations don't get removed correctly at the right point. Sadly this also happend if I specify the babel options in webpack directly as opposed to the .babelrc.
This currently defeats me in bundling up a bunch of .js files whilst using flow and while I found several plugins that supposedly strip flow annotations simply using the flow preset is what flowtype.org appears to recommend.
For reproducibillity, my project files look like this:
package.json:
{
…
"dependencies": {},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.0.3",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"babel-preset-flow": "^6.23.0",
"flow-bin": "^0.60.1",
"webpack": "^3.9.1"
},
"scripts": {
"build": "./node_modules/webpack/bin/webpack.js",
"start": "./node_modules/babel-cli/bin/babel-node.js src/main.js",
"flow": "./node_modules/flow-bin/cli.js"
}
}
.flowconfig:
[include]
./src
[ignore]
[libs]
[lints]
[options]
.babelrc:
{
"presets": ["env", "flow"]
}
webpack.config.js:
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/main.js',
output: {
path: __dirname,
filename: 'bundle.js',
},
resolve: {
modules: [
path.resolve('./src/'),
'node_modules',
],
extensions: ['.js'],
},
module: {
rules: [
{
test: '/.js$/',
loader: 'babel-loader',
},
],
},
};
src/main.js:
// #flow
type Foo = {
foo: string,
};
const defaultFoo: Foo = {
foo: 'bar',
};
console.log(defaultFoo);
Download the relevant presets and add them to the webpack.config.js as follows:
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015', 'stage-0', 'react']
}
}
}
]
}

npm link with webpack - cannot find module

I'm trying to npm link a module to a project using webpack as its bundler. Of course, after trying many things, I keep getting this error:
ERROR in ./src/components/store/TableView.jsx
Module not found: Error: Cannot resolve module 'react-bootstrap-table'
Here are the exact steps I take when doing this:
1.) cd ../forks/react-bootstrap-table
2.) npm link
(success, checked ~/.nvm/.../node_modules/react-bootstrap-table for symlink and it's there)
3.) cd ../../projRoot/
4.) npm link react-bootstrap-table
(no errors thrown?, says successful link)
5.) node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js
Solutions I've tried:
- https://webpack.github.io/docs/troubleshooting.html
- How to make a linked component peerDepdencies use the equivalent node_modules of the script being linked to?
- And many purple links on google serps
webpack.config.js
const webpack = require('webpack')
const path = require('path')
const ROOT_PATH = path.resolve(__dirname)
module.exports = {
devtool: process.env.NODE_ENV === 'production' ? '' : 'source-map',
entry: [
'webpack/hot/only-dev-server',
'./src/index.js'
],
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: ['react-hot','babel']
},
{
test: /\.scss$/,
loaders: ['style','css','sass'],
exclude: /node_modules/
},
{
test: /\.css$/,
loaders: ['style','css']
},
{
test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader'
}
]
},
resolve: {
extensions: ['', '.js', '.jsx'],
fallback: path.resolve(__dirname, './node_modules')
},
resolveLoader: {
fallback: path.resolve(__dirname, './node_modules')
},
output: {
path: process.env.NODE_ENV === 'production' ? path.resolve(ROOT_PATH, 'app/dist') : path.resolve(ROOT_PATH, 'app/build'),
publicPath: '/',
filename: 'bundle.js'
},
devServer: {
contentBase: path.resolve(ROOT_PATH),
historyApiFallback: true,
hot: true,
inline: true,
progress: true,
stats: 'errors-only',
host: '192.168.1.115'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
}
Notes:
1. this is the only symlink in the project
2. I run npm install inside forked version (also tried without, doesn't work)
3. I use NVM, but I have used symlinks before without webpack successfully.
I've been at this for a few days now, any help will be much appreciated.
I was facing a similar issue with webpack and ended up by adding this my webpack.config.js:
module.exports = {
resolve: {
symlinks: false
}
};
Here is the link to webpack docs. Since your question there happened a lot to webpack and their api, so I do not know how much relevance my answer still has according to your question. But for people facing this or a similar issue today this could be a solution. As to be seen, there are still people complaining about:
Webpack GitHub Issue 1643
Webpack GitHub Issue 1866
Also make sure you have bundle and yarn installed and executed in the linked package
Okay guys, this is specific to my use case, but make sure to follow all the instructions to completely build the library you are symlinking. Initially, I a npm install and gulp build, but that wasn't enough. I had to run a few extra commands to get the library to fully build.
Now it works! If you are still having issues, go through the documentation for each library you are symlinking, and use my webpack config as a template for resolving external libraries.
Just in case it's useful for others, the solution of adding the resolve.symlinks configuration to false suggested by #Beat was not enough in my case, I had to perform the following steps to solve it:
In the library:
Setup the libraries that are generating issues as peerDependencies in the package.json instead of dependencies or devDependencies, e.g. in my case react:
"peerDependencies": {
"react": "^16.8.6",
...
}
run npm install
build the library (in my case, with a rollup -c npm script
In my main app:
change the version of my library to point to my local project with a relative path in package.json, e.g.
"dependencies": {
"my-library": "file:../../libraries/my-library",
...
}
Add resolve.symlinks = false to my main app's webpack configuration
Add --preserve-symlinks-main and --preserve-symlinks to my package.json start script, e.g:
"scripts": {
"build": "set WEBPACK_CONFIG_FILE=all&& webpack",
"start": "set WEBPACK_CONFIG_FILE=all&& webpack && node --preserve-symlinks-main --preserve-symlinks dist/server.js",
}
run npm install
run npm run start

Categories

Resources