问题
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