问题
I'm writing a web app in TypeScript. The app uses React and Relay from Facebook. My TypeScript source code gets compiled into ES6 code using the TypeScript compiler TSC. Then, the ES6 code gets transpiled into ES5 code using Babel. In order for Relay to work in the browser, a Babel plugin needs to transform the Relay GraphQL queries: https://facebook.github.io/relay/docs/guides-babel-plugin.html. The problem is, because TSC first transpiles these queries, the Babel Relay plugin doesn't recognize them anymore so they don't get transpiled into something the browser understands, so the browser throws an error:
Uncaught Invariant Violation: RelayQL: Unexpected invocation at runtime. Either the Babel transform was not set up, or it failed to identify this call site. Make sure it is being used verbatim as
Relay.QL
.
My TypeScript source code:
const SiteQuery = {
store: () => Relay.QL`query { site }`
};
... this gets compiled by TSC into something like this:
var SiteQuery = {\r\n store: function () { return (_a = [\"query { site }\"], _a.raw = [\"query { site }\"], Relay.QL(_a)); var _a; }\r\n};
... instead of something like this (because the Babel Relay plugin doesn't do its work properly):
var SiteQuery = {\n store: function store() {\n return (function () {\n return {\n fieldName: 'site',\n kind: 'Query',\n metadata: {},\n name: 'Router',\n type: 'Site'\n };
This is because the Babel Relay plugin doesn't recognize the transpiled version, and as a result it doesn't transpile the query into something the browser understands.
How to make this work?
回答1:
You need to tell the Typescript compiler to transpile to ES6, then use Babel with babel-relay-plugin
and es2015
preset to transpile the code to ES5 to run in your browser.
I recommend using Webpack to orchestrate all this. These will get you started:
- http://www.jbrantly.com/typescript-and-webpack/
- http://www.jbrantly.com/es6-modules-with-typescript-and-webpack/
The posts were written for Babel 5.x, so you'll need to manually add es2015
preset to make sure Babel compiles the ES6 sources to ES6.
回答2:
The answers here were helpful, but I thought I'd share what finally worked for me.
- Setup your babel-relay-plugin correctly. If you're running into problems here, I recommend using the npm package
babel-relay-plugin-loader
which then allows you to specify the location of your schema.json in package.json. For example:{ "metadata": { "graphql": { "schema": "./schema.json" } } }
Setup your babel config correctly. It should look something like this:
{ "passPerPreset": true, "presets": [ "react", "es2015", "stage-0" ], "plugins": [ "babel-relay-plugin-loader" ] } },
Setup your tsconfig to target "es6" -- this actually was essential to make my setup work. ts-loader then compiles to es6 and Babel handles the transpile down to es5.
Finally, add the loaders to your webpack config. Remember, it applies these RIGHT to left. So, mine looks like this:
loaders: [ { test: /.tsx?$/, exclude: /node_modules/, loader: 'react-hot!babel!ts-loader', }, ],
回答3:
Just in case, when you say
My TypeScript source code gets compiled into ES6 code using the TypeScript compiler TSC. Then, the ES6 code gets transpiled into ES5 code using Babel.
You can instruct TypeScript itself to transpile directly to es5, just set target: 'es5' in tsconfig.json and that's it, hope it helps since you can eliminate babel from your compile chain.
来源:https://stackoverflow.com/questions/34815578/how-to-transpile-a-relay-query-from-typescript-to-es5