styled-jsx/babel breaks with rollup and babel@7

Created on 20 Jan 2019  Â·  22Comments  Â·  Source: vercel/styled-jsx

Because the article I wrote about bundling styled-jsx components with Rollup still receives over hundred of views weekly (which makes me happy) I would like to update it:
babel 6 -> 7
rollup 0 -> 1
styled-jsx2 -> 3

Do you want to request a feature or report a bug?

BUG

What is the current behavior?

When I try to bundle components with styled-jsx and Rollup I get:

./src/HelloWorld.js → ./lib/dev.js...
[!] (babel plugin) Error: Invalid mapping: {"generated":{"line":1,"column":0},"original":{"line":8,"column":20},"name":null}
src/HelloWorld.js
Error: Invalid mapping: {"generated":{"line":1,"column":0},"original":{"line":8,"column":20},"name":null}
    at SourceMapGenerator._validateMapping (/Users/tomekm/Desktop/rollup-styled-jsx/node_modules/styled-jsx/node_modules/source-map/lib/source-map-generator.js:291:13)
    at SourceMapGenerator.addMapping (/Users/tomekm/Desktop/rollup-styled-jsx/node_modules/styled-jsx/node_modules/source-map/lib/source-map-generator.js:107:12)
    at Function.sourceMapsPlugin (/Users/tomekm/Desktop/rollup-styled-jsx/node_modules/styled-jsx/dist/lib/style-transform.js:46:15)
    at proxy (/Users/tomekm/Desktop/rollup-styled-jsx/node_modules/stylis/stylis.js:1473:30)
    at stylis (/Users/tomekm/Desktop/rollup-styled-jsx/node_modules/stylis/stylis.js:1657:13)
    at transform (/Users/tomekm/Desktop/rollup-styled-jsx/node_modules/styled-jsx/dist/lib/style-transform.js:116:3)
    at processCss (/Users/tomekm/Desktop/rollup-styled-jsx/node_modules/styled-jsx/dist/_utils.js:509:64)
    at PluginPass.exit (/Users/tomekm/Desktop/rollup-styled-jsx/node_modules/styled-jsx/dist/babel.js:250:49)
    at NodePath._call (/Users/tomekm/Desktop/rollup-styled-jsx/node_modules/@babel/traverse/lib/path/context.js:53:20)
    at NodePath.call (/Users/tomekm/Desktop/rollup-styled-jsx/node_modules/@babel/traverse/lib/path/context.js:40:17)

If the current behavior is a bug, please provide the steps to reproduce and possibly a minimal demo or testcase in the form of a Next.js app, CodeSandbox URL or similar

https://github.com/Tomekmularczyk/rollup-styled-jsx/tree/update-to-latest

If i remove "plugins": ["styled-jsx/babel"] from .babelrc it works (but then it doesn't transpile style tags).

What is the expected behavior?

doesn't break the build and transpiles style tags.

Environment (include versions)

  • OS: MacOS Mojave
  • Browser: -
  • styled-jsx (version): 3.2.0

Did this work in previous versions?

Yes

Most helpful comment

hey folks sorry for the late reply. I've been busy with work, I can try to see what's going on tomorrow.

All 22 comments

Anyone find anything on this?

I'm having the exact same issue here.

I can get around the error by disabling source maps, but then I get the following:

Internal Server Error:  TypeError: style$2.dynamic is not a function

Investigating now

To clarify, when disabling source maps rollup will actually produce a bundle. The error then occurs at runtime.

Inspecting a little bit the transpiled code I found lots of calls like this:

style$2.dynamic([["87120197", [padding, padding, CLOSING_TIME, CLOSING_TIME, padding, padding]]]) + " " + 'close-button'

Inspecting the element I see that it doesn't have a dynamic property but it has a default property which does have a dynamic property. If I add the .default in the middle I get a more obscure error:

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

It doesn't provide so much details. Only that something is failing on the render method.

@giuseppeg

@hojarasca changing to style$2.default actually worked for me.

I think some of my issues is that I'm in a monorepo and include, exclude, and external are tricky.

I don't think Rollup was treating it as a proper external, and I fixed that by matching the id with a regex:

external: id => /^react|styled-jsx/.test(id)

I've got it rendering now without error, but there are no styles applied. This may have to do with the fact that I'm using renderToStaticMarkup() and the styles don't render properly on the first render?

hey folks sorry for the late reply. I've been busy with work, I can try to see what's going on tomorrow.

@Tomekmularczyk @hojarasca I was having this problem as well. I solved it by making sure it was properly excluded from the bundle as an external. I also am including node_modules in commonjs() plugin and excluding from babel() plugin.

@Tomekmularczyk Perhaps you need to include: /node_modules/ in commonjs()?

So, I've gotten everything working locally, but when I try to deploy to now I get the following error:

TypeError: Cannot read property 'replace' of undefined
    at sanitize (/tmp/1a88b490/node_modules/styled-jsx/dist/stylesheet-registry.js:21:15)
    at StyleSheetRegistry.computeSelector (/tmp/1a88b490/node_modules/styled-jsx/dist/stylesheet-registry.js:207:17)
    at StyleSheetRegistry.getIdAndRules (/tmp/1a88b490/node_modules/styled-jsx/dist/stylesheet-registry.js:234:22)
    at StyleSheetRegistry.add (/tmp/1a88b490/node_modules/styled-jsx/dist/stylesheet-registry.js:80:38)
    at JSXStyle.render (/tmp/1a88b490/node_modules/styled-jsx/dist/style.js:74:28)
    at c (/tmp/1a88b490/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:30:231)
    at Ga (/tmp/1a88b490/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:31:1)
    at a.render (/tmp/1a88b490/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:36:367)
    at a.read (/tmp/1a88b490/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:35:450)
    at renderToString (/tmp/1a88b490/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:47:82)
    at renderPage (/tmp/1a88b490/node_modules/next/dist/server/render.js:319:26)
    at Function.getInitialProps (/tmp/1a88b490/node_modules/next/dist/server/document.js:65:25)
    at _callee$ (/tmp/1a88b490/node_modules/next/dist/lib/utils.js:86:30)
    at tryCatch (/tmp/1a88b490/node_modules/regenerator-runtime/runtime.js:62:40)
    at Generator.invoke [as _invoke] (/tmp/1a88b490/node_modules/regenerator-runtime/runtime.js:288:22)
    at Generator.prototype.(anonymous function) [as next] (/tmp/1a88b490/node_modules/regenerator-runtime/runtime.js:114:21)

Looks like sanitize() isn't being passed anything: https://github.com/zeit/styled-jsx/blob/cdfd1fcb756b668b16f792e007bb8b56e6db4042/src/stylesheet-registry.js#L4

Okay, weirdest part is that error occurs in a different Next.js app in my monorepo that hasn't had any code changes :thinking: That's worrisome.

The styled-jsx package is hoisted by yarn workspaces to the root node_modules... hope we're not leaking problems across apps in my monrepo

I can confirm that this is specifically some king of global state issue, since it's fixed by using nohoist options with yarn workspaces to keep a seperate styled-jsx module in each package. @giuseppeg Should I open a separate issue for this?

@NathanielHill how did you fix it with using nohoist? I have this same problem for a package (https://github.com/sergiodxa/next-nprogress/) which uses this a dependency (I am using a yarn monorepo too)

Hi, guys. Here I have my last experiments.

I tried to bundle my component library using webpack instead of rollup. After I managed to correctly configure webpack it worked, but it failed on runtime. This only happens styled-jsx is part of the build. It works styled-jsx it's not included.

But... I started to try different stuff and at the end I discovered that it works if I compile in production mode.

After that I rolled back to rollup I tried build for prod and it builds, but fails in runtime with obscure errors (in dev it doesn't even build).

Also this doesn't happens with babel 6, so I believe that the problem is more related to something betweein styled-jsx and babel than between styled-jsx and rollup or webpack.

I can create a minimum repo with all this stuff on the weekend if that helps.

@theallseingeye So, if a module is required from the same file path, it will be cached by node and therefore behave like a Singleton.

It appears to me that I was having some kind of state/style leakage occuring across workspaces in my monorepo, so I made sure the shared component workspace had it's own copy of styled-jsx.

https://yarnpkg.com/blog/2018/02/15/nohoist/

I believe this is a bug @giuseppeg, but nohoist solves it for me.

@hojarasca You are likely to have problems with modules (especially default imports) between CJS/ESM because you're using both. Make sure in your rollup config you're passing/excluding the right things to those two plugins.

Have you tried turning of sourcemaps and nohoist if you're in a monorepo?

@Tomekmularczyk I took a look at your branch and as mentioned in this issue at some point it seems that some source maps are invalid. If you disable source maps in the babel conf plugins: [['styled-jsx/babel', { sourceMaps: false ]] then your test case builds just fine.

I will try to debug when I have some time.

As for the other issues that you folks have been discussing about, I think this is out of topic.
@NathanielHill could you open a separate issue and provide a testcase (reproduce your setup and put it in repo) so that I can try it out?

Closing in favor or #547

@giuseppeg I'll open an issue if I can find the time to reproduce. My setup is quite complicated, so hopefully it's not too crazy to isolate a minimal reproduction

Thanks a lot for this @giuseppeg ! I have updated the article and repo.

I'm having the same error that @hojarasca mentioned above, Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

Looking at the compiled code I can see that it's compiling the style component as a commonJs module instead of a react component. Then trying to use it as a component in calls to React.createClass(style, ...)

Here's the problomatic code

var style = createCommonjsModule(function(module, exports) {
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.flush = flush;
  exports.default = void 0;

  var _stylesheetRegistry = _interopRequireDefault(stylesheetRegistry);

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

  function _typeof(obj) {
    if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
      _typeof = function _typeof(obj) {
        return typeof obj;
      };
    } else {
      _typeof = function _typeof(obj) {
        return obj &&
          typeof Symbol === "function" &&
          obj.constructor === Symbol &&
          obj !== Symbol.prototype
          ? "symbol"
          : typeof obj;
      };
    }
    return _typeof(obj);
  }

  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }

  function _defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }

  function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    return Constructor;
  }

  function _possibleConstructorReturn(self, call) {
    if (call && (_typeof(call) === "object" || typeof call === "function")) {
      return call;
    }
    return _assertThisInitialized(self);
  }

  function _assertThisInitialized(self) {
    if (self === void 0) {
      throw new ReferenceError(
        "this hasn't been initialised - super() hasn't been called"
      );
    }
    return self;
  }

  function _getPrototypeOf(o) {
    _getPrototypeOf = Object.setPrototypeOf
      ? Object.getPrototypeOf
      : function _getPrototypeOf(o) {
          return o.__proto__ || Object.getPrototypeOf(o);
        };
    return _getPrototypeOf(o);
  }

  function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError("Super expression must either be null or a function");
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, {
      constructor: { value: subClass, writable: true, configurable: true }
    });
    if (superClass) _setPrototypeOf(subClass, superClass);
  }

  function _setPrototypeOf(o, p) {
    _setPrototypeOf =
      Object.setPrototypeOf ||
      function _setPrototypeOf(o, p) {
        o.__proto__ = p;
        return o;
      };
    return _setPrototypeOf(o, p);
  }

  var styleSheetRegistry = new _stylesheetRegistry.default();

  var JSXStyle =
    /*#__PURE__*/
    (function(_Component) {
      _inherits(JSXStyle, _Component);

      function JSXStyle(props) {
        var _this;

        _classCallCheck(this, JSXStyle);

        _this = _possibleConstructorReturn(
          this,
          _getPrototypeOf(JSXStyle).call(this, props)
        );
        _this.prevProps = {};
        return _this;
      }

      _createClass(
        JSXStyle,
        [
          {
            key: "shouldComponentUpdate",
            // probably faster than PureComponent (shallowEqual)
            value: function shouldComponentUpdate(otherProps) {
              return (
                this.props.id !== otherProps.id || // We do this check because `dynamic` is an array of strings or undefined.
                // These are the computed values for dynamic styles.
                String(this.props.dynamic) !== String(otherProps.dynamic)
              );
            }
          },
          {
            key: "componentWillUnmount",
            value: function componentWillUnmount() {
              styleSheetRegistry.remove(this.props);
            }
          },
          {
            key: "render",
            value: function render() {
              // This is a workaround to make the side effect async safe in the "render" phase.
              // See https://github.com/zeit/styled-jsx/pull/484
              if (this.shouldComponentUpdate(this.prevProps)) {
                // Updates
                if (this.prevProps.id) {
                  styleSheetRegistry.remove(this.prevProps);
                }

                styleSheetRegistry.add(this.props);
                this.prevProps = this.props;
              }

              return null;
            }
          }
        ],
        [
          {
            key: "dynamic",
            value: function dynamic(info) {
              return info
                .map(function(tagInfo) {
                  var baseId = tagInfo[0];
                  var props = tagInfo[1];
                  return styleSheetRegistry.computeId(baseId, props);
                })
                .join(" ");
            }
          }
        ]
      );

      return JSXStyle;
    })(React.Component);

  exports.default = JSXStyle;

  function flush() {
    var cssRules = styleSheetRegistry.cssRules();
    styleSheetRegistry.flush();
    return cssRules;
  }
});

@giuseppeg

@NathanielHill could you open a separate issue and provide a testcase (reproduce your setup and put it in repo) so that I can try it out?

I have opened an issue regarding the dynamic is not a function error. It has a test case, repo and npm package. Been trying to debug it with no success. Definitely has to do with the dynamic being available on default, but not the top-level object.

Was this page helpful?
0 / 5 - 0 ratings