2017-03-19 5 views
0

ファーストブート環境のインスタンスイニシャライザでDOMから読み込もうとしていますが、document.bodyが空であるようです。次のコードは、ブラウザで動作しますが、FASTBOOTに何も返さない:Ember FastBoot SimpleDOM本体が空です。

const ELEMENT_NODE_TYPE = 1; 

// TODO(maros): Get this working with FastBoot. For some reason the SimpleDOM 
// body is empty. 
const findBootstrapData = (document) => { 
    for (let currentNode = document.body.firstChild; currentNode; currentNode = currentNode.nextSibling) { 
    if (currentNode.nodeType !== ELEMENT_NODE_TYPE) { 
     continue; 
    } 

    if (currentNode.getAttribute('class') === 'bootstrap-data') { 
     return JSON.parse(currentNode.firstChild.nodeValue); 
    } 
    } 
}; 

export function initialize(appInstance) { 
    const store = appInstance.lookup('service:store'); 
    const document = appInstance.lookup('service:-document'); 

    const data = findBootstrapData(document); 
    if (data) { 
    store.push({ data: data.posts }); 
    } 
} 

export default { 
    name: 'blog-posts', 
    initialize 
}; 

私は読んしようとしているデータは、エンバーCLIのアドオンを使用して{{content-for "body"}}部分に注入されています。これはFastBootなしでも完璧に動作します。

このインスタンスイニシャライザは、どのようにしてFastBootで動作させることができますか?


編集:

余分な文脈のために、ここで私はエンバーCLIアドオンを使用してDOMを移入しています方法は次のとおりです。

/* eslint-env node */ 
'use strict'; 

const fs = require('fs'); 
const path = require('path'); 
const convertMarkdown = require('marked'); 
const parseFrontMatter = require('front-matter'); 

// Reads blog posts from `/posts`, compiles from markdown to HTML and stores 
// as JSON in a script tag in the document. An instance initializer then picks 
// it up and hydrates the store with it. 
module.exports = { 
    name: 'blog-posts', 

    contentFor: function(type) { 
    if (type !== 'body') { 
     return; 
    } 

    const dirname = path.join(__dirname, '..', '..', 'posts'); 
    const data = fs.readdirSync(dirname).map((filename, index) => { 
     if (!filename.endsWith('.md')) { 
     return; 
     } 

     const fileContent = fs.readFileSync(path.join(dirname, filename), 'utf-8'); 
     const frontMatter = parseFrontMatter(fileContent); 

     return { 
     id: index + 1, 
     type: 'post', 
     attributes: { 
      title: frontMatter.attributes.title, 
      body: convertMarkdown(frontMatter.body), 
     }, 
     }; 
    }); 

    return ` 
     <script class="bootstrap-data" type="text/template"> 
     ${JSON.stringify({ posts: data })} 
     </script> 
    `; 
    } 
}; 

答えて

0

document.bodyは常にアプリの起動ライフサイクル中に空になります。レンダリングはまだ行われていないため(インスタンスイニシャライザフェーズ中)、ファーストブートプレースホルダは置き換えられません。

次のいずれかを行うことができ:アプリのライフサイクル外でそれをしたい場合はhttp://ember-fastboot.com/docs/user-guide#the-shoebox

    1. あなたがプッシュしFASTBOOTブートストラップデータを取得するために靴箱のAPIを使用することができますそれでは、fastboot.visitリクエストが完了してからresult.html()の後にそれを行うことができます。

  • +0

    あなたはアプリのライフサイクルの外でこれを行う方法を詳しく説明できますか?私はaddonの 'contentFor'フックでブートストラップデータを取得しています(これを含めるように私の質問を編集しました)。私は 'contentFor'中にShoeboxにアクセスする方法がわかりません。 –

    +0

    ビルド後、ビルドされたindex.htmlにscriptタグが表示されますか? 'contentFor'はビルド時に実行されます。基本的には、そのデータを使用してストアを実装し、アプリで使用したいと思っていますか?もしそうなら、fastbootのDOMは最小限のデータ構造なので、fastbootで動作するとは思わない。したがって、 'document.body'は空であり、index.html本文の内容を表していません。 fastbootの 'metadata'プロパティを使用し、ブート時にアクセスしてストアに移入したいとします。このPRを見てください:https://github.com/ember-fastboot/fastboot/pull/75 –

    +0

    Ok、 'metadata'は役に立ちそうです。私は 'fastboot.visit'の使い方がはっきりしていません。 [docs](https://www.ember-fastboot.com/)のどこにも言及されておらず、私は現在明示的にそれを自分自身と呼んでいません。 –

    関連する問題