Open joshunger opened 8 years ago
You can fix this by shimming window
in Webpack with the imports-loader plugin
require("imports?window=>global!hammer")
Or:
require("imports?window=>{}!hammer")
Trying to shim this using webpack's imports-loader
doesn't work if you're doing server side rendering (like you might do with React). When rendering the initial response on the backend webpack isn't involved so shimming doesn't work. Since hammer is about behavior as opposed to rendering content it would great to fix this limitation. I'm going to submit a PR that takes the jquery approach suggested by @joshunger. I hope you'll consider merging it.
Unfortunately... it's not quite as simple as passing window
or this
(global
) into the constructor. It also needs document
. Not sure this package is setup to be used in a project which renders server side.
The only way we could really make this work and what we have discussed to fix this in another issue i cant seem to find is to just noop if there is not a document and window. Hammer cannot operate without them.
@arschmitz Thanks for the reply. The noop approach is more or less what I was thinking about. Alternatively I could perform a conditional import using a canUseDOM
test but I"m using ES6 module imports which don't lend themselves to that. I believe the noop approach would be completely acceptable for SSR since hammer is only adding "behavior" (i.e. events) and not contributing to what's getting rendered.
I'm new to hammer and not really familiar with the codebase. Any tips on how best to noop this? I could add conditionals here and there but that doesn't seem very elegant...
@arschmitz was it https://github.com/hammerjs/hammer.js/issues/849 Remove global dependency to window and document ?
Here is the jQuery file I was looking at https://github.com/jquery/jquery/blob/master/src/wrapper.js
@joshunger yes thats exactly how it should be done. I'm also a member of the jQuery team :-) the only difference here is how we break up the wrapper we use 2 files beginning and end on hammer
Submitted PR #973 that fixes this using the jquery style approach suggested by @joshunger. Works well.
Well, so this project doesn't support server side rendering? 🚶
any progress ?
For those who use Webpack there's a simple workaround:
plugins: [
...
new webpack.NormalModuleReplacementPlugin(/hammerjs/, 'mocks/HammerMock'),
],
mocks/HammerMock module:
export default class HammerMock {
constructor() {
this.DIRECTION_LEFT = 0;
this.DIRECTION_RIGHT = 1;
}
on() {}
}
you will probably need to adjust the code above considering methods you use.
@udivankin Thanks for posting the workaround; however, what do you mean by "mocks/HammerMock" module? Is this a module that exists somewhere? Or something one must create? I'm confused.
@merges that's an ES6 module somewhere in your project (in my case I put it in mocks folder and named HammerMock,js). Webpack's NormalModuleReplacementPlugin will just replace all occurrences of
import Hammer from 'hammerjs';
with
import Hammer from 'mocks/HammerMock';
you can also use require.extensions to patch out hammerjs.
@graingert could u possibly explain further on how to do that
I am also running into this problem. I just started using https://github.com/bytefunc/react-resize-layout, and underneath it is using hammer 2.0.8. My server side rendering config is using webpack 4x. Instructions above not clear, unfortunately. Would somebody be able to offer step-by-step (or gist) on what to do to get this to work in SSR setups? thank you in advance.
Or would it be possible to update Hammer-js such that it does not access window handle within export code? (because that code gets invoked during SSR initialization, but in reality window handle is needed later on (as normally folks that rely on Hammer.JS (eg react-resize-layout), call Hammer in componentDidMount (which happens on client side ).
For completeness, this suggestion did not work for me, because (still a guess), my SSR build/release pipeline is using Razzle (which underneath creates JS chunks (not one big bundle) for efficiency)
I had a similar issue with velocity-animate and (crudely) solved it via string-replace-loader
the concept is just
for the ssr entry, replace "import hammerjs from 'hammerjs'\n" with ""
and the loader config
test: /\.js$/,
loader: 'string-replace-loader',
options: {
search: "import hammerjs from 'hammerjs'\n",
replace: '',
}
this is working for me in my vue ssr setup currently
Got a fix. I downloaded the hammer.min.js
.
Just wrap the if((typeof document !== 'undefined') && (typeof window !== 'undefined')){ ALL_THE_HAMMER_MIN_JS }
The reason is because Node. When youre in node it does not know what window is. You can test it in youre terminal. Here is the example:
ReferenceError: window is not defined
> if( window ) console.log( 'something' );
ReferenceError: window is not defined
> console.log( typeof window );
undefined
undefined
> if( typeof window === 'undefined' ) console.log( 'this is undefined' );
this is undefined```
thank you @polymer940c , is there a way to override/polyfill hammer in a way that would not require its source code change in the node_modules? thx again for the suggestion!
In case anyone come here for angular ssr issue, you can use below webpack config for your server ts build.
{ test: /hammerjs/, loader: "null-loader" }
Similarly: https://medium.com/@puresmash/solve-hammer-js-issue-on-ssr-project-2e79664a7196
@egjs/hammerjs will work also, but it's not working properly with slider on mobile in my project.
thank you @polymer940c , is there a way to override/polyfill hammer in a way that would not require its source code change in the node_modules? thx again for the suggestion!
Another solution is to load hammer on demand where you need it, so that you don't have to update hammer.min.js:
if (typeof window !== undefined) { // conditional include because window is undefined on build this.hammer = await import( /* webpackPrefetch: true */ 'hammerjs' ); }
So this issue is 4 years old and still no solution? 🙄
After installing below 2 dependencies, I was able to launch angular universal.
Any solution now ??
I solved this error in my case. Just check if it is browser then only import hammerjs. Basically
const hammerjs = {};
if(this.isBrowser()){
hammerjs = require('hammer-js');
}
and again check for browser when you are using hammerjs module. It worked
Hammer.js fails in node since window is undefined. Also document.
Line 2568 assumes window - https://github.com/hammerjs/hammer.js/blob/master/hammer.js#L2568
We're trying to run a bundle produced by webpack in the web as well as node targets. It would be helpful to include the same bundle even though we're not using hammer.js on the node side.
jQuery does something like -
typeof window !== "undefined" ? window : this