As per my knowledge next/babel in presets should transpile the code for non ES6 supporting browsers. But I can still find arrow functions, class, etc, in my /out folder. Also when I try to deploy this build it only works for chrome but not for IE or older versions of firefox.
Repo Link:
Steps to reproduce the behavior, please provide code snippets or a repository:
1) git clone https://github.com/mdvkmd/nextTranspileIssue.git nextTranspileIssue
2) cd nextTranspileIssue
3) npm install
4) npm run start
It should produce ES5 transpiled code in out folder and should work on IE 11, Firefox 30, etc
I've also tried the below babel.config (Will also attach more babel.configs that I have tried)
module.exports = function (api) {
api.cache(true);
const presets = [
[
'next/babel',
{
'preset-env': {
targets: {
browsers: ['last 2 versions', 'ie > 9']
},
corejs: '2',
useBuiltIns: 'usage',
loose: true
},
'transform-runtime': {
useESModules: false
}
}
]
];
const plugins = [
'inline-dotenv',
['module-resolver', { root: ['./src'] }],
['import', { libraryName: 'antd', style: 'css' }],
['emotion']
];
const env = {
test: { presets: [['next/babel']] },
production: { presets: [['next/babel', { 'preset-env': { modules: false } }]] }
};
return {
presets,
plugins,
env
};
};
But the above results in
Error occurred prerendering page "/recharge" https://err.sh/zeit/next.js/prerender-error: TypeError: Class constructor App cannot be invoked without 'new'
module.exports = function (api) {
api.cache(true);
const presets = [['next/babel',
{
'preset-env': {
targets: {
chrome: '58',
ie: '11'
},
modules: false
}
}],
'@emotion/babel-preset-css-prop'
];
const plugins = [
'inline-dotenv',
['module-resolver', { root: ['./src'] }],
['import', { libraryName: 'antd', style: 'css' }],
['emotion']
];
const env = {
test: { presets: [['next/babel']] },
production: { presets: [['next/babel', { 'preset-env': { modules: false } }]] }
};
return {
presets,
plugins,
env
};
};
Also tried the above babel.config still
Error occurred prerendering page "/abc" https://err.sh/zeit/next.js/prerender-error: TypeError: Class constructor App cannot be invoked without 'new'
Instead of using a custom Babel config for this, have you looked at using polyfills? There is a good example for this.
Next itself is compatible with the browsers you mentioned, but any third-party packages might not be. That is where the polyfills come in handy.
@jamesmosier I too read that next-babel covers the preset-env out of the box, but it doesn't converts the ES6 modules to ES5 like arrow function, async functions, etc
Just to confirm I also tried with the below config just for adding a few extra options for browsers.
const presets = [
[
'next/babel', {
'preset-env': {
targets: {
browsers: ['last 2 versions', 'ie > 9']
}
},
'transform-runtime': {
useESModules: false
}
}
],
'@emotion/babel-preset-css-prop'
];
Still no luck.
If you were to start an empty Next project, run next build, and then view the output it would properly transpile all of the assets for the browsers in question.
Once you start adding third-party NPM packages, that's when the polyfills would be useful.
As far as your specific Babel config, I'm not sure.
@abhinavnigam2207
In my experience it's not related to nextjs... as @jamesmosier mentioned this too often comes with npm thirdparty. So here's something that might help :
yarn add es-check --dev
Add scripts in your package.json
{
"clean": "rimraf --no-glob ./.next ./out",
"check:es:build": "es-check es5 './.next/static/**/*.js' -v",
"check:es:export": "es-check es5 './out/**/*.js' -v",
}
Then run yarn clean && yarn check:es:build for example
You'll probably end up with an error message. The tricky part is now to locate the incriminated package in the file (I generally open it, then format in webstorm, and guess the culprit).
yarn add next-transpile-modules --dev
Activate it in your next.config.js
const withTM = require('next-transpile-modules')([
// Those packages needs to be transpiled to be sure they pass `es-check es5`
'ky',
'@sindresorhus/is',
]);
module.export = withXX?(
withZZ?(
withTM({
// your next config
})
)
)
Then retry a build and a check.
Hope it helps
I also realized that you're using ant-design... So here's my current tricks to enable tree-shaking
const aliasPlugin = [
'module-resolver',
{
root: ['.'],
alias: {
_core: './src/core',
_assets: './src/assets',
_features: './src/features',
_components: './src/components',
_data: './src/data',
_backend: './src/backend',
_pages: './src/pages'
//....
},
},
];
const antdImportPlugin = [
'import',
{
libraryName: 'antd',
// 'es' will allow tree shking and thus you need to transpile afterwards
libraryDirectory: 'es',
// set this to true if you want the less customization and want to prevent modifying global styles
// @link https://next.ant.design/docs/react/customize-theme#How-to-avoid-modifying-global-styles?
style: 'css',
},
];
module.exports = {
env: {
development: {
presets: [['next/babel'], ['@emotion/babel-preset-css-prop']],
plugins: [antdImportPlugin, aliasPlugin],
},
production: {
presets: [['next/babel'], ['@emotion/babel-preset-css-prop']],
plugins: [antdImportPlugin, aliasPlugin],
},
test: {
presets: [['next/babel'], ['@emotion/babel-preset-css-prop']],
plugins: [antdImportPlugin, aliasPlugin],
},
},
};
"browserslist": {
"production": [
">1%",
"ie >= 11",
"edge >= 14",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
// We need to transpile this because we use the 'es' version
const withTM = require('next-transpile-modules')([
'antd',
'rc-util',
'rc-animate',
'rc-pagination',
'css-animation',
'rc-tabs',
]);
Far from perfect... but I could not find a better way till now.
I guess I was setting config.rules = [] rather than pushing into it. As I already had a .babel..config file my next.config was overriding it as instead of pushing I was setting the rules in it.
Below is the babel.config and next.config which solved my problem:
`module.exports = function (api) {
api.cache(true);
const presets = [['next/babel', {
'preset-env': {
// eslint-disable-next-line max-len
targets: '> 0.25%, not dead',
corejs: 2,
modules: 'commonjs',
forceAllTransforms: true,
useBuiltIns: 'usage'
}
}], '@emotion/babel-preset-css-prop'
];
const plugins = [
'inline-dotenv',
['module-resolver', { root: ['./src'] }],
['import', { libraryName: 'antd', style: 'css' }],
['emotion']
];
const env = {
test: {
presets: [
['next/babel', {
'preset-env': {
modules: 'commonjs'
}
}]
]
}
};
return {
presets,
plugins,
env
};
};
`
below is the next.config:
`webpack: (config, { isServer }) => {
config.output.publicPath = '';
if (isServer) {
const antStyles = /antd\/.?\/style\/css.?/;
const origExternals = [...config.externals];
config.externals = [ // eslint-disable-line
(context, request, callback) => { // eslint-disable-line
if (request.match(antStyles)) return callback();
if (typeof origExternals[0] === 'function') {
origExternals0;
} else {
callback();
}
},
...(typeof origExternals[0] === 'function' ? [] : origExternals)
];
config.module.rules.unshift({
test: antStyles,
use: 'null-loader'
});
}
if (ANALYZE) {
config.plugins.push(new BundleAnalyzerPlugin({
analyzerMode: 'server',
analyzerPort: 8888,
openAnalyzer: true
}));
}
config.node = {
fs: 'empty'
};
config.module.rules.push({
loader: 'babel-loader',
exclude: /node_modules/,
test: /\.js$/,
options: {
cacheDirectory: true,
plugins: [
['import', { libraryName: 'antd', style: 'css' }]
]
}
});
config.module.rules.push({
test: /\.less$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{
loader: 'less-loader',
options: {
modifyVars: themeVariables,
root: path.resolve(__dirname, './'),
javascriptEnabled: true
}
}
]
});
config.module.rules.push({
test: /\.css$/,
use: [
{
loader: 'css-loader'
}
]
});
return config;
}
`
Most helpful comment
@abhinavnigam2207
In my experience it's not related to nextjs... as @jamesmosier mentioned this too often comes with npm thirdparty. So here's something that might help :
Locate problems with es-check
Add scripts in your package.json
Then run
yarn clean && yarn check:es:buildfor exampleYou'll probably end up with an error message. The tricky part is now to locate the incriminated package in the file (I generally open it, then format in webstorm, and guess the culprit).
Transpile the package with next-transpile-modules
Activate it in your
next.config.jsThen retry a build and a check.
Notes
Hope it helps