Open hanford opened 7 years ago
I was able to fix this issue by forking react-redux
and modifying it to this: https://github.com/hanford/react-redux/commit/7d6a542e7b77a72949fdc78833bd32a7b9088609
Hi there! It looks like your aliasing on the server is actually not taking effect - you can tell because there are React internals included in the stack trace you posted. It's likely you're using Preact + Preact-compat to render your app, but the libraries you're pulling in are actually using React.
Can you give any details about how you're doing the aliasing on the server?
For what it's worth, the best (maybe only) way I'm aware of to properly alias preact-compat
under node (without webpack) is module-alias:
require('module-alias').addAliases({
'react' : 'preact-compat',
'react-dom': 'preact-compat'
});
or, specify this in your package.json
:
"_moduleAliases": {
"react": "preact-compat",
"react-dom": "preact-compat"
}
... and install the hook:
require('module-alias/register');
Not sure if this will help you but...
We have this compiling on the server with webpack and had to make sure to exclude the correct modules from externals e.g.
// webpack.server.js
const config = {
...
target: 'node',
node: {
__dirname: false,
__filename: false
},
externals: getExternals()
...
}
function getExternals() {
const excludes = [ 'react-router', 'react-redux', 'react' ];
return fs.readdirSync('node_modules')
.filter((x) => !~excludes.indexOf(x))
.reduce((nodeModules, mod) => {
nodeModules[mod] = 'commonjs ' + mod;
return nodeModules;
}, {});
}
Without the excludes
list, webpack won't process those libs, so they don't get aliased by preact. react
is obviously the key one here, add others as needed.
@mikestead are you aliasing outside webpack to handle that then? interested to know how that works.
Nope just aliasing in the webpack config as usual.
config.resolve.alias = {
react: 'preact-compat',
'react-dom': 'preact-compat'
}
Because webpack picks up the alias and is processing react imports it seems to swap out react for preact compat, just like for the client, and all seems to work fine.
nice!
@hanford where did we end up with this? Definitely looked like an aliasing issue to me (the fact that react/*
was being included at all is basically a guarantee something is amiss there).
Alternatively - you might actually just be able to alias react-redux
to preact-redux
- the latter is pre-aliased with a few things stripped out, it'll both reduce your bundle size and fix the children.only issue.
Yeah, cant make this work - every single module says it can not find react. That function gives webpack 2 a bunch of errors as well
I have added to package.json, added to aliasing for webpack, added everything. react-helmet wasnt working so i stopped using it then I started getting react-router errors which i obviously am not about to remove and re-do the entire app for :(
@bradennapier If anything is saying it can't find React, that means your aliases are not being used. Can you elaborate on how you did the aliasing? One common mistake I see is that people alias via Webpack, but then run their code without bundling directly in Node (which doesn't know anything about Webpack aliases).
Yeah, my problem was that that was where I was looking but I had that part correct. Just figured it out. I had a few modules being built into a vendor dll so when we moved into the client they were not aliased.
ahhh yeah, that sounds about right. if there was something funky required to alias that DLL by all means post it here. I think we need to add some details to the aliasing section of the preact website to cover these cases.
I just removed them all together, it was only for development anyway so I am using the dll for lodash and friends only.
Ahh, ok. I think we can probably safely say webpack DLL's are not aliasable, that's at least good to know.
Am having the same issue here, and I referred to #242 in which I found a quick solution to get require
s working correctly. As evidenced in the following SSR stacktrace, you can see that preact
is being substituted for react
as expected, and yet I am encountering the same issue.
Invariant Violation: React.Children.only expected to receive a single React element child.
at invariant (/usr/src/app/node_modules/fbjs/lib/invariant.js:44:15)
at Object.onlyChild [as only] (/usr/src/app/node_modules/react/lib/onlyChild.js:33:84)
at Provider.render (/usr/src/app/node_modules/react-redux/lib/components/Provider.js:51:28)
at renderToString (/usr/src/app/node_modules/preact-render-to-string/src/index.js:90:18)
at renderToString (/usr/src/app/node_modules/preact-render-to-string/src/index.js:97:11)
at renderToString (/usr/src/app/node_modules/preact-render-to-string/src/index.js:97:11)
at /usr/src/app/src/js/server/core/middleware/post/react-server.js:46:30
at run (/usr/src/app/node_modules/babel-polyfill/node_modules/core-js/modules/es6.promise.js:87:22)
at /usr/src/app/node_modules/babel-polyfill/node_modules/core-js/modules/es6.promise.js:100:28
at flush (/usr/src/app/node_modules/babel-polyfill/node_modules/core-js/modules/_microtask.js:18:9)
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickDomainCallback (internal/process/next_tick.js:128:9)
Am about to try with preact-redux
as suggested above. Will advise on my progress.
"preact": "7.2.x",
"preact-compat": "3.14.x",
"react-redux": "4.4.x",
"react-router": "2.x.x",
"redux": "3.3.x"
Problem solved with preact-redux
!
Still seeing this issue. The easiest workaround is to symlink preact-compact
to react
and react-dom
in node_modules.
"_moduleAliases": {
"react": "node_modules/preact/compat/dist/compat.js",
"react-dom": "node_modules/preact/compat/dist/compat.js"
}
solved my issue on server side (preact 10.4.0)
there was a problem with using react-redux
on server
Yes, for Node/SSR module-alias is a good solution with the configuration @sedlukha posted.
@sedlukha Can you help how to patch preact-cli@3.0.0-rc.10
with module-alias
? where is the place for require('module-alias/register')
? Thanks
@rodynenko I don't use preact-cli. You need to add require('module-alias/register')
at the very main file of server side of your app, before any code.
In my case I use razzle for ssr. So my target file is server.js
.(preact example)
@rodynenko This shouldn't be needed for preact-cli
it has the alias properties already set up in webpack.
@sedlukha @marvinhagemeister Thanks. It seems to be en error in my code.
Is this resolved? No longer relevant to me / happy to close if it's resolved
Hello! Thanks again for making such an amazing little framework. preact-compat has been a dream to work with, and I'm excited to integrate. I've just run into one little issue, that I hope isn't a blocker, because the performance gains are tremendous! 🔥
I'll add as much code as possible, if it's relevant, note that our application runs fine in the browser, where this code isn't executed.
So we server side render everything with React and things work fine. The code looks like this:
So we're using
tags, however I don't think that's the issue. This runs fine in a node environment, and returns HTML when the function is invoked in a purely react environment (without the preact aliasing). However, when I introduced the preact & webpack aliasing, I started seeing this error:react-helmet
, for theSo, investigating this stack trace, the first error points to
react/lib/onlyChild
which is this function:weirdly, the
children
in this argument are we're failing the ternaryReactElement.isValidElement
, here is what the children arg is:After doing some investigation, commenting out the
onlyChild
ternary fixes server side rendering, however I don't think forkingreact-redux
andreact
is the best solution here.the
ReactElement
call appears to be checking for$$typeof: Symbol(react.element)
Annnnd the whole reason any of this is called is because we're rendering
<Provider />
fromreact-redux