在同构反应应用程序中,是否有更简洁的方法在客户端和服务器端获取当前URL?

Dez*_*Dez 11 javascript node.js reactjs react-router react-redux

我正在开发基于一个应用程序这个阵营终极版样板.在一个组件中,我需要在安装组件时获取当前URL,以便为社交媒体生成可共享的URL.使用React Router可以从动态生成的URL访问组件.在客户端我通过javascript document对象获取它没有任何问题,但问题在于服务器端.

我想在Redux商店中提供保存在此config.js文件中的Node.js环境数据,其中保存了主机名

// Node.js environment file config.js    
require('babel-polyfill');

const environment = { 
  development: {
    isProduction: false
  },  
  production: {
    isProduction: true
  }
}[process.env.NODE_ENV || 'development'];

module.exports = Object.assign({
  host: process.env.HOST || 'localhost',
  port: process.env.PORT,
  apiHost: process.env.APIHOST || 'localhost',
  apiPort: process.env.APIPORT
}, environment);
Run Code Online (Sandbox Code Playgroud)

并将locationReact Router 的对象设置为组件中的props,获取路径名并完全构造URL.

我所做的是创建一个具有初始状态的简单reducer,以保持Node.js配置环境数据,并将我的combineReducers函数中包含的默认操作与其他app reducer一起包含.

const initialState = { 
  config: {}
};

export default function config(state = initialState, action = {}) {
  switch (action.type) {
    default:
      return state;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后我在我的server.js文件中将Node.js对象与创建存储中的环境数据一起注入初始状态数据.

import config from './config';
...
const store = createStore(memoryHistory, client, {config});
...
Run Code Online (Sandbox Code Playgroud)

因此,我有主机名,我可以在组件中通过Redux商店构建其客户端和服务器端的完整URL.

但是,有没有更简单/最干净的方式?我担心我可能会过度使用它或为我的应用程序创建任何安全问题.

Gur*_*bot 2

我在尝试使用 Helmet 服务器端时遇到了这个问题。我将请求作为 prop 传递给我的主要<App>组件,然后使用该请求对象(服务器端)或窗口对象(客户端)。

应用程序.js

render() {

    // Get full url from client or server
    let fullURL = ''
    if(typeof window !== 'undefined'){
        fullURL = window.location.protocol + '//' + window.location.host + this.props.location.pathname
    }else if(this.props.serverRequest){
        fullURL = this.props.serverRequest.headers.host + '/' + this.props.location.pathname
    }

    const urlTag = fullURL === '' ? null : <meta property="og:url" content={fullURL} />
    const linkTag = fullURL === '' ? null : <link rel="canonical" href={fullURL} />

    const helmet = this.props.siteInfo.site
        ? <Helmet>
            <title>{this.props.siteInfo.site.title}</title>
            <meta property="twitter:title" content={this.props.siteInfo.site.title} />
            {urlTag}
            {linkTag}
            <meta property="og:type" content="website" />
          </Helmet>
        : null

    return (
        <div>
            {helmet}
            <Notices />
            <div className="body">
                <Header />
                <Body />
            </div>
            <Footer />
        </div>
    )
}
Run Code Online (Sandbox Code Playgroud)

服务器.js

const markup = renderToString(
    <Provider store={store}>
        <StaticRouter location={req.url} context={context}>
            <App serverRequest={req} />
        </StaticRouter>
    </Provider>
)

const helmet = Helmet.renderStatic()
Run Code Online (Sandbox Code Playgroud)

这是“正确的”还是“最佳实践”?不知道,但它效果很好并且很容易遵循:)