2016-10-10 67 views
3

我有一个react-redux应用程序在aspnet核心上运行,服务器端渲染使用aspnet预渲染。Aspnet服务器渲染调试

可以说我犯了一个编程错误,在儿童组件中,我尝试访问一个未定义的道具,因为一个愚蠢的错字。

import {Child} from './child' 
export class Parent extends React.Component { 
    render() { 
    const someProp = { 
     something: "something" 
    }; 
    return <Child someProp={someProp} />; 
    } 
} 

export class Child extends React.Component { 
    render() { 
    return <div>this.props.someprop.something</div>; 
     //typo: should be someProp instead of someprop 
} 

没有服务器渲染,我会得到类似这样的错误:在x行不能访问的不确定的东西:YY 但随着serverrendering我得到一个:

An unhandled exception occurred while processing the request.

Exception: Call to Node module failed with error: Prerendering timed out after 30000ms because the boot function in 'ClientApp/src/boot-server' returned a promise that did not resolve or reject. Make sure that your boot function always resolves or rejects its promise. You can change the timeout value using the 'asp-prerender-timeout' tag helper.

这使得调试很难,当你没有得到任何错误的反馈。 任何人知道如何设置一个拒绝,如果失败了?或者甚至有可能调试服务器端呈现的代码?

这里是我的启动服务器文件,告诉我你是否需要更多的文件。

import * as React from 'react'; 
import { Provider } from 'react-redux'; 
import { renderToString } from 'react-dom/server'; 
import configureStore from './store/configureStore'; 
import {getFormById} from './actions/getFormActions'; 
import {updateUserLocale} from './actions/userLocaleActions'; 
import FormResponder from './components/mainComponents/formResponder'; 

export default function renderApp (params) { 

    return new Promise((resolve, reject) => { 

     const store = configureStore(); 
     store.dispatch(getFormById(params.data.id, params.data.config, params.data.authenticationToken)); 
     store.dispatch(updateUserLocale(params.data.userLocale)); 
     const app = (
      <Provider store={ store }> 
       <FormResponder /> 
      </Provider> 
     ); 

    // Perform an initial render that will cause any async tasks (e.g., data access) to begin 
    renderToString(app); 

    // Once the tasks are done, we can perform the final render 
    // We also send the redux store state, so the client can continue execution where the server left off 
    params.domainTasks.then(() => { 
     resolve({ 
      html: renderToString(app), 
      globals: { 
       initialReduxState: store.getState(), 
       authenticationToken: params.data.authenticationToken, 
       config: params.data.config 
      } 
     }); 
    }, reject); // Also propagate any errors back into the host application 
}); 
} 

回答

1

发现,对于我工作的解决方案:我插一试 /风行最终的renderToString。 在catch中我发送一个包含错误的调度。

更新引导server.jsx

params.domainTasks.then(() => { 
     let html; 
     try { 
      html = renderToString(app); 
     } 
     catch (err) { 
      store.dispatch(loadFormFailed({message: err.toString() })); 
     } 

     resolve({ 
      html: html, 
      globals: { 
       initialReduxState: store.getState(), 
       authenticationToken: params.data.authenticationToken, 
       config: params.data.config, 
       disableReactServerRendring: false 
      } 
     }); 
     }, reject); 
     // Also propagate any errors back into the host application 
    }); 
2

我已经做了索姆研究,并得出结论:这是不可能的时间beeing调试初始服务器渲染代码。

我做的反而是实现逻辑,以便我可以禁用服务器渲染。

这是它的样子:

public async Task<IActionResult> Index(string id, string userLocale = "en", bool server = true) 
{ 
    Guid positionId; 
    if (!Guid.TryParse(id, out positionId)) 
    { 
     throw new Exception("Invalid position id");   
    } 

    var token = await _apiClient.GetToken(); 

    var formData = new ApplicationFormViewModel() 
    { 
     Id = positionId, 
     UserLocale = userLocale, 
     AuthenticationToken = token.AccessToken, 
     Server = server 
    }; 
    return View(formData); 
} 

view.cshtml:

@{if (@Model.Server) { 
    <div 
    class="container" 
    id="react-app" 
    asp-prerender-module="ClientApp/src/boot-server" 
    asp-prerender-data="new { 
     Id = @Model.Id, 
     UserLocale = @Model.UserLocale, 
     AuthenticationToken = @Model.AuthenticationToken, 
     Config = new { 
      ApplicationPostUrl = @Url.Action("SaveApplication"), 
      AttachmentPostUrl = @Url.Action("UploadAttachment"), 
      FormGetUrl = @Url.Action("GetForm") 
     } 
    }" 
    asp-prerender-webpack-config="webpack.config.js" > 
     Loading... 
</div> 
} 
else { 
    <script> 
     var id= '@Model.Id'; 
     var config= { 
      applicationPostUrl: '@Url.Action("SaveApplication")', 
      attachmentPostUrl: '@Url.Action("UploadAttachment")', 
      formGetUrl: '@Url.Action("GetForm")' 
     }; 
     var userLocale='@Model.UserLocale'; 
     var authenticationToken='@Model.AuthenticationToken'; 
     var server = false; 
    </script> 
    <div class="container" id="react-app">loading</div> 

} 
} 



@section scripts { 

    <script src="~/dist/main.js" asp-append-version="true"></script> 
} 

启动server.jsx:

export default function renderApp (params) { 

    return new Promise((resolve, reject) => { 

     const store = configureStore(); 
     store.dispatch(getFormById(params.data.id, params.data.config, params.data.authenticationToken)); 
     store.dispatch(updateUserLocale(params.data.userLocale)); 
     const app = (
      <Provider store={ store }> 
       <FormResponder /> 
      </Provider> 
     ); 

    // Perform an initial render that will cause any async tasks (e.g., data access) to begin 
    renderToString(app); 

    // Once the tasks are done, we can perform the final render 
    // We also send the redux store state, so the client can continue execution where the server left off 
    params.domainTasks.then(() => { 
     resolve({ 
      html: renderToString(app), 
      globals: { 
       initialReduxState: store.getState(), 
       authenticationToken: params.data.authenticationToken, 
       config: params.data.config, 
       server: true 
      } 
     }); 
     }, reject); // Also propagate any errors back into the host application 
}); 
} 

启动client.jsx:

// Grab the state from a global injected into server-generated HTML 
const {id, initialReduxState, authenticationToken, config, server, userLocale } = window; 

if (server) { 


// Get the application-wide store instance, prepopulating with state from the server where available. 
const store = configureStore(initialReduxState); 
// This code starts up the React app when it runs in a browser. 
ReactDOM.render(
    <Provider store={ store }> 
     <FormResponder authenticationToken={authenticationToken} config={config} /> 
    </Provider>, 
    document.getElementById('react-app') 
); 


} 
else { 

    const store = configureStore(); 
    store.dispatch(getFormById(id, config, authenticationToken)); 
    store.dispatch(updateUserLocale(userLocale)); 

    render(
     <Provider store ={store}> 
      <FormResponder authenticationToken={authenticationToken} config={config} /> 
     </Provider>, 
     document.getElementById('react-app') 
    ); // Take our FormBuilder component and attach it with DOM element "app" 
} 

所以现在我可以简单地通过在URL的末尾添加服务器=假开启服务器渲染,并开始调试:)

4

我有过类似的经历与Visual Studio 2017年的工作我最终意识到,原来的(多个)错误诊断的信息实际上在输出窗口。

+0

你刚刚救了我疯了! – racamp101