没有加载/提供样式表 - 反应

时间:2018-02-15 22:23:27

标签: javascript reactjs webpack

我正在尝试使用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")
);

./风格/ Main.scss

.header {
    background-color: #002933;
}

我有2个webpack配置,1个用于客户端&amp; 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会报告已加载样式表

enter image description here

修改

除了ES6导入外,我还尝试使用CommonJS&#39; require() 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 ,但仍然没有...... {/ p>

当我构建我的服务器webpack配置时,我现在收到错误:

.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" ] } } }

import styles from "../../styles/Main.scss";

我试图回归基础并让我的babel处理服务器端捆绑而不是webpack。这是由MERN建立的SSR与CSS模块我亲切地链接到@mootrichard

编辑2

对样式表使用es6导入时可能会有所帮助的一些观察结果:

styles

并将<link>记录到控制台中,它会返回 undefined (证明由于某种原因无法找到该文件)

head标记放在初始页面的<link>中时,标记中会显示localhost:8000/app.css标记,但网络中:< / p>

tutorial

enter image description here

然而,当导航到class Parent def my_method puts "Value of FOO is #{FOO}" end end class Child < Parent FOO = "bar" end Child.new.my_method #=> NameError: uninitialized constant Parent::FOO 时,会回复带有样式的正面回复:

enter image description here

如果浏览器可以单独找到捆绑版本,那么为什么它没有在我的初始页面中加载? (路径正确)

2 个答案:

答案 0 :(得分:2)

我认为你的webpack.config json层次结构中有一个错误,你的css / sass加载器。用这个“rules”数组替换模块下的“loaders”数组:

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

答案 1 :(得分:2)

您遇到问题是因为您使用css-loader/locals但未使用ExtractTextPlugin(至少在开发中)。 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作为呈现的字符串发送。因此webpack没有注入<link>标记的位置。您可能需要考虑在标题中添加<link>标记以引用所需的CSS文件,因为webpack将创建单个CSS文件。

最后,我强烈建议在webpack上学习更多内容,特别是因为SSR是一个较新的过程,并且要求做的事情与许多人在最初创建webpack时最初预期的有所不同。