Next.js: Babel producing invalid output

Created on 31 Oct 2016  路  5Comments  路  Source: vercel/next.js

I've found that the Babel output for tagged template literals is incorrect - here's an example repo that includes the .next folder where the issue can be seen.

The reason I _think_ this is a Next issue rather than just Babel is that the incorrect output only seems to happen outside the pages directory, and I see that the custom webpack config for Next is treating this directory differently. I've also never had this problem with other projects that use tagged templates successfully.

Many thanks for your help, and creating a very interesting tool.

bug

All 5 comments

Ok, I've done some more trial and error, and found that Babel transpiles correctly as long as React is in scope.

This input:

import React from 'react'
const foo = () => {}
foo``

produces this output:

'use strict';

var _taggedTemplateLiteral2 = require('/Users/ben/code/template-literals-error/node_modules/babel-runtime/helpers/taggedTemplateLiteral');

var _taggedTemplateLiteral3 = _interopRequireDefault(_taggedTemplateLiteral2);

var _templateObject = (0, _taggedTemplateLiteral3.default)([''], ['']);

var _react = require('/Users/ben/code/template-literals-error/node_modules/react/react.js');

var _react2 = _interopRequireDefault(_react);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var foo = function foo() {};
foo(_templateObject);

...which works!

But this input:

const foo = () => {}
foo``

produces this, non-working output:

"use strict";

var _templateObject = (0, _taggedTemplateLiteral3.default)([""], [""]);

var _taggedTemplateLiteral2 = require("/Users/ben/code/template-literals-error/node_modules/babel-runtime/helpers/taggedTemplateLiteral");

var _taggedTemplateLiteral3 = _interopRequireDefault(_taggedTemplateLiteral2);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var foo = function foo() {};
foo(_templateObject);

I know that React needs to be in scope in components, but in this case, I'm not rendering a component. Or the react scope could be a total red herring - sadly, I don't know enough about Babel.

After seeing a similar issue on Slack, I have another reproducible example that's unrelated to both template literals and the file location, but is an ES6 feature causing an incorrect Babel output.

In pages/index.js:

import React from 'react'
async function test() {}
export default () => <p>Hello, world</p>

This returns the following error: TypeError: Cannot read property 'default' of undefined at /Users/ben/code/template-literals-error/.next/dist/pages/index.js:12:59. Here's the output in question - notice that _regenerator2 is being called before it's defined.

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _asyncToGenerator2 = require('/Users/ben/code/template-literals-error/node_modules/babel-runtime/helpers/asyncToGenerator');

var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);

var test = function () {
  var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee() {
    return _regenerator2.default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
          case 'end':
            return _context.stop();
        }
      }
    }, _callee, this);
  }));

  return function test() {
    return _ref.apply(this, arguments);
  };
}();

var _regenerator = require('/Users/ben/code/template-literals-error/node_modules/babel-runtime/regenerator');

var _regenerator2 = _interopRequireDefault(_regenerator);

var _react = require('/Users/ben/code/template-literals-error/node_modules/react/react.js');

var _react2 = _interopRequireDefault(_react);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = function () {
  return _react2.default.createElement(
    'p',
    null,
    'Hello, world'
  );
};
    if (module.hot) {
      module.hot.accept()
      if (module.hot.status() !== 'idle') {
        var Component = module.exports.default || module.exports
        next.router.update('/', Component)
      }
    }

I encounter the same issue with async functions. I'm not quite sure in which babel thing or combination of things the issue lies (transform-async-to-generator, regenerator-runtime etc). This mentions maybe we should use babel-plugin-transform-regenerator instead of babel-plugin-transform-async-to-generator.

Or could we switch to fast-async instead of generators? It's also supposed to be more performant.

Maybe rename the issue to "async functions not supported: switch Babel config to fast-async?".

A workaround is to use an async arrow function instead of plain async function:

import React from 'react'
const test = async () => {}
export default () => <p>Hello, world</p>
Was this page helpful?
0 / 5 - 0 ratings

Related issues

jesselee34 picture jesselee34  路  3Comments

lixiaoyan picture lixiaoyan  路  3Comments

kenji4569 picture kenji4569  路  3Comments

pie6k picture pie6k  路  3Comments

havefive picture havefive  路  3Comments