我正在开发一个使用服务器端渲染的反应应用程序。 我的路线工作,主页除外。不知道为什么。我假设我没有正确设置我的快速服务器来处理索引路由......?
以下是处理快递的模块。设置等等。我假设我app.get('*)
或app.use(express.static)
不正确。
app.js(服务器)
require('ignore-styles')
const compression = require('compression')
const express = require('express')
const path = require('path')
require('babel-register')({
ignore: /\/(build|node_modules)\//,
presets: ['env', 'react-app']
})
const universalLoader = require('./universal')
const app = express()
// Support Gzip
app.use(compression())
// Serve static assets
app.use(express.static(path.resolve(__dirname, '..', 'build')))
// Always return the main index.html, so react-router render the route in the client
app.get('*', universalLoader)
module.exports = app
universalLoader.js(服务器)
import path from 'path'
import fs from 'fs'
import React from 'react'
import { Provider } from 'react-redux'
import { renderToString } from 'react-dom/server'
import { StaticRouter, matchPath } from 'react-router-dom'
import configureStore from '../src/store'
import App from '../src/components/App'
import routes from '../src/shared/routes'
import { getSiteInfo } from '../src/store/actions/siteInfo'
import { REACT_APP_SITE_KEY } from '../src/shared/vars'
import Helmet from 'react-helmet'
module.exports = function universalLoader(req, res, next) {
// console.log('Loading....')
const store = configureStore()
const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl
let routeFound = false
// Try to find a matched route
const promises = routes.reduce((promise, route) => {
var props = matchPath(req.url, route)
// If route was matched, component exists, and has an initialAction
// then call it's initialAction.
// This action will most-likely load some data asyncronously
if (props && route.component && route.component.initialAction) {
promise.push(Promise.resolve(store.dispatch(route.component.initialAction(store, props))))
}
return promise
}, [])
// Load initial site data
promises.push(Promise.resolve(store.dispatch(getSiteInfo(REACT_APP_SITE_KEY))))
// Wait until all async data has been loaded
Promise.all(promises)
.then(() => {
// Load index file path
const filePath = path.resolve(__dirname, '..', 'build', 'index.html')
// Read index file
fs.readFile(filePath, 'utf8', (err, htmlData) => {
if(err){
console.error('read err', err)
return res.status(404).end()
}
const preloadedState = store.getState()
// console.log("PreloadedState:", preloadedState)
const context = preloadedState
// console.log(context)
// Note: Pass in serverRequest prop so the App knows the domain it's on for meta tags
const markup = renderToString(
<Provider store={store}>
<StaticRouter location={req.url} context={context}>
<App serverRequest={req} serverResponse={res} />
</StaticRouter>
</Provider>
)
const helmet = Helmet.renderStatic()
// Somewhere a `<Redirect>` was rendered
if(context.url){
console.log('Redirected:', context.url)
redirect(301, context.url)
// we're good, send the response
}else{
// Page meta data
const meta = helmet.title.toString() + helmet.meta.toString() + helmet.link.toString()
// Prep state to be injected into DOM for client
const pageState = `<script>window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\u003c')}</script>`
// Inject state and markup
const RenderedApp = htmlData
.replace('<script></script>', pageState) // Store state to pass to client
.replace('<meta name="helmet">', meta) // Meta data
.replace('{{SSR}}', markup) // Actual markup/component html
console.log("SSR Rendered: ", req.path)
res.send(RenderedApp)
}
})
})
.catch(err => {
console.log("Error:", err)
})
}
我是console.log()
- 在universalLoader()
内处理路线时。所有路线都在控制台中显示正在发生的事情。除了我的主页。它甚至没有显示&#34;正在加载......&#34;消息。
答案 0 :(得分:1)
express.static
将提供build
目录中的所有文件。如果它找到所请求的文件,它将提供它并结束请求/响应。如果找到合适的文件,express.static
之后注册的中间件将无法运行。
基于这一行:
const filePath = path.resolve(__dirname, '..', 'build', 'index.html')
您的index.html
目录中似乎有一个名为build
的文件。当您点击express.static
的网址时,这将由index.html
提供,但如果您点击/
网址,它也会被提供,因为express.static
默认提供服务index.html
。请在此处查看index
属性:
https://expressjs.com/en/4x/api.html#express.static
您指向的目录express.static
需要包含静态的文件,即无需任何处理的文件。如果任何文件需要处理,他们需要住在其他地方。请注意Express应用程序通常具有views
单独文件夹的方式,这在很多方面类似于您尝试做的事情。
我还建议评论express.static
,看看它有什么影响。它应该是确认express.static
负责停止索引路径的快速方法。
<强>更新强>
根据您的评论,您似乎在build/static
处有一个包含JS和CSS文件的静态目录。您可以直接使用以下方式提供此服务:
app.use(express.static(path.resolve(__dirname, '..', 'build', 'static')))
但是,这会导致您的所有网址也发生变化,因此http://localhost/static/js/example.js
现在将为http://localhost/js/example.js
。要保留原始网址,您需要通过路径路径重新放入static
:
app.use('/static', express.static(path.resolve(__dirname, '..', 'build', 'static')))