【问题标题】:window is not defined server side rendering(react + express)窗口未定义服务器端渲染(react + express)
【发布时间】:2020-11-16 04:11:58
【问题描述】:

如果请求浏览器URL,路由正常工作。

顺便说一句,location = ${path}; 调用react renderToString函数时出现Component An error的部分。

我正在查看 webpack 设置或其他内容,但找不到原因。救命!

// App.js

import React, {useState, useEffect} from 'react';
import moment from "moment";
import Header from "./components/header/Header";
import Footer from "./components/footer/Footer";

export default function App() {

    const [time, setTime] = useState(null);

    useEffect(() => {
        console.log('use effect..');
        setTime(moment().format('hh:mm:ss a'));
    }, []);

    return (
        <div style={{height:'100%'}}>
            <Header/>
            <div style={{height:'100%'}}>
                <h1>Sample App</h1>
                <p>Current time is {time}</p>
            </div>
            <Footer/>
        </div>
    )

}

// Header.js

import React from 'react';

export default function Header() {

    function goPage(path) {
        console.log(`goPage..`);
        console.log(window.location); // error
        // window.location = path;
    }

    return (
        <header style={{width: '100%', border: '1px dotted black'}}>
            <div>
                <span style={{padding: '4px'}}>My App |</span>
                <span style={{padding: '4px', cursor: 'pointer'}}>Home</span>
                <span style={{padding: '4px', cursor: 'pointer'}} onClick={goPage('/about')}>About</span>
            </div>
        </header>
    )
}


server.js

const express = require('express');
const path = require('path');
import React from 'react';
import ReactDOMServer from 'react-dom/server';

const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const config = require('../webpack.config.js');
const compiler = webpack(config);

import Router from '../routes/index';

import App from '../src/App';
import Html from "../src/Html";

const expressApp = express();
const port = process.env.PORT || 3000;

if (process.env.NODE_ENV != 'production') {
    expressApp.use(webpackDevMiddleware(compiler, {
        publicPath: '/'
    }));
}
expressApp.use(express.static(path.join(__dirname, '')));

expressApp.get('*', (request, response) => {

    console.log('request.. in express');
    console.log(Router.match(request));
    const component = ReactDOMServer.renderToString(Router.match(request));

    const html = ReactDOMServer.renderToStaticMarkup(<Html
        title="Sample Title"
        description="Isomorphic web application sample"
        body={component}
    />);

    response.send(`<!DOCTYPE html>` + html);

});


expressApp.listen(port, () => {
    console.log(`App is listening at http://localhost:${port}/`);
});


// Router

import React from 'react';

import App from "../src/App";
import NotFound from "../src/components/error/NotFound";
import Error from "../src/components/error/Error";
import About from "../src/components/about/About";

const routes = [
    {name : 'home', path : '/', action : () => <App/>},
    {name : 'about', path : '/about', action : () => <About/>},
    {name : '404', path : '/404', action : () => <NotFound/>},
    {name : '500', path : '/500', action : () => <Error/>},
];


export default {
    match(location) {
        console.log(location.path);
        const route = routes.find(x => x.path === location.path);

        if (route) {
            try {
                return route.action();
            } catch (err) {
                console.log('err');
                return routes.find(x => x.path === '/500').action();
            }
        } else {
            console.log('404');
            return routes.find(x => x.path === '/404').action();
        }
    }
}

// webpack config

const path = require('path');

// plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
const nodeExternals = require('webpack-node-externals');


// SSR
const ssr = {
    mode : 'development',
    entry: './server/server.js',
    output: {
        path: path.join(__dirname, '/build'),
        filename: "server.js",
    },
    target: 'node',
    node: false,
    externals: [nodeExternals()],
    resolve: {
        modules: ['node_modules']
    },
    module: {
        rules: [
            {
                test: /(.js|.jsx)/,
                exclude: /node_modules/,
                include: [
                    path.join(__dirname, '/src'),
                    path.join(__dirname, '/routes/index.js'),
                    path.join(__dirname, '/server/server.js'),
                ],
                use: {
                    loader: 'babel-loader'
                }
            },
        ]
    },

    plugins: [
        new CleanWebpackPlugin({
            cleanAfterEveryBuildPatterns: ['build']
        })
    ],
};

// CSR
const csr = {
    mode : 'development',
    entry:'./client/client.js',
    output: {
        publicPath: '/',
        path: path.join(__dirname, '/build'),
        filename: 'client.js'
    },
    target: 'web',
    module: {
        rules: [
            {
                test: /(.js|.jsx)/,
                exclude: /node_modules/,
                include: [
                    path.join(__dirname, '/src'),
                    path.join(__dirname, '/routes/index.js'),
                    path.join(__dirname, '/client/client.js'),
                ],
                use: {
                    loader: 'babel-loader'
                }
            },
        ]
    },
    // devtool: 'source-map',
    plugins: [
        new MomentLocalesPlugin({
            localesToKeep: ['es-us', 'ru'],
        }),
    ]
};


module.exports = [ssr, csr];

服务器由express组成,设置为babel7和webpack4。 如果您查看 server.js 部分,您会在请求 URL 中获得相应的 react 组件。 如果在获取的组件上调用renderToString(),会出现window is not defined的错误。 我真的很想解决它。请帮忙。

【问题讨论】:

标签: javascript node.js reactjs express webpack


【解决方案1】:

为什么window没有在SSR中定义

在ssr上没有window的定义。因为 window 是一个基于浏览器的属性。

你需要做一些事情来避免这种情况。例如

function goPage(path) {
        console.log(`goPage..`);
        if (window) {
           console.log(window.location);
        }
    }

在服务器端你可以通过这个获取url

req.url
// or
app.get('/users/:userId/books/:bookId', function (req, res) {
  console.log(req.params)
}

【讨论】:

    猜你喜欢
    • 2018-04-26
    • 2021-12-18
    • 2017-12-30
    • 1970-01-01
    • 2018-08-06
    • 2019-10-18
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    相关资源
    最近更新 更多