Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8.0.0 - babel not compiling properly #6273

Closed
dunika opened this issue Feb 12, 2019 · 31 comments · Fixed by #6534
Closed

8.0.0 - babel not compiling properly #6273

dunika opened this issue Feb 12, 2019 · 31 comments · Fixed by #6534

Comments

@dunika
Copy link

dunika commented Feb 12, 2019

I am getting the following issue which I presume is related to babel.

node_modules/@babel/runtime-corejs2/helpers/esm/asyncToGenerator.js:1
(function (exports, require, module, __filename, __dirname) { import _Promise from "../../core-js/promise";

SyntaxError: Unexpected token import

It seems that @babel/runtime-corejs2/helpers/esm is being used instead of just@babel/runtime-corejs2/helpers where the compiled files seem to be.

I didn't notice this in dev with the following config

"presets": [
   ["next/babel", {"preset-env": {
      "modules": "commonjs"
    }}]
 ],

The issue is when I try and run the production build. Here is the relevant config

{
  "env": {
    "production": {
      "presets": [
        ["next/babel", {
          "preset-env": {
            "targets": {
              "browsers": ["> 1%"]
            }
          }
        }]
      ],
      "plugins": [
        [ "babel-plugin-styled-components", { "displayName": false } ],
        "transform-react-constant-elements",
        "@babel/plugin-transform-react-inline-elements"
      ]
    },
  },
  "plugins": [
    [
      "transform-imports",
      {
        "lodash": {
          "transform": "lodash/${member}",
          "preventFullImport": true
        },
        "validator": {
          "transform": "validator/lib/${member}",
          "preventFullImport": true
        },
        "recompose": {
          "transform": "recompose/${member}",
          "preventFullImport": true
        },
      }
    ], 
    "date-fns",
    "transform-modern-regexp",
    "@babel/plugin-proposal-export-default-from",
    "@babel/plugin-proposal-export-namespace-from",
    "@babel/plugin-proposal-optional-catch-binding",
    [ 
      "module-resolver", { 
        "root": [ "./src" ]
      } 
    ],
    [
      "inline-import", {
        "extensions": [ ".css" ]
      }
    ]
  ]
}

@timneutkens
Copy link
Member

Please provide a reproducible repository.

@kyle-mccarthy
Copy link

@dunika I am having the same issue as you, out of curiosity do you have multiple babel configs? I do and it looks like babel is reading my .babelrc and .babelrc.

@kyle-mccarthy
Copy link

kyle-mccarthy commented Feb 12, 2019

@timneutkens here is a repo that reproduces the issue with https://github.com/kyle-mccarthy/nextjs8-babel-issue

If you run yarn build:server and then look at the .next/production-server/other.js file you can see that it is using esm files.

I dug into it a little bit and think this commit is the problem.

Modifying the primary .babelrc file and setting useESModules to false allows for the compiled server code to run correctly.

For example:

{
  "presets": [
    [
      "next/babel",
        "transform-runtime": {
          "useESModules": false
        }
      }
    ]
  ]
}

@duvholt
Copy link

duvholt commented Feb 12, 2019

I think have the same problem. I managed to reproduce it by modifying one of the existing examples.
https://github.com/duvholt/nextjs8-babel-server-issue
See commits for more details on the code I added to reproduce the crash.

Using Next v7 this code compiles fine.

Edit:
I can also confirm that turning off ES modules in transform-runtime works like @kyle-mccarthy said.

@Emiliano-Bucci
Copy link

Don't know if is related to this, but when trying to build, i get this:

Emitted warnings from webpack: export 'default' (imported as 'Component') was not found in
and so on. Works fine with v7.

@icflorescu
Copy link

I can confirm the same issue introduced by 8.0.0.
Modifying next/babel preset to ['next/babel', { 'transform-runtime': { useESModules: false } }] saved my day.

Thanks a lot, @kyle-mccarthy!

I've spent hours debugging this on a complex project (custom server, different .babelrc.js, etc.) and I was just preparing to extract the minimal reproducible test case in a separate repo when I saw your comment...

@icflorescu
Copy link

Here's another reproduction repo to help debugging the issue: github.com/icflorescu/next8-babel-issue.

@timneutkens
Copy link
Member

Re: #6273 (comment)

Sounds like it's not really a Next.js issue then, you're trying to transpile the custom server, which is really not needed in nearly all use cases.

The correct way to configure it (though again I really wouldn't recommend transpiling the custom server, really makes no sense to me)

Adding a big warning here as I've seen this go wrong many times, sorry for the caps etc 😉:

DO NOT PUT THIS BABELRC IN YOUR NEXT.JS ROOT DIRECTORY. YOU WILL OPT OUT OF TREE SHAKING ESMODULES. ONLY ADD IT TO THE SERVER DIRECTORY

server/.babelrc:

{
  "presets": [
    [
      "next/babel",
        "preset-env": {
          "modules": "commonjs"
        }
      }
    ]
  ]
}

@kyle-mccarthy
Copy link

kyle-mccarthy commented Feb 17, 2019

@timneutkens I have to compile the server because I use the babel plugin module resolver. While I guess it isn't directly related to next or at least isn't a bug in next, it is probably worth mentioning in the docs.

For anyone that does need to transpile their server side code, I ended up with a better fix by using the babel env options to define separate server and client envs. This allows for you to leave the useESModules option enabled.

babel.config.js

module.exports = {
  env: {
    server: {
      plugins: [
        ...
      ],
    },
    client: {
      presets: [
        [
          'next/babel'
        ]
      ],
    },
  },
};

Then in my package.json I have two different build steps:

{
  ...
  "scripts": {
    "build:clean": "rm -rf .next",
    "build:server": "tsc --project tsconfig.server.json && BABEL_ENV=server npx babel .next/production-server -d .next/production-server --extensions \".js\"",
    "build:ui": "BABEL_ENV=client npx next build",
    "build": "yarn build:clean && yarn build:ui && yarn build:server",
    ...
  },
  ...
}


@timneutkens
Copy link
Member

timneutkens commented Feb 17, 2019

I have to compile the server because I use the babel plugin module resolver.

Why do you need this? For zeit.co we have around 20 different routes and have everything contained without any compilation of the server.

This indicates you're doing something non-standard / it can probably be improved a lot 🤔

@kyle-mccarthy
Copy link

@timneutkens the module resolver lets me reference files absolutely rather than having to specify a relative file path.

I use typescript and in development I can define the paths/aliases in the tsconfig file and use the tsconfig-paths module; however, when you transpile the code from typescript to javascript, typescript doesn't replace those aliases with the relative file path. That is where the module-resolver comes in. Once the code is transpiled via tsc, I run it through babel to rewrite the alias with the relative path.

Obviously the process is less than ideal, and it would be nice if typescript just replaced the paths when it transpiled the code, but since it doesn't I have to use babel for that.

@pruhstal
Copy link

pruhstal commented Feb 18, 2019

@timneutkens I too was running into an issue compiling after upgrading to Next 8 that was solved by modifying my babel preset-env to include commonjs modules, however, you mentioning that it will opt out of tree-shaking makes me a bit worried of how I'm going to solve that.

Like @kyle-mccarthy I'm also using module-resolver. In fact, here's my entire .babelrc for my project (note that this lives OUTSIDE of src).

{
  "presets": [
    [
      "next/babel",
      {
        "preset-env": {
          "modules": "commonjs"
        }
      }
    ],
    "@babel/preset-flow"
  ],
  "compact": false,
  "plugins": [
    ["@babel/plugin-transform-flow-strip-types"],
    [
      "wrap-in-js",
      {
        "extensions": ["less$"]
      }
    ],
    [
      "module-resolver",
      {
        "root": ["./"],
        "alias": {
          "api": "./src/api",
          "db": "./src/db",
          "common": "./src/common",
          "components": "./src/components",
          "config": "./config",
          "constants": "./src/constants",
          "controllers": "./src/controllers",
          "higher-order": "./src/higher-order",
          "routes": "./src/routes",
          "static": "./src/static",
          "styles": "./src/styles",
          "types": "./types",
          "worker": "./src/worker"
        }
      }
    ],
    [
      "inline-import",
      {
        "extensions": [".css"]
      }
    ],
    [
      "import",
      {
        "libraryName": "antd",
        "style": false
      }
    ],
    [
      "transform-assets",
      {
        "extensions": ["txt", "svg", "png"],
        "name": "/static/[name].[ext]?[sha512:hash:base64:7]"
      }
    ]
  ]
}

As you can see, everything is in src, however, all server based code isn't under src/server. Are you saying to move all that server code into src/server and then throw:

{
  "presets": [
    [
      "next/babel",
        "preset-env": {
          "modules": "commonjs"
        }
      }
    ]
  ]
}

in src/server/.babelrc?

@baldurh
Copy link

baldurh commented Feb 19, 2019

We’re experiencing the same issue as @Emiliano-Bucci describes it:

Don't know if is related to this, but when trying to build, i get this:

Emitted warnings from webpack: export 'default' (imported as 'Component') was not found in
and so on. Works fine with v7.

This goes away by turning on "commonjs" for both server and client (tried to do it only for the server but it did not work) but we’re not satisfied with shipping that to production.

@spencewood
Copy link

Sounds like it's not really a Next.js issue then, you're trying to transpile the custom server, which is really not needed in nearly all use cases.

@timneutkens I think that transpiling on the server side is not as rare a use case as you might think. Anyone that has custom routing needs beyond the simple, out-of-the-box routing Next.js provides and uses TypeScript is in this boat. For me, this particular issue is holding me back from updating to 8.0 right now. I'm not super thrilled with idea of overriding the babel modules transform or performing a custom transpiling step, as all of this worked just fine in 7.0.

@icflorescu
Copy link

Sounds like it's not really a Next.js issue then, you're trying to transpile the custom server, which is really not needed in nearly all use cases.

@timneutkens I completely agree with @spencewood. Transpiling the server is definitely not a rare use case.

There are, for instance, people using it just for the sake of being able to import instead of require, make use of optional chaining (which is still in proposal state), or to get rid of relative paths like ../../../models/Policy.js with the help of an import resolver.
I know microservices are the hype nowadays, but I've also seen people who prefer to set up just a single server application hosting both the Next.js front-end and an underlying API (with Objection.js-based models, lots of helpers, etc.).

Hence, not being able to transpile the server in v8 sounds a bit like a regression.

As a side note regarding tree-shaking in Next.js, it kind of works but it's far from perfect.
I'm using mdi-react icons in one of my projects and tree-shaking works perfectly when transpiling for production but the entire project becomes really slow during development, so I have to include transform-imports in .babelrc.

@timneutkens
Copy link
Member

Hence, not being able to transpile the server in v8 sounds a bit like a regression.

I didn't say it's not possible, it's definitely possible to transpile the server, your babel config that compiled the server was wrong in the first place as it didn't account for transforming import to require(), which is what causes the issue that you're seeing.

There are, for instance, people using it just for the sake of being able to import instead of require

I still strongly believe that this is the wrong tradeoff to make just to use different syntax to do the same thing, especially because the custom server should generally be just routing. Node.js supports most of es2016+ by now (even async/await natively)

Just to be clear, I'm just trying to warn for a pitfall in your applications here. I'm not trying to be mean or tell you what to do 🙏 Everything will still work if you transpile the server, as Next.js is completely unaware that it's even running in a custom server environment.

rogerhutchings added a commit to zooniverse/front-end-monorepo that referenced this issue Feb 21, 2019
rogerhutchings added a commit to zooniverse/front-end-monorepo that referenced this issue Feb 21, 2019
@ladieman217
Copy link

@timneutkens here is a repo that reproduces the issue with https://github.com/kyle-mccarthy/nextjs8-babel-issue

If you run yarn build:server and then look at the .next/production-server/other.js file you can see that it is using esm files.

I dug into it a little bit and think this commit is the problem.

Modifying the primary .babelrc file and setting useESModules to false allows for the compiled server code to run correctly.

For example:

{
  "presets": [
    [
      "next/babel",
        "transform-runtime": {
          "useESModules": false
        }
      }
    ]
  ]
}

thank you very much, save my time

@koolamusic
Copy link

Is there an official workaround for this issue, This also has prevented me from upgrading to Next.js ^8.x

@timneutkens
Copy link
Member

As said you probably have a wrong configuration:
#6273 (comment)

@ladieman217
Copy link

upgrade failed, down to next.js 7

@koolamusic
Copy link

I am now using, next@latest with a custom server.

@michaeljonathanblack
Copy link

michaeljonathanblack commented Mar 6, 2019

We also ran into this issue when upgrading from Next.js 7 to Next.js 8, likely due to our incorrect configuration.

Here's the initial build error after upgrading:

/Users/mherold/git/next-test/node_modules/@babel/runtime-corejs2/helpers/esm/objectSpread.js:1
(function (exports, require, module, __filename, __dirname) { import _Object$getOwnPropertyDescriptor from "../../core-js/object/get-own-property-descriptor";
                                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

SyntaxError: Unexpected identifier
    at new Script (vm.js:79:7)
    at createScript (vm.js:251:10)
    at Object.runInThisContext (vm.js:303:10)
    at Module._compile (internal/modules/cjs/loader.js:657:28)
    at Module._compile (/Users/mherold/git/next-test/node_modules/pirates/lib/index.js:83:24)
    at Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Object.newLoader [as .js] (/Users/mherold/git/next-test/node_modules/pirates/lib/index.js:88:7)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)

And here's the compile error we're seeing after implementing presets: [['next/babel', { 'transform-runtime': { useESModules: false } }]], patch:

Failed to compile.

../node_modules/next/dist/client/next-dev.js 34:6
Module parse failed: Unexpected token (34:6)
You may need an appropriate loader to handle this file type.
|
|
> import('./noop');
| var _window = window,
|     assetPrefix = _window.__NEXT_DATA__.assetPrefix;

Finally, here are various relevant files that might be related:

babel.config.js

const env = require('./env-config.js');

module.exports = {
  babelrc: false,
  plugins: [
    ['emotion', { autoLabel: true, sourceMap: true }],
    'inline-react-svg',
    ['transform-define', env],
    ['lodash'],
  ],
  env: {
    development: {
      presets: ['next/babel'],
    },
    production: {
      presets: ['next/babel', ['@babel/env', { targets: { node: '8' } }]],
      plugins: [['emotion', { autoLabel: true, sourceMap: false }]],
    },
    test: {
      presets: [['next/babel', { 'preset-env': { modules: 'commonjs' } }]],
    },
  },
};

next.config.js

const withBundleAnalyzer = require('@zeit/next-bundle-analyzer');
const withProgressBar = require('next-progressbar');
const withOffline = require('next-offline');

const serviceWorkerConfig = require('./src/lib/serviceWorker/config');

module.exports = withOffline(
  withBundleAnalyzer(
    withProgressBar({
      assetPrefix: '',
      useFileSystemPublicRoutes: false,
      poweredByHeader: false,
      webpack: config => {
        config.module.rules.push(
          {
            test: /\.css$/,
            use: ['to-string-loader', 'css-loader'],
          },
          {
            test: /\.js$/,
            exclude: /(node_modules)/,
            use: {
              loader: 'babel-loader',
            },
          }
        );
        return config;
      },
      analyzeServer: ['server', 'both'].includes(process.env.BUNDLE_ANALYZE),
      analyzeBrowser: ['browser', 'both'].includes(process.env.BUNDLE_ANALYZE),
      bundleAnalyzerConfig: {
        server: {
          analyzerMode: 'static',
          reportFilename: '../../bundles/server.html',
        },
        browser: {
          analyzerMode: 'static',
          reportFilename: '../bundles/client.html',
        },
      },
      workboxOpts: serviceWorkerConfig,
    })
  )
);

package.json (removed a lot of noise)

{
  "name": "next-test",
  "main": "index.js",
  "scripts": {
    "dev": "NODE_ENV=development nodemon"
  },
  "engines": {
    "node": "10.15.0",
    "npm": "6.4.1"
  },
  "dependencies": {
    "@yolkai/next-routes": "^2.0.0",
    "@zeit/next-bundle-analyzer": "^0.1.2",
    "express": "^4.16.4",
    "next": "^8.0.3",
    "next-offline": "^3.3.3",
    "next-progressbar": "^1.0.0",
    "react": "^16.8.3",
    "react-dom": "^16.8.3"
  },
  "devDependencies": {
    "@babel/cli": "^7.2.3",
    "@babel/core": "^7.2.2",
    "@babel/node": "^7.0.0",
    "@babel/preset-env": "^7.2.3",
    "@babel/preset-react": "^7.0.0",
    "ajv": "^6.7.0",
    "babel-core": "^7.0.0-bridge.0",
    "babel-eslint": "^10.0.1",
    "babel-jest": "^23.4.2",
    "babel-plugin-emotion": "^10.0.6",
    "babel-plugin-inline-react-svg": "^1.0.1",
    "babel-plugin-lodash": "^3.3.4",
    "babel-plugin-transform-define": "^1.3.1",
    "nodemon": "^1.18.9"
  }
}

Does anyone have any insight?

Or an example project with a transpiled server we can build backward from?

Being able to write our code the same everywhere is a huge boon, but these transpilation issues make it seem like a zero sum game.

@timneutkens
Copy link
Member

timneutkens commented Mar 6, 2019

Just did a new release that holds #6534, currently on it's way to being published to npm as next@canary.

@schoenwaldnils
Copy link
Contributor

I tested [email protected] but still get this error

Failed to compile.

./node_modules/next/dist/client/next-dev.js 36:6
Module parse failed: Unexpected token (36:6)
You may need an appropriate loader to handle this file type.
|
|
> import('./noop'); // Support EventSource on Internet Explorer 11
|
| if (!window.EventSource) {

.babelrc.js

module.exports = {
  presets: ['next/babel'],
  plugins: [
    ['inline-react-svg', {
      svgo: { plugins: [{
        cleanupIDs: false
      }]}
    }],
    'emotion',
  ]
};

@timneutkens
Copy link
Member

@schoenwaldnils that's actually a different issue: #6240

@FatihErtugral
Copy link

add comment line

E2-lazy-loading-modules/node_modules/next/dist/client/next-dev.js
// import('./noop'); // Support EventSource on Internet Explorer 11

@timneutkens
Copy link
Member

That won't solve the issue if you have dynamic imports in other places.

@iMerica
Copy link

iMerica commented Jun 2, 2019

There are so many invalid babelrc code snippets on this thread.

@iamricky
Copy link

iamricky commented Sep 1, 2019

Unfortunately, I've run into a similar issue.
I see the following error when I start my custom server:

throw new Error(`Could not find a valid build in the '${this.distDir}' directory! Try building your app with 'next build' before starting the server.`);
                ^

Error: Could not find a valid build in the '/Users/workstation/Sites/dry-run/.next' directory! Try building your app with 'next build' before starting the server.

This only happens when NODE_ENV is set to production.
Otherwise, it works as expected.

Then I try running next build per the error's instructions but see the following error:

import withCSS from '@zeit/next-css';
       ^^^^^^^

SyntaxError: Unexpected identifier

I've tried a few of the suggestions found here but without much success. Has the issue been directly addressed?

@MihaiWill
Copy link

MihaiWill commented Dec 21, 2019

Is there any solution for this? How can I run yarn server/app.js with babel?
I am making a query using with-apollo example to get all posts for my sitemap.xml, so I need to run app.js with babel. Thanks

@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Jan 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.