2016-10-10 12 views
3

aspnet prerenderingを使用してサーバサイドレンダリングを行う、aspnetコアで動作するreact-reduxアプリケーションがあります。Aspnetサーバレンダリングデバッグ

私は子供のコンポーネントで私は愚かなタイプミスのために未定義の小道具にアクセスしようとすると、プログラミングエラーを起こしていると言います。線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 {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 
} 

あなたが何が間違っていたかについてのフィードバックを得ることができないときはかなり難しいです。 何かが失敗した場合に拒否をセットアップする方法を知っている人はいますか?またはサーバーサイドのレンダリングされたコードをデバッグすることも可能ですか?

ここは私のブートサーバーファイルです。ファイルがいくつか必要な場合は教えてください。

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

私はSOMの研究を行っていると、最初のサーバーレンダリングされたコードをデバッグするために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

関連する問題