Hi,
Last year I found a solution to allow Babel to process files in node_modules using something like this:
const webpackConfig = Encore.getWebpackConfig();
const babelLoader = webpackConfig.module.rules.find(rule => {
if (rule.use && rule.use[0]) {
const firstUse = rule.use[0];
return firstUse.loader === 'babel-loader';
}
return false;
});
babelLoader.exclude = /node_modules\/(?!bootstrap\/).*/;
module.exports = webpackConfig;
But in the recent versions, when I run yarn run encore production I get the files from Bootstrap without being transpiled, which not happens in my regular files.
I am using the file babelrc to configure Babel:
{
"presets": [
[
"@babel/preset-env",
{
"debug": true,
"useBuiltIns": "usage",
"corejs": 3,
"targets": "> 0.25%, not dead"
}
]
]
}
The weird thing is that if I configure Babel through webpack.config.js:
.configureBabel(function(babelConfig) {
}, {
include_node_modules: ['bootstrap']
})
it works perfect. So I don't know the difference between the two solutions. Is there any implementation detail under this case that causes the first solution not valid (as I said, last year it works well)?
Something more... if I copy the babel config from file babel.js to .babelrc:
{
"presets": [
[
"@babel/preset-env",
{
"targets": {},
"modules": false,
"forceAllTransforms": true,
"useBuiltIns": "entry"
}
]
],
"plugins": ["@babel/plugin-syntax-dynamic-import"]
}
It doesn't work neither. I have tried to replicate the logic of option include_node_modules in my webpack.config.js:
const webpackConfig = Encore.getWebpackConfig();
const babelLoader = webpackConfig.module.rules.find(rule => {
if (rule.use && rule.use[0]) {
const firstUse = rule.use[0];
return firstUse.loader === 'babel-loader';
}
return false;
});
babelLoader.exclude = (filePath) => {
if (!/(node_modules|bower_components)/.test(filePath)) {
return false;
}
const whitelistedModules = ['bootstrap'].map(
module => path.join('node_modules', module) + path.sep
);
for (const modulePath of whitelistedModules) {
if (filePath.includes(modulePath)) {
console.log('hi');
return false;
}
}
return true;
};
module.exports = webpackConfig;
The callback is executed when run yarn run encore production and returns false as expected but I still gets the spread operator in the resulting file that contains the Bootstrap code. However, if I use:
.configureBabel(function(babelConfig) {}, {
include_node_modules: ['bootstrap']
})
it works as expected. I can't find the difference between the two methods so I think there is something in the middle that breaks my alternative when using the .babelrc file.
Note that in the latest version of Encore, you can now use the include_node_modules (well, its new name is includeNodeModules but include_node_modules still works with a deprecation warning) even when using an external babel config, by passing null as the first argument to configureBabel.
Yeah, I know! But my question is about the difference in the two methods because it seems that using .babelrc file doesn't perform the same result as using the configureBabel method
Hi @ger86,
I can't see any reason why it wouldn't work since the exclude rule is not handled by Babel but by Webpack itself.
I did a quick test with the following files and it seems to be fine:
// webpack.config.js
const Encore = require('@symfony/webpack-encore');
Encore
.disableSingleRuntimeChunk()
.setOutputPath('build/')
.setPublicPath('/')
.cleanupOutputBeforeBuild()
.addEntry('main', './src/index.js')
;
const config = Encore.getWebpackConfig();
const babelLoader = config.module.rules.find(
rule =>
rule.use &&
rule.use[0] &&
rule.use[0].loader === 'babel-loader'
);
babelLoader.exclude = /node_modules\/(?!bootstrap\/).*/;
module.exports = config;
// src/index.js
require('bootstrap/js/src/popover.js');
Without the babelLoader.exclude = ... line:
$ fgrep -Rnil '...' ./build | wc -l
1
With it:
$ fgrep -Rnil '...' ./build | wc -l
0
Would you be able to share a repository that could show this issue?
Sure, I will post a repository with the failing code this weekend. Thanks
Hi,
I have created a repo: https://github.com/ger86/webpackencore-babel with my config and the steps to reproduce in the Readme.md.
As you will see, when there is a .babelrc file, you get the spread operator in the resulting file.
I would love to know the explanation of what is happening because I have been unable to find it after many hours.
Thanks
@ger86 I think that the exclude rule isn't actually the issue.
No matter which one of the config listed in your webpack.config.jsyou are using, Babel do process Bootstrap's files.
However, it doesn't do it with the same config than the one used for your files:
.babelrc file it uses the configuration provided by Encore, which applies project-wide.babelrc you are using a file-relative configuration which only applies to the current package... and not to Bootstrap (Babel would use its .babelrc if it had one).As noted on the following page a babel.config.js file should work better in your case: https://babeljs.io/docs/en/configuration#what-s-your-use-case
Hi @ger86,
Just a simple question, what's your need to transpile Bootstrap source code, when you can only include what you need of Bootstrap thanks to the files in js/dist.
The files in the js/dist are already transpiled separately
import 'bootstrap/js/dist/dropdown'
@Johann-S Not sure how useful it would be (if at all), but one possible use-case would be to use their own targets instead of the ones used during Bootstrap's release process.
@ger86 I think that the
excluderule isn't actually the issue.No matter which one of the config listed in your
webpack.config.jsyou are using, Babel do process Bootstrap's files.However, it doesn't do it with the same config than the one used for _your_ files:
- without the
.babelrcfile it uses the configuration provided by Encore, which applies project-wide- with the
.babelrcyou are using a file-relative configuration which only applies to the current package... and not to Bootstrap (Babel would use its.babelrcif it had one).As noted on the following page a
babel.config.jsfile should work better in your case: https://babeljs.io/docs/en/configuration#what-s-your-use-case
Ahhh, maybe that is the "problem" what causes that behaviour. I don't know about another .babelrc. Maybe we can complete the docs explaining that in order to help other users that have the same problem
Hi @ger86,
Just a simple question, what's your need to transpile Bootstrap source code, when you can only include what you need of Bootstrap thanks to the files in
js/dist.
The files in thejs/distare already transpiled separatelyimport 'bootstrap/js/dist/dropdown'
Yes, because when Bootstrap 4 was released the files in dist was not ES6 modules, so I can't use in that way..
@ger86 according to what you said, you should think about updating your Bootstrap version because we released several security fixes and you'll be able to use the dist files