When webpack built: Invariant Violation: RelayQueryNode: Abstract class cannot be instantiated.
prewk opened this issue · 5 comments
Hi, I saw issue #10 but since I'm not using decorators I didn't want to lead anyone astray.
I've started with the basic relay-starter-kit
and worked my way from there. isomorphic-relay
works fine with rehydration etc, until... I do a webpack build (Both webpack -p
and webpack -d
causes this problem).
My dev environment consists of running the server with babel-node
and WDS as watch, whereas my production build transpiles the server files with babel and the routes
file (The React application entry from isomorphic-relay
s perspective) as a CommonJS module.
It perhaps sounds more complex than it is, I can open the transpiled server files and just console.log
the imported routes
module and get the same results as in the dev environment so I don't see why there should be a difference.
Anyway, when I run the built server and visit a route which in the dev env will server-render without any problems, the application crashes with this stack trace:
/Users/oskar/src/my-relay-project/node_modules/react-relay/node_modules/fbjs/node_modules/promise/lib/done.js:10
throw err;
^
Invariant Violation: RelayQueryNode: Abstract class cannot be instantiated.
at invariant (/Users/oskar/src/my-relay-project/node_modules/react-relay/node_modules/fbjs/lib/invariant.js:38:15)
at new RelayQueryNode (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayQuery.js:107:93)
at createNode (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayQuery.js:1192:12)
at /Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayQuery.js:178:24
at Array.forEach (native)
at /Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayQuery.js:174:28
at RelayQueryRoot.getChildren (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayQuery.js:186:9)
at RelayQueryRoot.instrumentedCallback [as getChildren] (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayProfiler.js:137:40)
at RelayQueryRoot.hasDeferredDescendant (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayQuery.js:261:67)
at RelayQueryRoot.instrumentedCallback [as hasDeferredDescendant] (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayProfiler.js:137:40)
at RelayQueryRoot.hasDeferredDescendant (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayQuery.js:482:81)
at /Users/oskar/src/my-relay-project/node_modules/react-relay/lib/GraphQLQueryRunner.js:96:64
at Array.forEach (native)
at splitAndFlattenQueries (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/GraphQLQueryRunner.js:95:15)
at /Users/oskar/src/my-relay-project/node_modules/react-relay/lib/GraphQLQueryRunner.js:177:5
at /Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayTaskQueue.js:118:25
at /Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayTaskQueue.js:124:15
at RelayTaskQueue._invokeWithinScopedQueue (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayTaskQueue.js:163:7)
at /Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayTaskQueue.js:153:14
at RelayTaskQueue._scheduleIfNecessary (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayTaskQueue.js:180:9)
at RelayTaskQueue.enqueue (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayTaskQueue.js:130:10)
at Object.enqueue (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayTaskScheduler.js:86:37)
at runQueries (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/GraphQLQueryRunner.js:159:22)
at GraphQLQueryRunner.forceFetch (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/GraphQLQueryRunner.js:82:12)
at RelayContext.forceFetch (/Users/oskar/src/my-relay-project/node_modules/react-relay/lib/RelayContext.js:98:45)
at /Users/oskar/src/my-relay-project/node_modules/isomorphic-relay/lib/prepareData.js:47:22
at new Promise (/Users/oskar/src/my-relay-project/node_modules/babel-polyfill/node_modules/core-js/modules/es6.promise.js:197:7)
at Promise.exports.(anonymous function).target.(anonymous function).function.target.(anonymous function).F (/Users/oskar/src/my-relay-project/node_modules/isomorphic-relay/node_modules/babel-runtime/node_modules/core-js/library/modules/_export.js:35:28)
at Object.prepareData (/Users/oskar/src/my-relay-project/node_modules/isomorphic-relay/lib/prepareData.js:31:12)
at Object.prepareData (/Users/oskar/src/my-relay-project/node_modules/isomorphic-relay-router/lib/prepareData.js:27:38)
at /Users/oskar/src/my-relay-project/build/server/render.js:37:49
at /Users/oskar/src/my-relay-project/node_modules/react-router/lib/match.js:65:5
at /Users/oskar/src/my-relay-project/node_modules/react-router/lib/createTransitionManager.js:117:11
at done (/Users/oskar/src/my-relay-project/node_modules/react-router/lib/AsyncUtils.js:81:19)
I perform the render from the server through this module:
import React from 'react';
const { routes } = require('../front/routes');
import { renderToString } from 'react-dom/server';
import { match } from 'react-router';
import IsomorphicRouter from 'isomorphic-relay-router';
export default function render(networkLayer, location) {
return new Promise((resolve, reject) => {
match({ routes, location }, (error, redirectLocation, renderProps) => {
if (error) {
reject(error);
} else if (redirectLocation) {
resolve({
status: 301,
from: location,
location: redirectLocation.pathname + redirectLocation.search,
});
} else if (renderProps) {
IsomorphicRouter.prepareData(renderProps, networkLayer)
.then(({ data, props }) => {
const reactOutput = renderToString(
<IsomorphicRouter.RouterContext { ...props } />
);
resolve({
status: 200,
reactOutput,
preloadedData: JSON.stringify(data),
});
})
.catch(err => {
reject(err);
});
} else {
resolve({
status: 404,
from: location,
});
}
});
});
}
I know it's a lot to swallow, but do you have any pointers on where to look? Thanks!
If I, instead of using the webpack
built module for my routes.js
(target: node
and libraryTarget: commonjs
), just require my original unbuilt non-minified version with babel-node
instead - it works.
Therefore, the error must have something to do with creating a transpiled webpack bundle of routes.js
and all of its React stuff. Can you think of something that might disappear in the build step?
My webpack build config doesn't have anything fancy, really:
{
entry: [path.join(__dirname, '..', 'src', 'front', 'routes')],
output: {
path: path.join(__dirname, '..', 'build', 'front'),
filename: 'routes.js',
libraryTarget: 'commonjs',
},
target: 'node',
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.NormalModuleReplacementPlugin(/\/iconv-loader$/, 'node-noop'),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
minimize: false,
mangle: false,
compressor: {
warnings: false
}
})
],
module: {
loaders: [
{ test: /\.js$/, loaders: ['babel'], include: path.join(__dirname, '..', 'src') },
{ test: /\.json$/, loaders: ['json'] },
],
},
}
Probably it's because externals
is missing in your webpack config. See denvned/isomorphic-relay-router#5 (comment).
Thanks, I tried it out externals: /^[^.]/
, assuming it would exclude all non-relative imports. It spat out a small module whose only purpose, it seems, is to require the unminified version, by absolute path (wtf) instead:
module.exports=function(r){function e(t){if(o[t])return o[t].exports;var n=o[t]={exports:{},id:t,loaded:!1};return r[t].call(n.exports,n,n.exports,e),n.loaded=!0,n.exports}var o={};return e.m=r,e.c=o,e.p="",e(0)}([function(r,e,o){r.exports=o(1)},function(r,e){r.exports=require("/Users/oskar/src/my-relay-project/src/front/routes")}]);
I guess it's more of a webpack question, but do you know if that exclude rule screws up if you're consistently using import x from '../y'
instead of require
, because that's what I'm doing?
it seems, is to require the unminified version, by absolute path (wtf)
It must be because you use absolute path for entry
. Try the following instead:
context: path.join(__dirname, '..', 'src'),
entry: './front/routes',
Good eye, thank you very much!