After updating our app from Next.js 7.0.2 to 9.0.2 enzyme’s shallow rendering (same issue with enzyme’s mount) for the custom <App>
(_app.is) not working anymore. The local development server is serving the app perfectly fine, though.
For experimental purposes we also tried running our tests with Next.js 8.1.0 and the rendering caused no problems.
Clone the issue repository:
https://github.com/rzschoch/next-9-issues/tree/shallow-issue
npm install
npm run test
TypeError: Class constructor App cannot be invoked without 'new'
The test in /src/pagesSpecs/_app.spec.js
should be rendered without issues and compared against the existing snapshot (from Next.js 7.0.2).
Hey @rzschoch, could you test it with the latest canary? There should be a fix for it.
Hi @huv1k 9.0.3-canary.5 does not fix it, unfortunately.
That’s @huv1k solution for now (thank you):
“We updated our build to use modern javascript with esmodules in this PR (https://github.com/zeit/next.js/pull/7014). There is a problem that node doesn't support it yet so you need to use for your tests current node. You can achieve this with this .babelrc:“
{
"presets": ["next/babel"],
"plugins": ["inline-react-svg"],
"env": {
"test": {
"presets": [
["next/babel", { "preset-env": { "targets": { "node": "current" } } }]
],
"plugins": ["dynamic-import-node"]
}
}
}
Now it should work just with canary @rzschoch https://github.com/zeit/next.js/pull/8181
It is now working fine with the latest canary (9.0.3-canary.6 in my case) and a .babelrc
like so:
{
"presets": ["next/babel"],
"plugins": ["inline-react-svg"]
}
Same issue in 9.0.3
not happen in 9.0.2
I have the same problem with 9.0.3 on a HOC of the custom _app.ts. I get the same error at super(props) in constructor of HOC.
compiled line:
_this = Object(_babel_runtime_corejs2_helpers_esm_possibleConstructorReturn__WEBPACK_IMPORTED_MODULE_16__["default"])(this, Object(_babel_runtime_corejs2_helpers_esm_getPrototypeOf__WEBPACK_IMPORTED_MODULE_17__["default"])(WithI18next).call(this, props));
source:
const withI18next = (WrappedApp: typeof App) => {
const WrappedComponentWithSSR = withSSR()(WrappedApp)
...
class WithI18next extends App<WithI18nextProps> {
public static displayName = `WithI18next(${WrappedApp.name || 'App'})`
...
public constructor(props: WithI18nextProps) {
super(props)
...
}
The latest canary didn't work for me, but the following did:
{
"plugins": [],
"presets": [
[
"next/babel",
{
"preset-env": { "targets": { "node": "current" } }
}
]
]
}
Just a data point, I was able to resolve this issue with unit testing a custom _app.js
by giving my App
subclass a no-op constructor
:
// This no-op constructor helps with an error:
// TypeError: Class constructor App cannot be invoked without 'new'
constructor(props) {
super(props);
}
Still same problem in [email protected]
, my _app.js
and _document.js
files are exactly same as this example project about styled-component
.
here is my .babelrc
-
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-flow",
[
"next/babel",
{
"preset-env": { "targets": { "node": "current" } }
}
]
],
"plugins": [
[
"@babel/plugin-proposal-decorators",
{ "legacy": true }
],
[
"styled-components",
{ "ssr": true, "displayName": true, "preprocess": false }
],
[
"babel-plugin-root-import",
{
"rootPathPrefix": "~",
"rootPathSuffix": "./src/app"
}
]
]
}
It workes when removing both _app.js
and _document.js
.
Never mind, removing "@babel/preset-env"
from "presets"
solve this issue.
I have the same issue. This is mine next.config.js:
/* eslint no-param-reassign: 0 */
const appConfig = require("./config");
const path = require("path");
const webpack = require("webpack");
module.exports = {
publicRuntimeConfig: {
restRootEndpointUrl: appConfig.REST_ROOT_ENDPOINT_URL,
adminAuthenticationUrl: appConfig.ADMIN_AUTHENTICATION_URL,
},
distDir: "../build/app",
webpack: (config, { buildId, dev, isServer, defaultLoaders }) => {
// Fixes npm packages that depend on `fs` module
config.node = {
fs: "empty"
};
config.resolve.alias["../../storefront-ui/config"] = path.resolve(
__dirname,
"storefront-ui/config.js"
);
config.resolve.alias["storefront-ui"] = `@r00dy/storefront-ui/`;
config.module.rules.push({
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
loader: "graphql-tag/loader"
});
config.module.rules.push({
test: /\.svg$/,
use: [
{
loader: "@svgr/webpack",
options: {
svgoConfig: {
plugins: {
removeViewBox: false
}
},
titleProp: true
}
}
]
});
// Variables required by storefront-ui to be defined globally. The following line makes them visible in bundle.
config.plugins.push(
new webpack.DefinePlugin({
__DEV__: dev,
__BROWSER__: !isServer
})
);
return config;
}
};
and this is babel.rc:
{
"presets": ["next", "@babel/preset-react", "@emotion/babel-preset-css-prop"],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }]
]
}
I tried with calling:
constructor(props) {
super(props);
}
but it didn't work. And it started after upgrading to 9.0.5.
I'm also facing the same issue after updating from 7 to 9.0.5.
Here is my .babelrc:
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
["next/babel", { "preset-env": { "targets": { "node": "current" } } }]
],
"plugins": ["@babel/plugin-proposal-class-properties", "inline-react-svg"],
"env": {
"development" : {
"compact": false
}
}
}
Also my next.config.js:
const withSass = require('@zeit/next-sass')
const eslintFormatter = require('react-dev-utils/eslintFormatter')
const alias = require('./config/alias')
const StyleLintPlugin = require('stylelint-webpack-plugin')
const FilterPlugin = require('./config/filter.plugin')
const withOffline = require('next-offline')
const withSize = require('next-size')
const nextBuildId = require('next-build-id')
module.exports = withOffline(withSize(withSass({
useFileSystemPublicRoutes: false,
cssModules: true,
cssLoaderOptions: {
localIdentName: '[local]_-[hash:base64:5]'
},
sassLoaderOptions: {
includePaths: ['static/style']
},
publicRuntimeConfig: {
API_URL: JSON.stringify(process.env.API_URL),
PUBLIC_URL: JSON.stringify(process.env.PUBLIC_URL)
},
generateBuildId: () => nextBuildId({ dir: __dirname }),
webpack(configuration) {
const config = configuration
config.node = {
fs: 'empty'
}
config.resolve = {
alias: { ...(config.resolve.alias || {}), ...alias },
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx']
}
config.plugins.push(
// Silence mini-css-extract-plugin generating lots of warnings for CSS ordering.
// We use CSS modules that should not care for the order of CSS imports, so we
// should be safe to ignore these.
new FilterPlugin({ filter: /chunk styles \[mini-css-extract-plugin]\nConflicting order between:/ }),
)
config.module.rules.push(
{
test: /\.(js|jsx|mjs)$/,
enforce: 'pre',
use: [
{
options: {
formatter: eslintFormatter,
eslintPath: require.resolve('eslint')
},
loader: require.resolve('eslint-loader')
}
],
include: alias['app-root']
},
{
test: /\.(ttf|eot|woff|woff2|otf|txt|jpg|png|svg|ico)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
name: '[path][name].[hash].[ext]',
publicPath: '/_next'
}
}
]
}
)
config.plugins.push(
new StyleLintPlugin({
context: alias['app-root'],
files: '**/*.scss',
emitErrors: true
})
)
return config
}
})))
Never mind, removing
"@babel/preset-env"
from"presets"
solve this issue.
after i removed the preset-env in presets, all i had in .babelrc was
"presets": [
"next/babel"
]
and it didn't work
After that i changed to
"presets": [
[
"next/babel",
{
"preset-env": { "targets": { "node": "current" } }
}
]
]
and it works :+1:
Never mind, removing
"@babel/preset-env"
from"presets"
solve this issue.
This also worked for me, I replaced
["@babel/preset-env", { "targets": "> 0.5% in US" } ]
with
["next/babel", { "preset-env": { "targets": "> 0.5% in US" } }]
I'm running into this:
TypeError: Class constructor cannot be invoked without 'new'
with the following tsconfig.json:
{
"compilerOptions": {
"declaration": false,
"target": "es6",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"exclude": [
"node_modules"
],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
]
}
Any ideas?
In my case, I had a custom webpack config which was using babel loader like this:
{
// for all files except for node_modules, but including @scoped within node_modules
test: /\.(js|tsx)$/,
exclude: /node_modules(?!\/@scoped\/)/,
use: {
loader: 'babel-loader',
},
},
and the babel.config.js
was like this:
module.exports = {
presets: [
'next/babel',
],
plugins: [
[
'react-css-modules', {
generateScopedName: '[name]__[local]',
webpackHotModuleReloading: true,
handleMissingStyleName: 'warn',
},
],
'dynamic-import-node',
[
'@babel/plugin-proposal-decorators', {
legacy: true,
},
],
],
};
This was giving me an error 'App cannot be invoked without new'
The error was resolved by either of these:
Did not choose this option as nextjs docs specifically suggest not to add the presets which are already included in 'next/babel'
https://nextjs.org/docs/advanced-features/customizing-babel-config
3. by changing babel.config.js:
presets: [
[
'next/babel',
{
'preset-env': { targets: { node: 'current' } },
},
],
],
```
This was the option we went ahead with, although it is still not clear why this solves the issue.
What's the working solution for lerna, nextjs, and babel these days?
I'm trying to avoid pre-transpiling my libraries before import, and I've hit a brick wall with every solution here. Here's what I can't get working:
next-transpile-modules
.next-babel-loader
include
and exclude
rules to pass/fail respectively.
Most helpful comment
after i removed the preset-env in presets, all i had in .babelrc was
and it didn't work
After that i changed to
and it works :+1: