簡體   English   中英

window 未定義服務器端渲染(react + express)

[英]window is not defined server side rendering(react + express)

如果請求瀏覽器URL,路由工作正常。

順便說一句,位置 = ${path}; 調用 react renderToString function 時出現 Component An error 的部分。

我正在查看 web 包設置之類的,但找不到原因。 幫助!

// 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的錯誤。 我真的很想解決它。 請幫忙。

為什么 SSR 中沒有定義window

在 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)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM