reactjs - 浏览器历史记录需要 DOM

标签 reactjs express create-react-app server-side-rendering

已经有围绕此主题的问题,其解决方案指向服务器上的内存历史记录。但是,我这样做了,问题仍然存在于 client 文件夹内的 store.js 上。虽然我没有使用这个 client/store.js 它仍然给我带来与主题相同的错误。

所以我的猜测是我在服务器或客户端包装组件的方式有问题。

我正在开发已经加载的项目堆栈 - redux、react-redux、react-router-redux、redux-thunk、history 等...老实说,为 SSR 设置添加这些内容对我来说是令人畏惧的 -服务器端渲染(我的基本动机) 我将分享我的结构和本练习中涉及的重要文件!

首先欢迎服务器到来。

server/bootstrap.js

require('ignore-styles');
require('babel-register')({
    ignore: [ /(node_modules)/ ],
    presets: ['es2015', 'react-app']
});
require('./index');

服务器/index.js

import express from 'express';
import serverRenderer from './middleware/renderer';

const PORT = 3000;
const path = require('path');
const app = express();
const router = express.Router();

// root (/) should always serve our server rendered page
router.use('^/$', serverRenderer);
// other static resources should just be served as they are
router.use(express.static(
    path.resolve(__dirname, '..', 'build'),
    { maxAge: '30d' },
));
router.use('*', serverRenderer);
// tell the app to use the above rules
app.use(router);
// start the app
app.listen(PORT, (error) => {
    if (error) {
        return console.log('something bad happened', error);
    }

    console.log("listening on " + PORT + "...");
});

server/middleware/renderer.js

import React from 'react'
import ReactDOMServer from 'react-dom/server';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import store from '../../src/store';
import {createMemoryHistory } from 'history';
import { StaticRouter } from 'react-router'

// import our main App component
import App from '../../src/index';
const path = require("path");
const fs = require("fs");
const history = createMemoryHistory({
  initialEntries: ['/', '/next', '/last'],
  initialIndex: 0
})
export default (req, res, next) => {
    const filePath = path.resolve(__dirname, '..', '..', 'build', 'index.html');
    fs.readFile(filePath, 'utf8', (err, htmlData) => {
        if (err) {
            console.error('err', err);
            return res.status(404).end()
        }
        const html = ReactDOMServer.renderToString(
            <Provider store={store}>
              <ConnectedRouter history={history}>
                <App />
              </ConnectedRouter>
            </Provider>
        );
        return res.send(
            htmlData.replace(
                '<div id="root"></div>',
                `<div id="root">${html}</div>`
            )
        );
    });
}

我的 src 文件夹结构将是

  • 组件
  • 容器
    • 应用程序
      • index.js
      • styles.js
  • index.js
  • store.js

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import { StaticRouter } from 'react-router'

import './index.css';
import store, { history } from './store';
import App from './containers/app';

const target = document.querySelector('#root');

ReactDOM.render(
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <App />
    </ConnectedRouter>
  </Provider>,
  target
);

难以理解的难题

src/store.js

import { createStore, applyMiddleware, compose } from 'redux';
import { routerMiddleware } from 'react-router-redux';
import thunk from 'redux-thunk';
import createHistory from 'history/createBrowserHistory';
import rootReducer from './reducers';

export const history = createHistory();

const initialState = {};
const enhancers = [];
const middleware = [thunk, routerMiddleware(history)];

if (process.env.NODE_ENV === 'development') {
  const devToolsExtension = window.devToolsExtension;

  if (typeof devToolsExtension === 'function') {
    enhancers.push(devToolsExtension());
  }
}

const composedEnhancers = compose(applyMiddleware(...middleware), ...enhancers);

const store = createStore(rootReducer, initialState, composedEnhancers);

export default store;

在运行节点 server/bootstrap.js 时,它给我一个错误 不变违规:浏览器历史记录需要 DOM 并且此错误在 store.js 中生成

如果有人可以通过分享的代码让我知道我对当前 SSR 的 create-react-app 做错了什么以及在哪里!

最佳答案

我加载了该应用程序两次。一旦在客户端,其他在服务器。 我使用相同的设置(提供程序和连接的路由器)单独在服务器中进行渲染,并将 createBrowserHistory 更改为 createMemoryHistory ,并且它有效。

关于reactjs - 浏览器历史记录需要 DOM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48649569/

相关文章:

reactjs - 在 react-admin 中实现后退按钮

javascript - 在 React Native 中需要图像模块时遇到问题

node.js - 如何在 typescript 中获得与express的Post方法相同的数据类型

javascript - 如何使用 Node 和羽毛笔?

reactjs - 为什么调试器要求我再次弹出?

github-pages - 如何使用 github 页面修复 manifest.json 404

reactjs - 如何创建验证字符串格式的 typescript 类型?即检查字符串是否有效 css 长度属性

node.js - Express JS 在重启时保持 session 事件

javascript - react-bootstrap 选项卡 - 内容未显示

javascript - react JSX : href path inside an array of anchor tags is referencing the last path in a loop