apollographql/apollo-client

Import syntax inside node_modules/apollo-client with apollo-client@0.8.1

Closed this issue · 23 comments

HriBB commented

I might be missing something obvious, but apollo-client@0.8.1 uses import syntax inside node_modules and I get an error

apollo-upload-network-interface bojan$ npm run test

> apollo-upload-network-interface@ test /Users/bojan/www/apollo-upload-network-interface
> mocha --compilers js:babel-core/register ./test/test.js

/Users/bojan/www/apollo-upload-network-interface/node_modules/apollo-client/transport/networkInterface.js:9
import 'whatwg-fetch';
^^^^^^

SyntaxError: Unexpected token import

This is the content of networkInterface.js inside node_modules

var __assign = (this && this.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};
import 'whatwg-fetch';
import { print } from 'graphql-tag/printer';
export function printRequest(request) {
    return __assign({}, request, { query: print(request.query) });
}
var HTTPFetchNetworkInterface = (function () {
// ...

I might be missing something obvious, so you can close this issue if it's not valid.

We recently changed the bundle to have UMD, commonjs and es6, so I assume it's related to how you're importing Apollo Client. @kamilkisiela, @calebmer I'm heading out to the mountains today. Can one of you help out here?

@HriBB First question, which build tool do you use? Webpack, rollup, something different?

About that UMD, CommonJS, ES6 Modules thing.

In package.json we have:

"main": "apollo.umd.js",
"module": "index.js",
"jsnext:main": "index.js",

It means that if your build tool wants to use es6 modules, it looks for the module or the jsnext:main in package.json. Both points to an entry module. Otherwise, it uses just the main field.

Think of apollo.umd.js as a bundle, a one file that contains all the modules. It's compiled to ES5 and supports AMD and CommonJS.

index.js is an entry point for all the modules that are in separate files and use ES6 Modules syntax. They are compiled to ES5 too, just like the UMD bundle.

So why we did that? Thanks to having es6 modules we support, for an example tree-shaking. It's useful to keep your app as small as possible.

I don't know if you're familiar with SystemJS but it requires to specify all the modules / packages manually. It means, that in each defined package you have to define an entry point. If you will put there index.js it will take files that has ES6 Modules so your browser will throw an error about import (SyntaxError: Unexpected token import). You should use apollo.umd.js then, it uses CommonJS.
So maybe you have something similar in your project.

Now I noticed that you use mocha. It suppose to take a file that is defined under main filed in package.json. Could you create a small, separated reproduction?

HriBB commented

I'm using webpack with babel. I fixed it by including apollo-client in babel loader following this issue

module: {
  loaders: [{
    test: /\.js$/,
    loaders: ['babel?cacheDirectory'],
    exclude: /node_modules\/(?!(apollo-client)\/).*/,
    include: [
      path.resolve(__dirname, '..', 'client'),
      path.resolve(__dirname, '..', 'node_modules', 'apollo-client')
    ]
  }
}

I'm not really sure how to handle this in apollo-upload-network-interface, which only uses babel. Should I add module and jsnext:main?

As for the reproduction, just fork apollo-upload-network-interface, run npm install and then npm run test.

@HriBB Which version of webpack?

HriBB commented

Webpack v1. Need to try out v2 soon. Or maybe rollup.

@HriBB v2 and rollup works okay, I'm testing all the versions right now. With webpack@2.2 you get es6 support by default :)

HriBB commented

OK, I guess I'm doing something wrong. Will try to fix this later this week.

ne8il commented

I'm getting this error (SyntaxError: Unexpected token import) in Meteor (1.4.2.3) just by having apollo-client@0.8.1 installed, without requiring it anywhere. This gets output into the modules.js file:

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                     //
// node_modules/apollo-client/queries/queryTransform.js                                                                //
//                                                                                                                     //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                                                                       //
import { checkDocument, } from './getFromAST';                                                                         // 1
import { cloneDeep } from '../util/cloneDeep';    

It was working fine previously with apollo-client@0.5.12. Not sure if there's something I need to configure about how it gets loaded or if anyone else on Meteor has fixed this.

@ne8il works fine
Take a look at this. It's a reproduction of your issue.

I also tried out importing apollo-client in the app (imported branch). It takes umd bundle which is a very good thing.

HriBB commented

Hmm ... this is really weird, but for some reason apollo-client works on one project, but does not work on another. Anyway, I'm still having issues with running mocha tests.

/home/bojan/www/apollo-upload-network-interface/node_modules/apollo-client/transport/networkInterface.js:9
import 'whatwg-fetch';
^^^^^^
SyntaxError: Unexpected token import
    at Object.exports.runInThisContext (vm.js:76:16)
    at Module._compile (module.js:528:28)
    at Module._extensions..js (module.js:565:10)

Any ideas on how to convince babel to transpile node_modules/apollo-client when running mocha?

HriBB commented

Yeah I fixed it by adding a setup.js that overrides babel-register ignore option.

require('babel-register')({
  ignore: /node_modules\/(?!apollo\-client)/i
});

require('./test.js')

I'm closing this issue, because it's not a bug in apollo-client. Feel free to reopen or comment ...

@ne8il I have the same issue with meteor 1.4.2.7 and apollo-client > 0.8.x. Do you found any fix?

ne8il commented

@mimamuh I did not. I tried running kamilkisiela's fix listed above. His sample project runs for me fine locally, but importing those deps into my own meteor project doesn't fix it. I kind of put that on the back burner so I will try again and see if anything's changed.

ne8il commented

@mimamuh I found that the problem centered around having the atmosphere package apollo at version 0.0.1. If you update that to a newer version it should go away. I'm not entirely sure why it's is an issue. @kamilkisiela if you add that package at that version to your sample project you should see the same issue, but only if you care to, my issue should be fixed. Thanks for looking into it.

@ne8il Thx for your information. In my case I don't use the apollo atmosphere package instead I load the apollo-client directly via npm. I have to do some more tests I think.

@ne8il I've solved my issue, too. It was due to importing from a subdirectory which caused the build system to ignore the project.json as @stubailo explained it at the meteor forum. It was a old api anyway I've used.
Thx for your help!

Posting my scenario & solution here, hope it helps someone with similar situation. Project environment is TypeScript 2.5.2 and Webpack 3.

Scenario: With import ApolloClient from 'apollo-client/ApolloClient', I got this error:

/xxx/node_modules/apollo-client/ApolloClient.js:9
import { createNetworkInterface, } from './transport/networkInterface';
^^^^^^

SyntaxError: Unexpected token import
    at createScript (vm.js:80:10)

Solution: import ApolloClient from 'apollo-client'

No idea why IntelliJ decided to add /ApolloClient when I auto-imported.

I was seeing a similar error which was caused by various imports reaching into both apollo-client and react-apollo beyond the root (ex. import Query from "react-apollo/Query")

To fix, just use the named imports from the root module (ex. import { Query } from "react-apollo")

Thanks @bkoltai, it helped!

I had this error:

Uncaught ReferenceError: exports is not defined
    at Module../node_modules/immutable-tuple/dist/tuple.mjs (tuple.mjs:1)
    at __webpack_require__ (bootstrap:782)
    at fn (bootstrap:150)
    at Object../node_modules/optimism/lib/index.js (index.js:5)
    at __webpack_require__ (bootstrap:782)
    at fn (bootstrap:150)
    at Object../node_modules/apollo-cache-inmemory/lib/optimism.js (optimism.js:6)
    at __webpack_require__ (bootstrap:782)
    at fn (bootstrap:150)
    at Object../node_modules/apollo-cache-inmemory/lib/readFromStore.js (readFromStore.js:9)
    at __webpack_require__ (bootstrap:782)
    at fn (bootstrap:150)
    at Object../node_modules/apollo-cache-inmemory/lib/inMemoryCache.js (inMemoryCache.js:15)
    at __webpack_require__ (bootstrap:782)
    at fn (bootstrap:150)
    at Object../node_modules/apollo-cache-inmemory/lib/index.js (index.js:21)

when importing 'apollo-cache-inmemory'

import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';

Thanks to @HriBB I added 'exclude' property to my babel-loader in webpack.config like this

          {
            test: /\.(js|mjs)$/,
            exclude: /(@babel(?:\/|\\{1,2})runtime)|(node_modules\/(?!(apollo-client)\/).*)/, // <-- nice
            loader: require.resolve('babel-loader'),
            options: {
              babelrc: false,
              configFile: false,
              compact: false,
              // ... etc
          },

...and the issue disappeared
Maybe there is a better solution. But for now this saved me.