简体   繁体   English

使用热重载的ReactJS服务器端渲染(webpack-dev-server)

[英]ReactJS server side rendering with hot reloading (webpack-dev-server)

I'm trying to build my first server side rendering with ReactJS. 我正在尝试使用ReactJS构建我的第一个服务器端渲染。 I've based my code from this Redux tutorial 我已经从Redux教程中获得了代码

The application is working fine when running npm start ( webpack && node server.js ). 运行npm startwebpack && node server.js )时,应用程序运行正常。

I want to use hot reloading to be able to do an application fast debugging on dev environment. 我想使用热重装能够在开发环境上进行应用程序快速调试。 So I've added the start option on my npm configuration ( webpack-dev-server --inline --hot ). 因此,我在npm配置中添加了start选项( webpack-dev-server --inline --hot )。 Notice that I don't have a index.html file as react-router is choosing the proper JSX file to load. 注意,我没有index.html文件,因为react-router正在选择要加载的正确JSX文件。

npm start opens my public folder and show files, but does no start my application. npm start打开我的公用文件夹并显示文件,但不启动我的应用程序。 Normally I would click on a index.html file, but I have none. 通常,我会单击index.html文件,但没有任何文件。

I can't understand what's going on and don't know how to solve. 我不明白发生了什么,也不知道如何解决。 Help appreciated. 帮助表示赞赏。

package.json: 的package.json:

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config webpack.config.prod.js -p",
    "start": "webpack-dev-server --inline --hot",
    "dev": "webpack && node server.js"
  },

webpack.config.js: webpack.config.js:

module.exports = {
    entry: './client.js',
    output: {
        filename: 'bundle.js',
        path: __dirname + '/public'
    },
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                query: {
                    presets: ['react', 'es2015', 'stage-0']
                }
            }
        ]
    }
};

server.js server.js

require('babel-register')({
    presets: ['react', 'es2015', 'stage-0']
});

var express = require('express');
var config = require('config');
var app = express();

var serverConfig = config.get('serverConfig');

app.use(express.static('public'));
app.use(require('./routes/index.jsx'));

app.listen(serverConfig.port, function () {
    console.log('FactoryWays server running on port ' + serverConfig.port);
    console.log('Press CTRL-C to stop the server.');
});

client.js client.js

var ReactDOM = require('react-dom');
var React = require('react');
var routes = require('./routes/routes.jsx');
var Redux = require('redux');
var Provider = require('react-redux').Provider;

function reducer(state) { return state; }

var store = Redux.createStore(reducer, window.PROPS);

ReactDOM.render(
    <Provider store={store}>
        {routes}
    </Provider>, document
);

routes/index.jsx: 路线/ index.jsx:

var router = require('express').Router();
var React = require('react');
var ReactDOMServer = require('react-dom/server');
var ReactRouter = require('react-router');
var Redux = require('redux');
var Provider = require('react-redux').Provider;

function reducer(state) { return state; }

router.get('*', function(request, response) {
    var initialState = { title: 'Universal React' };
    var store = Redux.createStore(reducer, initialState);

    ReactRouter.match({
        routes: require('./routes.jsx'),
        location: request.url
    }, function(error, redirectLocation, renderProps) {
        if (renderProps) {
            var html = ReactDOMServer.renderToString(
                <Provider store={store}>
                    <ReactRouter.RouterContext {...renderProps} />
                </Provider>
            );
            response.send(html);
        } else {
            response.status(404).send('Not Found');
        }
    });
});

module.exports = router;

routes/routes.jsx: 路线/ routes.jsx:

var React = require('react');
var ReactRouter = require('react-router');
var Router = ReactRouter.Router;
var Route = ReactRouter.Route;
var IndexRoute = ReactRouter.IndexRoute;
var browserHistory = ReactRouter.browserHistory;

module.exports = (
    <Router history={browserHistory}>
        <Route path='/' component={require('../views/Layout.jsx')}>
            <IndexRoute component={require('../views/Index.jsx')} />
        </Route>
    </Router>
);

views/Layout.jsx: 意见/ Layout.jsx:

var React = require('react');
var Link = require('react-router').Link;
var connect = require('react-redux').connect;

var Layout = React.createClass({
    _handleClick: function() {
        alert();
    },
    render: function() {
        var custom = this.props.custom;
        return (
            <html>
                <head>
                    <title>{custom.title}</title>
                    <link rel='stylesheet' href='/style.css' />
                </head>
                <body>
                    <h1>{custom.title}</h1>
                    <p>Isn't server-side rendering remarkable?</p>
                    <button onClick={this._handleClick}>Click Me</button>
                    {this.props.children}
                    <ul>
                        <li>
                            <Link to='/'>Home</Link>
                        </li>
                        <li>
                            <Link to='/about'>About</Link>
                        </li>
                    </ul>
                    <script dangerouslySetInnerHTML={{
                        __html: 'window.PROPS=' + JSON.stringify(custom)
                    }} />
                    <script src='/bundle.js' />
                </body>
            </html>
        );
    }
});

var wrapper = connect(
    function(state) {
        return { custom: state };
    }
);

module.exports = wrapper(Layout);

Notice that I don't have a index.html file as react-router is choosing the proper JSX file to load 注意,我没有index.html文件,因为react-router正在选择要加载的正确JSX文件

You still need one if you're running webpack-dev-server . 如果您正在运行webpack-dev-server则仍然需要一个。

Webpack is used to bundle JavaScript together. Webpack用于将JavaScript捆绑在一起。 That's it. 而已。 In your case (based on your webpack.config.js file), it's outputting a bundle.js file in your public directory. 就您而言(基于webpack.config.js文件),它将在您的public目录中输出bundle.js文件。

Webpack Dev Server is a simple static file server to aid development. Webpack Dev Server是一个简单的静态文件服务器,有助于开发。 It doesn't know anything about your server configuration in server.js . 它对server.js的服务器配置一无所知。

Your two commands in your package.json require different setups: package.json中的两个命令需要不同的设置:

npm start

npm start runs webpack-dev-server . npm start运行webpack-dev-server By default, webpack-dev-server will serve the contents of your current directory, so you'll need to put your an index.html in the root directory of your project. 默认情况下, webpack-dev-server将提供当前目录的内容,因此您需要将index.html放在项目的根目录中。 The contents of index.html are simple: just boilerplate HTML that includes a script tag linking to your bundle.js file. index.html的内容很简单:只是样板HTML,其中包含链接到bundle.js文件的script标签。

npm dev

When you're running npm dev however, you're rolling your own server, defined in server.js . 但是,当您运行npm dev时,您正在滚动自己的服务器,该服务器在server.js定义。 In that case it's configured to generate and serve an index.html (as well as all the other static files you need) for you. 在这种情况下,它被配置为为您生成并提供index.html (以及您需要的所有其他静态文件)。

If you want to do hot-reloading and run your own server, you can add webpack-dev-middleware to your Express server. 如果要进行热重装运行自己的服务器,可以将webpack-dev-middleware添加到Express服务器。

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

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