サーバー側のリアクションアプリを構築し、Webpackを使用しているときにStyle-Loaderで問題が発生しています。
バージョン「^ 0.23.1」を使用していますが、バンドルしてビルドするスクリプトを実行すると、Style-Loaderに問題があります。
問題はwindow is not defined
webpack:///./node_modules/style-loader/lib/addStyles.js?:23
return window && document && document.all && !window.atob;
誰もこの問題に遭遇しましたか? StackとGithubのスタイルローダーの問題を調べた後、解決策が見つかりません。
これが私のwebpackファイルです。
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",
}),
],
}
他に何か見たいことがあれば、投稿できます。
あなたの問題は、ノードサーバーでjsコードを実行するときにwindow
オブジェクトがないことだと思います。サーバーにはコードがレンダリングされるウィンドウがないため、これも理にかなっています。代わりにグローバル参照にglobal
オブジェクトを使用できます。関連記事はこちらをご覧ください: node.jsにはブラウザのウィンドウオブジェクトと同等のものがあります
style-loader
は、Webサイトのhead
(window
/document
)にスタイルを挿入しようとします。これは、レンダリング/実行時にサーバーに存在しません。
Server-configからこのローダーを削除して、他のものに置き換える必要があります(例: ExtractTextPlugin または MiniCSSExtractplugin 、Webpackバージョンに応じて)
この問題は、web-packとstyle-loaderを順に使用するコンポーネントライブラリからいくつかのテーマとスタイルを必要としたときに発生しました。
私のプロジェクトは純粋なスクリプトであり、いくつかのファイルを生成することになっているため、ブラウザがありませんでした。スタイルローダー(および他のいくつかのライブラリ)がタグにスタイルを挿入しようとしたため、まったくコンパイルされませんでした。
ウィンドウとドキュメントのモックを作成して、インポートしたプロジェクトをコンパイルできるようにしました。
[〜#〜] note [〜#〜]これは、コンポーネントライブラリのごく一部しか必要としない私のケースで機能しました。より複雑なプロジェクトでこれを使用すると、おそらくいくつかの奇妙なバグ。しかし、それは誰かが同様の問題を理解するのを助けるかもしれません
実際のインポートを行う前にこれを実行します
問題を引き起こすのは実際のインポートなので、インポートする前にハックする必要があります。
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;
};
正しく取得できた場合、サーバー側のコードをバンドルするためにスタイルローダーを使用しようとしていると思います。
loader: ['style-loader', 'css-loader', 'sass-loader']
これを試して:
loader: ['css-loader/locals', 'sass-loader']
スタイルローダーは、サーバー側コードで使用されることを想定していません。そのため、css-loaderの代わりにnullローダーを用意し、スタイルローダーを削除します。これは私が推測するトリックを行う必要があります。