[英]No loading/serving of stylesheets - react
我正在嘗試使用React路由器的StaticRouter
進行SSR。
express.js (服務器)
const html = ReactDOMServer.renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
res.status(200).send(`
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/app.css" type="text/css"/>
</head>
<body>
<div id="app">${html}</div>
</body>
</html>
`);
提供靜態文件:
app.use(express.static(path.resolve(__dirname, "../dist/client")));
App.js (共享)
import React from "react";
import { Switch, Route } from "react-router";
export default () => {
return (
<Switch>
...
</Switch>
);
};
index.jsx (客戶端)
import React from "react";
import { BrowserRouter } from "react-router-dom";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(
<BrowserRouter>
<App/>
</BrowserRouter>,
document.getElementById("app")
);
./styles/Main.scss
.header {
background-color: #002933;
}
我有2個webpack配置,其中1個用於客戶端,1個用於服務器:
webpack.config.dev.js
const nodeExternals = require("webpack-node-externals");
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
devtool: "cheap-module-eval-source-map",
entry: {
app: [
"eventsource-polyfill",
"webpack-hot-middleware/client",
"webpack/hot/only-dev-server",
"react-hot-loader/patch",
"./client/index.jsx",
],
vendor: [
"react",
"react-dom",
],
},
output: {
path: `${__dirname}/dist/client`,
...
},
...
module: {
loaders: [
...
}, {
test: /\.scss$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
{
loader: "css-loader",
query: {
localIdentName: "[hash:8]",
modules: true
}
}, {
loader: "postcss-loader"
}, {
loader: "sass-loader"
}
]
}),
},
],
},
plugins: [
new ExtractTextPlugin({
filename: "[name].css",
allChunks: true
}),
]
};
webpack.config.server.js
const ExternalsPlugin = require("webpack-externals-plugin");
module.exports = {
...
output: {
path: `${__dirname}/dist/`,
filename: "server.bundle.js",
},
...
resolve: {
...
modules: [
"client",
],
},
module: {
loaders: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: "babel-loader",
}, {
test: /\.scss$/,
loader: 'style-loader!css-loader/locals?module&localIdentName=[name]__[local]___[hash:base64:5]!sass-loader',
},
],
},
plugins: [
new ExternalsPlugin({
type: "commonjs",
include: `${__dirname}/node_modules/`,
}),
],
};
我有一個JSX文件,其中.header
應該應用於:
import React from "react";
import Links from "./Links.jsx";
import profilePic from "../../img/brand/profilePic.jpg";
import styles from "../../styles/Main.scss";
export default class Header extends React.Component {
constructor() {
super();
}
render() {
return (
<header className={styles.header}>
<img src={profilePic} alt="Professional Picture"/>
<h5>{this.props.pageName}</h5>
<Links/>
</header>
);
}
}
這引發了錯誤:
TypeError: Cannot read property 'header' of undefined
at Header.render (E:/Documents/Projects/website/client/js/components/Header.jsx:22:30)
at resolve (E:\Documents\Projects\website\node_modules\react-dom\cjs\react-dom-server.node.development.js:2149:18)
at ReactDOMServerRenderer.render (E:\Documents\Projects\website\node_modules\react-dom\cjs\react-dom-server.node.development.js:2260:22)
at ReactDOMServerRenderer.read (E:\Documents\Projects\website\node_modules\react-dom\cjs\react-dom-server.node.development.js:2234:19)
at Object.renderToString (E:\Documents\Projects\website\node_modules\react-dom\cjs\react-dom-server.node.development.js:2501:25)
at E:/Documents/Projects/website/server/config/lib/express.js:204:31
at Layer.handle [as handle_request] (E:\Documents\Projects\website\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (E:\Documents\Projects\website\node_modules\express\lib\router\index.js:317:13)
at E:\Documents\Projects\website\node_modules\express\lib\router\index.js:284:7
at Function.process_params (E:\Documents\Projects\website\node_modules\express\lib\router\index.js:335:12)
at next (E:\Documents\Projects\website\node_modules\express\lib\router\index.js:275:10)
at p3p (E:\Documents\Projects\website\node_modules\lusca\lib\p3p.js:15:9)
at E:\Documents\Projects\website\node_modules\lusca\index.js:59:28
at xframe (E:\Documents\Projects\website\node_modules\lusca\lib\xframes.js:12:9)
at E:\Documents\Projects\website\node_modules\lusca\index.js:59:28
at xssProtection (E:\Documents\Projects\website\node_modules\lusca\lib\xssprotection.js:16:9)
運行應用程序時,的WebPack報道稱,樣式表已加載:
編輯
除了ES6導入外,我嘗試像在MERN中一樣使用CommonJS的require()
,但是還是看不到...
現在,當我構建服務器的webpack配置時,我會收到錯誤消息:
ERROR in (webpack)-dev-middleware/node_modules/mime/index.js
Module not found: Error: Can't resolve './types/standard' in 'E:\Documents\Projects\website\node_modules\webpack-dev middleware\node_modules\mime'
@ (webpack)-dev-middleware/node_modules/mime/index.js 4:26-53
@ (webpack)-dev-middleware/index.js
@ ./server/config/lib/express.js
@ ./server/config/lib/app.js
@ ./server/server.js
我不確定這是否會在這種情況下出現,但我認為在這里值得一提,因為我很失落。 在這一點上,我感覺好像在抓着稻草。
這是我的.babelrc
:
{
"presets": [
"react",
"es2015",
"stage-0"
],
"plugins": [
"react-hot-loader/babel",
"transform-decorators-legacy"
],
"env": {
"server": {
"plugins": [
[
"css-modules-transform", {
"preprocessCss": "./loaders/sass-loader.js",
"generateScopedName": "[hash:8]",
"extensions": [".scss"]
}
]
]
},
"production": {
"presets": [
"es2015",
"react",
"react-optimize",
"es2015-native-modules",
"stage-0"
]
}
}
}
我試圖回到基礎上,讓babel處理服務器端捆綁而不是webpack。 這是從帶有CSS模塊的SSR 教程構建的,@ mootrichard很好地鏈接了我
編輯2
使用es6導入樣式表時,一些觀察結果可能會有所幫助:
import styles from "../../styles/Main.scss";
並將styles
記錄到控制台中,它會返回undefined (證明由於某種原因找不到文件) 。
將<link>
標記放在初始頁面的head
, <link>
標記出現在標記中,但不在網絡中:
但是,當導航到localhost:8000/app.css
,會發送帶有樣式的肯定響應:
如果瀏覽器可以獨立找到捆綁版本,那么為什么不將其加載到我的初始頁面中? (路徑正確)
我認為您的css / sass加載程序在webpack.config json層次結構中存在錯誤。 用以下“規則”數組替換模塊下的“加載程序”數組:
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader']
}),
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
],
},
您可以在此處查看ExtractTextPlugin用法的更多示例: https : //github.com/webpack-contrib/extract-text-webpack-plugin#usage
您遇到了問題,因為您使用的是css-loader/locals
,但未使用ExtractTextPlugin
(至少在Development中)。 https://github.com/webpack-contrib/css-loader/issues/59
注意:要使用extract-text-webpack-plugin進行預渲染,應在預渲染包中使用css-loader / locals而不是style-loader!css-loader。 它不嵌入CSS,而僅導出標識符映射。
這也解釋了為什么您無法訪問樣式變量.theHeader
。
此外,錯誤Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:3000/app.css".
是紅鯡魚。 這只是您嘗試加載甚至不存在的樣式表時收到的錯誤消息。 在這種情況下,該目錄似乎不在您認為的目錄中,或者實際上沒有在該目錄中生成。
由於ExtractTextPlugin
在開發中被禁用,因此您的CSS可能僅由css-loader/locals
。 這在生產中可能不是問題,因為它與ExtractTextPlugin
配對,但可以解釋您在開發中運行此問題。
更新:
在進一步研究這一點時,我遇到了一篇博客文章,我認為這可能會幫助您弄清楚如何配置CSS以便按您的意願工作。 https://medium.com/@mattvagni/server-side-rendering-with-css-modules-6b02f1238eb1
我認為這里復雜的主要原因是您通過ReactDOMServer通過HTML作為呈現的字符串發送HTML。 因此,webpack沒有在其中注入<link>
標記的位置。 您可能要考慮在標頭中僅包含<link>
標記以引用所需的CSS文件,因為webpack始終會創建一個CSS文件。
最后,我強烈建議您對Webpack進行更多的研究,特別是因為SSR是一個較新的過程,並且其處理方式與首次創建Webpack時最初預期的方式有所不同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.