Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hammer.js fails in node since window is undefined #930

Open
joshunger opened this issue Mar 1, 2016 · 26 comments
Open

Hammer.js fails in node since window is undefined #930

joshunger opened this issue Mar 1, 2016 · 26 comments

Comments

@joshunger
Copy link

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

@Kishan-Gupta
Copy link

You can fix this by shimming window in Webpack with the imports-loader plugin

require("imports?window=>global!hammer")

Or:

require("imports?window=>{}!hammer")

@hburrows
Copy link

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.

@hburrows
Copy link

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.

@arschmitz
Copy link
Contributor

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.

@hburrows
Copy link

@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...

@joshunger
Copy link
Author

joshunger commented Apr 28, 2016

@arschmitz was it #849 Remove global dependency to window and document ?

@joshunger
Copy link
Author

Here is the jQuery file I was looking at https://github.com/jquery/jquery/blob/master/src/wrapper.js

@arschmitz
Copy link
Contributor

@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

@hburrows
Copy link

hburrows commented May 5, 2016

Submitted PR #973 that fixes this using the jquery style approach suggested by @joshunger. Works well.

@andypmw
Copy link

andypmw commented Apr 20, 2017

Well, so this project doesn't support server side rendering? 🚶

@paranoidjk
Copy link

any progress ?

@udivankin
Copy link

udivankin commented May 15, 2017

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.

@merges
Copy link

merges commented May 16, 2017

@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.

@udivankin
Copy link

@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';

@graingert
Copy link

you can also use require.extensions to patch out hammerjs.

@Tatenda
Copy link

Tatenda commented Jan 29, 2018

@graingert could u possibly explain further on how to do that

@vladp
Copy link

vladp commented May 23, 2018

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)

@olsonpm
Copy link

olsonpm commented May 29, 2018

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

@justanotherkevin
Copy link

justanotherkevin commented Jun 7, 2018

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```  

@vladp
Copy link

vladp commented Jun 8, 2018

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!

@adamzhu-xs
Copy link

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.

@KamilPuczka
Copy link

KamilPuczka commented Aug 19, 2020

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' ); }

@daviddelusenet
Copy link

So this issue is 4 years old and still no solution? 🙄

@Brijeshlakkad
Copy link

After installing below 2 dependencies, I was able to launch angular universal.

  1. npm install @egjs/hammerjs --save-dev
  2. npm install @types/hammerjs --save-dev

@SahilRajpal-hub
Copy link

Any solution now ??

@SahilRajpal-hub
Copy link

SahilRajpal-hub commented Mar 18, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.