materialize icon indicating copy to clipboard operation
materialize copied to clipboard

WebpackError: window is not defined

Open vojtechruz opened this issue 6 years ago • 9 comments

When trying to use materialize with GatsbyJS and deploying to Netlify I get the following error when building the project: WebpackError: window is not defined

1:04:37 PM:   WebpackError: window is not defined
1:04:37 PM:   
1:04:37 PM:   - materialize.min.js:6 Object.module.exports.layoutContext
1:04:37 PM:     ~/materialize-css/dist/js/materialize.min.js:6:1135
1:04:37 PM:   
1:04:37 PM:   - index.js:6 Object.exports.__esModule
1:04:37 PM:     src/layouts/index.js:6:1
1:04:37 PM:   
1:04:37 PM:   - index.js:3 Object.exports.__esModule
1:04:37 PM:     .cache/layouts/index.js:3:3
1:04:37 PM:   
1:04:37 PM:   - sync-requires.js:6 Object.exports.__esModule
1:04:37 PM:     .cache/sync-requires.js:6:35
1:04:37 PM:   
1:04:37 PM:   - static-entry.js:8 Object.<anonymous>
1:04:37 PM:     .cache/static-entry.js:8:1

The sample project is here: https://github.com/vojtechruz/staticman-example

The failed build log here: https://app.netlify.com/sites/staticman-example/deploys/5b81377f4ed62f240de8d134

vojtechruz avatar Aug 25 '18 12:08 vojtechruz

This issue occurs generally with server-side rendering as you are relying on window object which is not available on the server. It is not just gatsby specific. It would be nice to be able to work with SSR and materialize.

vojtechruz avatar Aug 25 '18 12:08 vojtechruz

It's not materialize's issue too. If your css/sass processor (e.g: style-loader) loads the css at runtime in your HTML, you would see this error. So those processors (e.g: style-loader) add code to work on real dom/window object etc, which are not present when you do SSR. I use ExtractTextPlugin to extract the css and manually add the css file in the HTML template. What I think would be nice is if any web pack plugin could do the variable substitution and place the css in the template at build time like const htmlTemplate= <html><head>${webpack.css.plugin.generatedcss}</head></html>;

Dhana-Krishnasamy avatar Sep 01 '18 09:09 Dhana-Krishnasamy

In gatsby js v1 (React 15) and materialize 1.0 I can initialize a sidebar like this

if (typeof window !== 'undefined') {
  require('materialize-css/dist/js/materialize.min.js')
}

class Navigation extends Component {
  componentDidMount() {
    let elem = document.querySelector('.sidenav')
    M.Sidenav.init(elem, {})  
}

But migrating to Gatsby 2 (React 16) it doesn't work anymore (window is not defined when building the production app)

hug0b avatar Sep 03 '18 14:09 hug0b

In gatsby v2 what works is something like (still for a Sidenav component here)


if (typeof window !== 'undefined') {
  require('materialize-css/dist/js/materialize.min.js')
}

class Navigation extends Component {
  componentDidMount() {
    const elem = document.querySelector('.sidenav')
    window.M.Sidenav.init(elem, {})
  }

If that helps anyone

hug0b avatar Sep 13 '18 23:09 hug0b

I suggest creating an issue in the Gatsby project.

DanielRuf avatar Sep 20 '18 05:09 DanielRuf

The only issue with gatsby js v2 it that I haven't figured out how to make the waves effect work in production builds.

hug0b avatar Sep 29 '18 12:09 hug0b

It's not materialize's issue too.

If I understand correctly, materialize JS uses the window object, which means that one would never be able to use it with ANY framework or situation, where server-side rendering is used, right? That's not just issue of Gatsby. What's suggested in the comments above is a workaround, but it would be nice if materialize would work with SSR out of the box?

Not sure how easy is the transition though, looks like there are 184 occurrences of the window in the materialize JS.

vojtechruz avatar Sep 30 '18 10:09 vojtechruz

You don't have to change anything inside. You just have to apply some UMD wrapper which exports Materialize to root or window.

DanielRuf avatar Oct 01 '18 04:10 DanielRuf

Did anyone figure out a workaround for this? I'm also trying to import materialize-css (trying to use waves specifically) into my Gatsby app. Not having any luck. Tried importing it inside a useEffect but that doesn't appear to work. Which seems weird because this works for scrollspy:

useEffect(() => {
    if (typeof window !== 'undefined') {
      import('materialize-css').then((M) => {
        const scrollSpyElems = document.querySelectorAll('.scrollspy');
        M.ScrollSpy.init(scrollSpyElems);
      });
    }
 }, []);

But for whatever reason, I cannot get waves to work using this same import.

Update:

Got waves to work by adding this inside the above import.then:

const wavesElems = document.querySelectorAll('.waves-effect');

const Waves = window.Waves;

wavesElems.forEach((wavesElem): void => {
     Waves.attach(wavesElem);
});

ahummel25 avatar Oct 04 '20 16:10 ahummel25