'window is not defined' error when using style-loader with webpack

∥☆過路亽.° 提交于 2020-01-02 01:15:13

问题


Building a server side react app and while using Webpack I am having issues with Style-Loader.

I am using version "^0.23.1" and when running a script to bundle and build there is an issue from Style-Loader.

The issue is window is not defined

webpack:///./node_modules/style-loader/lib/addStyles.js?:23
    return window && document && document.all && !window.atob;

Has anyone run into this issue? After looking through Stack and the Github issues for style-loader I am not finding any solution.

Here is my webpack file:

const path = require('path');
const webpack = require('webpack');

module.exports = {
  // webpack to use node
  target: 'node',
  entry: './src/index.js',
  output: {
    filename: 'client-build.js',
    path: path.resolve(__dirname, 'build/public'),
    publicPath: '/build/public'
  },
  module: {
    rules: [
      {
        test: /\.js$|\.jsx$/,
        loader: 'babel-loader',
        exclude: '/node_modules/',
        options: {
          presets: [
            '@babel/preset-react'
          ]
        }
      },
      {
        test: /\.(s*)css$/,
        loader: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.jpeg$|\.gif$|\.png$|\.svg$|\.woff$|\.ttf$|\.wav$|\.mp3$|\.jpg$|\.pdf$/,
        loader: 'file-loader',
        query: {
          name: 'assets/img/[name].[ext]'
        },
      },
    ]
  },
  plugins: [
    new webpack.ProvidePlugin({
      "React": "react",
    }),
  ],
}

If there is anything else you need to see I can post it.


回答1:


I think your problem is, that there is no window object when running js code on a node server. Which also makes sense, as your server has no window where your code is rendered. You can use the global object for global references instead, see this related post here: Does node.js have equivalent to window object in browser




回答2:


style-loader tries to inject styles into the head of the website (window / document), which will be non-existent on your server on render / execution.

You need to remove this loader from your server-config and replace it with something else (e.g. ExtractTextPlugin or MiniCSSExtractplugin, depending on your webpack version)




回答3:


I had a this problem where I needed some themes and styles from a component-library which in turn used webpack and style-loader.
My project was pure script and is supposed to generate some files and therefore had no browser. It would not compile at all since style-loader(and some other libs) tried to inject styles in the tag.
I ended up mocking window and document so that the imported project could compile.

NOTE that this worked in my case where I only needed a minor part of my component-library, if you use this in a more complicated project there will probably be some weird bugs. But it might help someone figure out a similar problem

Run this before you do the actual import
Since it is the actual import that causes the problem you need to do the hack before importing.

import * as Hack from './hack/StyleLoaderHack';
Hack.runHack();
...
import {X} from 'your library'

StyleLoaderHack.js

class HackStyle {
    position;

    constructor() {
        this.position = [];
    }
}

class HackElement {
    className;
    childNodes;
    style;

    constructor(tag) {
        this.className = tag;
        this.attributes = [];
        this.childNodes = [];
        this.style = new HackStyle();
    }

    appendChild = (child) => {
        let append;
        if (!(child instanceof HackElement)) {
            append = new HackElement(child);
        } else {
            append = child;
        }
        this.childNodes.push(append);
        return append;
    };

    insertBefore = (newChild, refChild) => {
        let insert;
        if (!(newChild instanceof HackElement)) {
            insert = new HackElement(newChild);
        } else {
            insert = child;
        }
        this.childNodes.push(insert);
    };

    setAttribute = (qualifiedName, value) => {
        // sketchy but works
        this.attributes.push(qualifiedName);
        this.attributes.push(value);
    };
}

class HackDocument {
    head;

    constructor() {
        this.head = new HackElement("head");
    }

    createElement = (tagName) => {
        const element = new HackElement(tagName);
        return element;
    };

    querySelector = (target) => {
        const node = new HackElement(target);
        return node;
    };

    querySelectorAll = (target) => {
        if (target === "[data-emotion-css]") {
            return [];
        }
        const node = new HackElement(target);
        return [node];
    };

    createTextNode = (data) => {
        return new HackElement(data);
    };
}


/**
 * Adds some function to global which is needed to load style-loader, emotion, create-emotion and react-table-hoc-fixed-columns.
 */
export const runHack = () => {
    global.window = {};

    const hackDocument = new HackDocument();
    global.document = hackDocument;
};



回答4:


If I got it correctly I think you are trying to use style-loader for bundling server side code.If it is the case try doing this instead of doing this:

    loader: ['style-loader', 'css-loader', 'sass-loader']

Try this:

    loader: ['css-loader/locals', 'sass-loader']

Style loader is not supposed to be used on the server side code. So we provide kind of a null-loader instead of css-loader and remove style loader. This should do the trick I guess.



来源:https://stackoverflow.com/questions/53951861/window-is-not-defined-error-when-using-style-loader-with-webpack

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!