leebenson / reactql

Universal React+GraphQL starter kit: React 16, Apollo 2, MobX, Emotion, Webpack 4, GraphQL Code Generator, React Router 4, PostCSS, SSR
https://reactql.org
MIT License
1.82k stars 173 forks source link

Server/browser awareness issue #16

Closed netbull closed 7 years ago

netbull commented 7 years ago

When I try this

async componentDidMount() {
    if (!SERVER) {
      try {
        await screenfull = import('screenfull');
      } catch (e) {
        console.log('Module did not load!');
      }
    }
  }

Build fails with error "Invalid left-hand side in assignment expression" and the ESLinit highlights the await

If I change it to this:

const screenfull = await import('screenfull');

I've got regeneratorRuntime The setup is almost fresh, just few react components.

npm -v 4.1.2
node -v v7.6.0

Any ideas ?

leebenson commented 7 years ago

thanks @netbull - that's a mistake in the docs. I'll get that fixed. Your const screenfull = await import('screenfull'); is the right way to go.

netbull commented 7 years ago

@leebenson that way I've got the

ReferenceError: regeneratorRuntime is not defined
leebenson commented 7 years ago

Ah, I see. Sounds like an issue with the babel polyfill. Will check that today and get it fixed.

leebenson commented 7 years ago

This now works as of 2.1.0.

Upgrade with npm i -g reactql.

Sample component to test:

app.js

import React from 'react';

export default class Example extends React.Component {
  constructor() {
    super();
    this.state = {};
  }

  async componentWillMount() {
    this.setState({
      name: await new Promise(resolve => {
        setTimeout(() => resolve('ReactQL'), 1000);
      }),
    });
  }

  render() {
    return (
      <h1>{this.state.name || 'none'}</h1>
    );
  }
}

The browser entry is polyfilled to work everywhere. On the server, if you're using < 7.6, async/await will be transformed into a generator. On >= 7.6, it'll use native async/await.

netbull commented 7 years ago

@leebenson thanks!

for browser is ok, but running

npm run build-run

throws exception Unexpected token import if I try to use this.screenfull = await import('screenfull');

leebenson commented 7 years ago

will investigate this further. On the surface, it seems like an issue with import not being treated like a Promise on the server.

mnpenner commented 6 years ago

await still doesn't seem to be working. Getting

regeneratorRuntime is not defined

Not sure what version of kit I'm using but I installed it just a couple days ago.

leebenson commented 6 years ago

@mnpenner - are you specifically trying to get await to work with imports? This issue is showing up in the browser and not on the server, right?

mnpenner commented 6 years ago

In the browser, but not with import(). Was trying to await self.createImageBitmap specifically, which returns a Promise.

leebenson commented 6 years ago

Sounds like an issue with your environment. The project generated by reactql new uses async/await in multiple places, and should run out-the-box with npm start on Node 7.6+ to produce this:

screen shot 2017-09-27 at 18 10 33

Which version of ReactQL are you getting with reactql version? Did you try creating a new project with reactql new? Are you running with npm start?

mnpenner commented 6 years ago

@leebenson I managed to reproduce it a brand new install. However, the issue may be related to worker-loader or when you add webpack plugins via ! syntax.

❯ node --version
v7.10.1
❯ reactql version
4.8.5

Kit v2.8.5.

Create src/async.js:

self.addEventListener('message', async ev => {
  let image = await self.createImageBitmap('TEST');
});

Drop this in src/components/main/index.js. I put this right above export default ():

import Worker from 'worker-loader!../../async';
const worker = new Worker();

worker.postMessage({hello: 'world'});

Run yarn add worker-loader to add the package.

Fire up the server: yarn start.

Gives error:

db426b9….worker.js:733 Uncaught ReferenceError: regeneratorRuntime is not defined

Looking at the source, it gets compile do this (minus the oodles of boilerplate):

/***/ "./node_modules/react-hot-loader/webpack.js!./node_modules/babel-loader/lib/index.js?{\"babelrc\":false,\"presets\":[[\"env\",{\"modules\":false,\"exclude\":[\"transform-regenerator\"]}],\"react\"],\"plugins\":[\"transform-object-rest-spread\",\"syntax-dynamic-import\",\"transform-regenerator\",\"transform-class-properties\",\"transform-decorators-legacy\"]}!./src/async.js":
/***/ (function(module, exports, __webpack_require__) {

var _this = this;

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

self.addEventListener('message', function () {
  var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(ev) {
    var image;
    return regeneratorRuntime.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.next = 2;
            return self.createImageBitmap('TEST');

          case 2:
            image = _context.sent;

          case 3:
          case 'end':
            return _context.stop();
        }
      }
    }, _callee, _this);
  }));

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

Which is fun, because I can see you've got \"exclude\":[\"transform-regenerator\"]}], in there, and then it goes ahead and uses regenerator anyway. Not sure what's going on.

No issues or source listed here either, so I don't know if it's specific to worker-loader.

leebenson commented 6 years ago

@mnpenner - according to https://github.com/webpack-contrib/worker-loader/issues/75, it doesn't seem like Webpack 3.x support has landed yet. Not sure if it's related.