babel 7 ignores files outside of current directory - javascript

Say I have following project structure (Well its more complex than below structure):
CommonComponents
CommonComponentA
CommonComponentB
package.json
webpack.config.js
.babelrc
ModuleA
ComponentC //import CommonComponentA
ComponentD
package.json
webpack.config.js
.babelrc
ModuleB
ComponentE //import CommonComponentB
ComponentF
package.json
webpack.config.js
.babelrc
I compile, bundle and utilize ModuleA and ModuleB separately. When I switched to babel 7, importing modules from CommonComponents directory stopped working. Babel ignores files which are outside current working directory and doesn't transpile them so webpack compilation fails complaining 'Unexpected token' at imported component.
From what I have understood so far, they have changed the way .babelrc lookup happens. I really can't wrap my head around the terms 'root', 'babelrcRoots', etc.
Can someone explain what I will need to do in order to compile ModuleA and ModuleB succesfully from their respective working directory ?

Based on the real structure of your project (it is a monorepo setup with a root folder?) and the webpack config you are using, you can have several ways to solve this, one way could be by adding the include key on you babel loader rule on webpack configuration files, you will end up with something like this:
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
include: path.resolve(__dirname, '../CommonComponents'),
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
}
]
}
as stated before, this depends on your real project structure, but you can give it a try and check it works.

Related

Using local npm libraries with es6, babel, and webpack

I'm running into an issue that appears to be due to my lack of understanding with webpack. I have created a file structure that looks like this:
|-serverless-cloud-functions
||-my-local-libs
|||-twilioClient
||-service1
||-service2
twilioClient is a library that I made, that needs to be included in service1 and service2. Because of limitations with the serverless framework, you can not bundle files outside of the service, so the only option (I think) is to use a npm install ../my-local-libs/twilioClient from inside a service folder. This works for installing the module, but now it resides in node_modules. Currently, I am using webpack and babel as well.
I believe my root issue is that my webpack config looks like this:
const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");
module.exports = {
entry: slsw.lib.entries,
target: "node",
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/
}
]
}
};
Which excludes my es6 twilioClient lib, because it is in the node_modules folder.
I saw a couple people suggest that this was the way to accomplish 'exclude everything in node modules besides twilioClient':
module.exports = {
entry: slsw.lib.entries,
target: "node",
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules\/(?!(twilioClient))/
}
]
}
};
But this did not work in my case. Any help is greatly appreciated.
Instead of trying to exclude twilioClient, you could use Babel to compile it separately. Something like this (in the twilioClient directory):
npx babel src --out-dir lib
In twilioClient/package.json, you could then set main to lib/index.js instead of src/index.js so that importing scripts will get the compiled version:
"main": "lib/index.js",
Then instead of hosting twilioClient alongside service1 and service2, you could just push it to github, and install it in each client using npm:
npm install --save http://github.com/your_github_username/twilioclient.git
Now you can use twilioClient as if it were any other npm dependency.
I have encountered a similar problem of using local common package with babel.
If you would like to not change the main since you also actively edit the package and do not want to run the build each time you make a change, then you should use the below babel.config.js
module.exports = function(api) {
api.cache(true);
const plugins = [
'#babel/plugin-transform-modules-commonjs',
];
return {
plugins,
ignore: [
/node_modules\/(?!(your-pkg)\/)/,
],
};
};
This transpiles the code for your-pkg into node_modules dir in dist.

javascript + gulp + babel + webpack. error: Module not found: Error: Can't resolve 'babel-loader'

I'm creating a javascript project. To create it I'm using gulp and babel.
My problem is that I can't develop my code over multiple file, so I'm search a solution to 'enable' importing. At the moment I'm trying to configure webpack.
The Gulp Task is this:
gulp.task('webpack', () => {
return webpack_stream(webpack_config)
.pipe(rename('webpack_code.js'))
.pipe(gulp.dest('.build/asset/webpack/'));
});
The webpack.config.js is this:
module.exports = {
entry: ['./src/asset/js/main.js'],
output: {
filename: 'bundle.js',
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.(js)$/,
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: [
['env', 'stage-0',{ modules: false }],
],
},
},
],
},
resolveLoader: {
modules: ['./node_modules'],
},
resolve: {
modules: ['./node_modules'],
},
target: 'node',
};
My current error is this:
Error in plugin 'webpack-stream'
Message:
multi ./src/asset/js/main.js
Module not found: Error: Can't resolve 'babel-loader' in ...
What's wrong?
Another Question: What's I have to put as value of entry key? Only the entry point js file or the whole files of the project?
Thanks!!
What's wrong?
I'd guess that in your project, your Webpack instance is not finding the babel loader because of your config / environment specific issues.
I've had the exact same issue as you. Here are some troubleshooting steps for to check first:
See if babel-loader is actually installed. I know it is simple, but it can save you time.
Check which Webpack/Babel versions you're dealling with in your package.json file. I'm using Webpack 4 and Babel 8. Sounds like some newer versions doesn't accept this: use: 'babel' in your webpack.config file. You need to ensure that the -loader is being used as it follows: use: 'babel-loader'.
Reinstall your node_modules folder. Sometimes it works.
Another Question:
What's I have to put as value of entry key?
Only the entry point js file or the whole files of the project?
Accordingly to Webpack's docs:
The entry object is where webpack looks to start building the bundle. The context is an absolute string to the directory that contains the entry files. - Webpack Ref
Considering that, you should pass to the entry object, the path of a folder or a file that will be used to generate your final JS file with all your modules in it.
If you have nested files, that you don't import as modules, I think you'll have to head to the docs and see this specific case.
But if this files are nested and are being imported as modules, in your entry file/folder, they will be generated in the output file.
I know it's not much but following these steps, helped me to solve it. :)

Bundling non-native npm modules with Webpack

Description
I have a nodejs + TypeScript + express project and currently the source *.ts files are being bundled with webpack and node_modules is ignored with webpack-node-externals.
When I deploy bundle.js in Docker, I would need to still run npm i --production on the target image to install the dependencies, which installs all the modules listed in package.json
The Problem:
If I am using only one function from lodash which does not have native parts, the whole lodash module (4.8MB) is installed nonetheless (which is intended).
This results in a huge node_modules folder where functions inside packages aren't always necessarily used in bundle.js. This problem is especially prevalent when containerizing the application with Docker.
Is there any way to bundle non-native modules with Webpack while leaving native modules alone?
This is very similar to https://stackoverflow.com/a/54393299/2234013 - I believe you're looking for nodeExternals({ whitelist }) and babel-loader exclude:
// excerpt from https://stackoverflow.com/a/54393299/2234013
externals: [
nodeExternals({
whitelist: [/lodash/]
})
],
...
module: {
rules: [
{
...
exclude: /node_modules\/(?!(lodash).*/,
use: {
loader: 'babel-loader',
...
}
}
]
}

How can I import React Components as a package/module from some other(non-project) directory?

I have a couple of React Components in a folder, which is not a react project. The Directory Structure i am following for components is:
~/components/Component1/index.jsx
~/components/Component2/index.jsx
Now I have a React project (built with create-react-app), named "myapp" I want to import those React Components as a package or module in my project.
I have tried mentioning a dependency in my package.json, but gives an error, because I can't mention absolute paths in package.json.
I don't want to publish these components as a npm package.
Kindly help me with this
The problem was:
I was trying to wrap material-ui components like iconButton, iconMenu, etc. to make the components easy to use programatically. To put them into a git repository I need a example directory with a seperate react project using the components I developed. So, I need to develop a package that hold components' definitions and exporting them to be used in other project. I want to keep my implementations private so I cannot even publish it to npm.js.
[you can see the question statement for thorough understanding of thr ptoblem.]
Coming to the solution help me doing the needed, I created a new project with yarn adding minimal dependencies. i.e.
babel
babel-cli
babel-core
babel-loader
babel-preset-es2015
babel-preset-react
babel-preset-stage-2
html-webpack-plugin
raw-loader
webpack
webpack-dev-server
and then devDependencies
react
react-dom
material-ui [occasional]
After the installations, [HERE COMES THE PART] I created a webpack.config.js with following script:
const path = require('path')
const webpack = require('webpack')
module.exports = {
devtool: 'cheap-eval-source-map',
entry: './docs/entry.js',
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
resolve: {
alias: {
genericcomponents: path.join(__dirname, 'src')
}
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
}
]
},
devServer: {
contentBase: 'docs/'
}
}
In the code above, after mentioning the output the entry, devtool and output of the transpilation process. I actually have another thing to define, which is alias, I defined the alias with the directory holding the components.
Now this package will hold all the components with the name I provided in the alias parameter.
After that I mentioned loaders for transpilation and file format to jsx, so It will accept the source with JSX Syntax.
And at last I mentioned my the directory where I placed my index.html and entry.js file.
Following is the directory structure of my project:
I have my App.jsx Component in docs folder. which can now import any of the components in the components folder by the giving the package name.
You are welcome to discuss of any of the problem occurred in the above solution.
I know the answer might sound very basic but is there any reason why don't you just copy paste the components into the new app and just use them as any other component ?

React webpack / browserify "unexpected token"

I have this npm module that I created and every time I try to include it to see if it works I get this error:
Unexpected token <
You may need an appropriate loader to handle this file type.
I've used react-starterkit and included it in main.js like so
var ReactDOM = require('react-dom');
var ColorPicker = require('color-picker-react');
ReactDOM.render(<ColorPicker />, document.getElementById('app'));
then when i run gulp which runs webpack I get the error. Here's the webpack.config.js
module.exports.getConfig = function(type) {
var isDev = type === 'development';
var config = {
entry: './app/scripts/main.js',
output: {
path: __dirname,
filename: 'main.js'
},
debug : isDev,
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}]
}
};
if(isDev){
config.devtool = 'eval';
}
return config;
}
I've tried everything I could think of and still can't get it to work. I'm not using ES6 anywhere and I've tried many different react starter kits but I just can't get it to work. Please help!!!
P.S. I am able to get the project to run when I clone it locally and build out app.js with browserify like so: browserify -t [ babelify --presets [ react ] ] app.js -o bundle.js
To solve the problem you need to remove the line exclude: /node_modules/ if you are not the author of the npm module (But you should go with another module).
The component color-picker-react doesn't seem to have a release build or script that compile the jsx. So you need to do it by your own and compile the jsx file on the fly using wepack.
Instead of just removing the exclude: /node_modules/
You can exclude all /node_modules/ except the /node_modules/color-picker-react folder by using a regex pattern :
//will exclude all modules except `color-picker-react`
exclude: /node_modules\/(?!color-picker-react).*\//,
EDIT Basics for creating a npm module:
A correct setup for a npm module is to add a prepublish script to
ensure compilation happens automatically before uploading to NPM.
Thus when you push your module to npm the users doesn't need to compile the module they can just require it.
Taking an example of a node_module:
https://github.com/securingsincity/react-ace/blob/master/package.json
The package.json file is saying which file is the entry point when you required the module
"main": "lib/ace.js",
You can see in the github repository that the lib folder doesn't exist because added to the .gitignore but the line
"prepublish": "npm run clean && npm run build"
is run before uploading to NPM so on the npm repository the lib/ folder exist and you can see it when you do npm install --save react-ace the lib folder appears in the node_modules/react-ace/ folder
A great link that explains how to build npm modules in es6 for example http://javascriptplayground.com/blog/2015/10/authoring-modules-in-es6/
EDIT explain what needs to be done on react-color-picker module :
Sorry i didn't see that you was the author of the module so you should go with the solution below.
The react-color-picker for example doesn't have a prepublish script and the main file is index.js which is
var ColorPicker = require('./colorpicker.js'); // require a file with jsx will throw an error if not precompiled
module.exports = ColorPicker;
So a syntax error is thrown.
To be able to use the npm module in your other applications :
Create a webpack config for the npm module to handle the conversion of your react component written using jsx (you can take some of the webpack configs of this module https://github.com/securingsincity/react-ace set libraryTarget: 'umd' you module will be more easy to consume from various module systems (global, AMD, CommonJS).)
add a prepublish script that output a precompiled version of the color picker (lib/pickedprecompiled.js)
change the main to "main": "lib/pickedprecompiled.js",

Categories

Resources