Javascript Universal React.JS-需要样式和图像

Javascript Universal React.JS-需要样式和图像,javascript,reactjs,webpack,server-side,universal,Javascript,Reactjs,Webpack,Server Side,Universal,最近我涉足了React和Webpack,到目前为止我一直很喜欢它。当然,这需要大量的阅读,查看示例,并尝试一些东西,但最终,反应本身以及热重新加载我的组件在我身上成长,我非常确定我想继续这样做 在过去的几天里,尽管我一直在尝试让我的“应用程序”变得非常简单(到目前为止,它只是一个带有几个子组件的菜单,并显示一个虚拟页面) 以下是我的项目布局: 到目前为止,我的网页配置是这样的: let path = require("path"), webpack = require("webpack

最近我涉足了React和Webpack,到目前为止我一直很喜欢它。当然,这需要大量的阅读,查看示例,并尝试一些东西,但最终,反应本身以及热重新加载我的组件在我身上成长,我非常确定我想继续这样做

在过去的几天里,尽管我一直在尝试让我的“应用程序”变得非常简单(到目前为止,它只是一个带有几个子组件的菜单,并显示一个虚拟页面)

以下是我的项目布局:

到目前为止,我的网页配置是这样的:

let path = require("path"),
    webpack = require("webpack"),
    autoprefixer = require("autoprefixer");

module.exports = {
    entry: [
        "webpack-hot-middleware/client",
        "./client"
    ],
    output: {
        path: path.join(__dirname, "dist"),
        filename: "bundle.js",
        publicPath: "/static/"
    },
    resolve: {
        root: path.resolve(__dirname, "common")
    },
    module: {
        loaders: [
            { 
                test: /\.js$/, 
                loader: "babel", 
                exclude: /node_modules/,
                include: __dirname
            },
            { test: /\.scss$/, loader: "style!css!sass!postcss" },
            { test: /\.svg$/, loader: "file" }  
        ]
    },
    sassLoader: {
        includePaths: [path.resolve(__dirname, "common", "scss")]
    },
    plugins: [        
        new webpack.DefinePlugin({
            "process.env": {
                BROWSER: JSON.stringify(true),
                NODE_ENV: JSON.stringify( process.env.NODE_ENV || "development" )
            }
        }),
        new webpack.optimize.OccurenceOrderPlugin(),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoErrorsPlugin()
    ],
    postcss: [autoprefixer({remove: false})]
}
忽略模块要求,我的服务器:

// Initialize express server
const server = express();

const compiler = webpack(webpackConfig);
server.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: webpackConfig.output.publicPath }));
server.use(webpackHotMiddleware(compiler));

// Get the request
server.use((req, res) => {
    // Use React Router to match our request with our components
    const location = createLocation(req.url);
    match({routes, location}, (error, redirectLocation, renderProps) => {
        if (error) {
            res.status(500).send(error.message);
        } else if (redirectLocation) {
            res.redirect(302, redirectLocation.pathname + redirectLocation.search);
        } else if (renderProps) {
            res.send(renderFullPage(renderProps));
        } else {
            res.status(404).send("Not found");
        }
    })

});

function renderFullPage(renderProps) {
    let html = renderToString(<RoutingContext {...renderProps}/>);
    return  `<!DOCTYPE html>
                <html lang="en">
                <head>
                    <meta charset="utf-8">
                    <title></title>
                </head>
                <body>
                    <div id="app">${html}</div>
                    <script src="/static/bundle.js"></script>
                </body>
                </html>
            `;
}

server.listen(3000);
此外,我还需要在我的客户端上声明一个路由器,重新使用我的服务器已经使用的路由:

// Need to implement the router on the client too
import React from "react";
import ReactDOM from "react-dom";
import { Router } from "react-router";
import createBrowserHistory from "history/lib/createBrowserHistory";
import routes from "../common/Routes";

const history = createBrowserHistory();

ReactDOM.render(
    <Router children={routes} history={history} />,
    document.getElementById("app")
);
//也需要在客户端上实现路由器
从“React”导入React;
从“react dom”导入react dom;
从“反应路由器”导入{Router};
从“history/lib/createBrowserHistory”导入createBrowserHistory;
从“./common/routes”导入路由;
const history=createBrowserHistory();
ReactDOM.render(
,
document.getElementById(“应用程序”)
);
现在我在这里。我的风格很实用,一切都很好。我仍然不是专家,但到目前为止,我有点了解正在发生的一切(这是我没有使用现有的通用js/react样板文件的主要原因——实际上了解正在发生的事情)

但现在我要解决的下一个问题是如何在组件中要求我的图像。 使用此设置,它确实可以工作,但我收到以下警告:

Warning: React attempted to reuse markup in a container but the 
checksum was invalid. 
This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. 
React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
     (client) "><img class="logo" src="/static/31d8270
     (server) "><img class="logo" alt=""
警告:React试图重用容器中的标记,但
校验和无效。
这通常意味着您正在使用服务器呈现,并且在服务器上生成的标记不是客户机所期望的。
React注入了新的标记以补偿其效果,但您已经失去了服务器呈现的许多好处。相反,请找出在客户端或服务器上生成的标记不同的原因:
(客户)“>
现在我的问题是:
我的风格/形象要求正确吗?我错过了什么来摆脱这个警告

关于webpack/react关联,我喜欢的一件事是如何使这些依赖关系与使用它们的UI的实际部分保持接近。然而,我发现,在大多数教程中都忽略了一件事,那就是如何在呈现服务器端时保持这种甜蜜感。 如果你们能给我一些见解,我将不胜感激


非常感谢!

我推荐webpack同构工具作为解决方案

我有一节介绍如何将SVG导入示例项目中的React应用程序:


下面是将我的Universal React应用程序转换为一个接受SVG的应用程序所需的代码:

为此,您至少可以采取两种方法:

  • 尝试对代码进行网页打包以在节点中运行
  • 使用Webpack编译客户端代码
  • 第一个选项要求您删除特定于网页包的代码,例如
    require.sure/System.import
    ,并向node教授您的模块解析规则以及如何将非js资产转换为js。这可以通过一些babel转换实现,也可以修改
    节点路径
    ,但这种方法确实意味着您e不断地追逐你的尾巴,也就是说,如果你开始使用一个新的Webpack特性/加载程序/插件,你需要确保你能够支持Node中的等效功能

    第二种方法可能更实用,因为您可以确保正在使用的任何网页功能也能在服务器上工作。这是一种方法:

    // webpack.config.js
    module.exports = [
        {
            target: 'web',
            entry: './client',
            output: {
                path: dist,
                filename: 'client.js'
            }
        }, {
            target: 'node',
            entry: './server',
            output: {
                path: dist,
                filename: 'server.js',
                libraryTarget: 'commonjs2'
            }
        }
    ];
    


    // webpack.config.js
    module.exports = [
        {
            target: 'web',
            entry: './client',
            output: {
                path: dist,
                filename: 'client.js'
            }
        }, {
            target: 'node',
            entry: './server',
            output: {
                path: dist,
                filename: 'server.js',
                libraryTarget: 'commonjs2'
            }
        }
    ];
    
    // client.js
    renderToDom(MyApp, document.body);
    
    // server.js
    module.exports = (req, res, next) => {
        res.send(`
            <!doctype html>
            <html>
                <body>
                    ${renderToString(MyApp)}`
                    <script src="/dist/client.js"></script>
                </body>
            </html>
        `);
    }
    
    // index.js
    const serverRenderer = require('./dist/server');
    server.use(serverRenderer);
    server.listen(6060);