简体   繁体   English

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

[英]No loading/serving of stylesheets - react

I am attempting SSR with React router's StaticRouter . 我正在尝试使用React路由器的StaticRouter进行SSR。

express.js (server) 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>
`);

Serving of static files: 提供静态文件:

app.use(express.static(path.resolve(__dirname, "../dist/client")));

App.js (shared) App.js (共享)

import React from "react";
import { Switch, Route } from "react-router";

export default () => {
    return (
        <Switch>
            ...
        </Switch>
    );
};

index.jsx (client) 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 ./styles/Main.scss

.header {
    background-color: #002933;
}

I have 2 webpack configurations, 1 for the client & 1 for the server: 我有2个webpack配置,其中1个用于客户端,1个用于服务器:

webpack.config.dev.js 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 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/`,
        }),
    ],
};

I have a JSX file where the .header should be applied to: 我有一个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>
        );
    }
}

This throws the error: 这引发了错误:

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)

When running the application, webpack reports that the stylesheet has been loaded: 运行应用程序时,的WebPack报道称,样式表加载:

在此处输入图片说明

EDIT 编辑

Other than an ES6 import, I have attempted to use CommonJS' require() as in MERN but still no look... 除了ES6导入外,我尝试像在MERN中一样使用CommonJS的require() ,但是还是看不到...

When I build my server webpack config, I am now getting the error: 现在,当我构建服务器的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

I am not sure if this a red-herring or not in this situation or not but thought it worth mentioning here as I am quite lost. 我不确定这是否会在这种情况下出现,但我认为在这里值得一提,因为我很失落。 Feel as though I am clutching at straws at this point. 在这一点上,我感觉好像在抓着稻草。

This is my .babelrc : 这是我的.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"
            ]
        }
    }
}

I was attempting to go back to basics and have my babel handle server-side bundling instead of webpack. 我试图回到基础上,让babel处理服务器端捆绑而不是webpack。 This was built from a tutorial for SSR with CSS modules I was kindly linked to by @mootrichard 这是从带有CSS模块的SSR 教程构建的,@ mootrichard很好地链接了我

EDIT 2 编辑2

A few observations which might help...when using an es6 import for stylesheets: 使用es6导入样式表时,一些观察结果可能会有所帮助:

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

and log styles into the console, it returns undefined (evidence that it cannot find the file for some reason) . 并将styles记录到控制台中,它会返回undefined (证明由于某种原因找不到文件)

When putting the <link> tag in the head for the initial page, the <link> tag is present in the markup but not in the network: <link>标记放在初始页面的head<link>标记出现在标记中,但不在网络中:

在此处输入图片说明

在此处输入图片说明

However, when navigating to localhost:8000/app.css , a positive response with the styling is sent back: 但是,当导航到localhost:8000/app.css ,会发送带有样式的肯定响应:

在此处输入图片说明

If the browser can find the bundled version standalone, then why is it not being loaded in my initial page? 如果浏览器可以独立找到捆绑版本,那么为什么不将其加载到我的初始页面中? (The path is correct) (路径正确)

I think you have an error in your webpack.config json hierarchy for you css/sass loaders. 我认为您的css / sass加载程序在webpack.config json层次结构中存在错误。 Replace your "loaders" array under module with this "rules" array: 用以下“规则”数组替换模块下的“加载程序”数组:

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"
            })
        },
    ],
},

You can see more examples of ExtractTextPlugin usage here: https://github.com/webpack-contrib/extract-text-webpack-plugin#usage 您可以在此处查看ExtractTextPlugin用法的更多示例: https : //github.com/webpack-contrib/extract-text-webpack-plugin#usage

You're having issues because you're using css-loader/locals but not using ExtractTextPlugin (at least in Development). 您遇到了问题,因为您使用的是css-loader/locals ,但未使用ExtractTextPlugin (至少在Development中)。 https://github.com/webpack-contrib/css-loader/issues/59 https://github.com/webpack-contrib/css-loader/issues/59

Note: For prerendering with extract-text-webpack-plugin you should use css-loader/locals instead of style-loader!css-loader in the prerendering bundle. 注意:要使用extract-text-webpack-plugin进行预渲染,应在预渲染包中使用css-loader / locals而不是style-loader!css-loader。 It doesn't embed CSS but only exports the identifier mappings. 它不嵌入CSS,而仅导出标识符映射。

This also explains why you're not able to access the style variable .theHeader . 这也解释了为什么您无法访问样式变量.theHeader

Also, the error Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:3000/app.css". 此外,错误Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:3000/app.css". is a red herring. 是红鲱鱼。 That is simply the error message you receive if you try to load a stylesheet that doesn't even exist. 这只是您尝试加载甚至不存在的样式表时收到的错误消息。 Which in this case, doesn't appear to be in the directory that you think it is, or isn't actually being generated into a file there. 在这种情况下,该目录似乎不在您认为的目录中,或者实际上没有在该目录中生成。

Since ExtractTextPlugin is disabled in development, its likely that your CSS is only being processed by css-loader/locals . 由于ExtractTextPlugin在开发中被禁用,因此您的CSS可能仅由css-loader/locals This might not be a problem in production, since it pairs with ExtractTextPlugin but could explain your problems of running this in development. 这在生产中可能不是问题,因为它与ExtractTextPlugin配对,但可以解释您在开发中运行此问题。


Update: 更新:

In looking into this over a little more, I came across a blog post that I think might help you figure out how to configure your CSS to work how you want. 在进一步研究这一点时,我遇到了一篇博客文章,我认为这可能会帮助您弄清楚如何配置CSS以便按您的意愿工作。 https://medium.com/@mattvagni/server-side-rendering-with-css-modules-6b02f1238eb1 https://medium.com/@mattvagni/server-side-rendering-with-css-modules-6b02f1238eb1

I think the main reason for the complication here is that you're sending over the HTML as a rendered string via ReactDOMServer. 我认为这里复杂的主要原因是您通过ReactDOMServer通过HTML作为呈现的字符串发送HTML。 So there is no where for webpack to inject a <link> tag into. 因此,webpack没有在其中注入<link>标记的位置。 You might want to consider just having a <link> tag in your header to reference your desired CSS file, since webpack is going to create a single CSS file anyways. 您可能要考虑在标头中仅包含<link>标记以引用所需的CSS文件,因为webpack始终会创建一个CSS文件。

Finally, I highly recommend studying a bit more on webpack, especially since SSR is a newer process and requires doing things a bit differently than many have initially anticipated when webpack was first created. 最后,我强烈建议您对Webpack进行更多的研究,特别是因为SSR是一个较新的过程,并且其处理方式与首次创建Webpack时最初预期的方式有所不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM