{"id":13659018,"url":"https://github.com/ember-fastboot/ember-cli-fastboot","last_synced_at":"2025-05-14T16:15:01.776Z","repository":{"id":25869613,"uuid":"29309660","full_name":"ember-fastboot/ember-cli-fastboot","owner":"ember-fastboot","description":"Server-side rendering for Ember.js apps","archived":false,"fork":false,"pushed_at":"2024-05-22T14:02:19.000Z","size":11708,"stargazers_count":852,"open_issues_count":143,"forks_count":158,"subscribers_count":45,"default_branch":"master","last_synced_at":"2025-04-02T01:01:38.785Z","etag":null,"topics":["fastboot","hacktoberfest"],"latest_commit_sha":null,"homepage":"http://ember-fastboot.com/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ember-fastboot.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-01-15T17:44:10.000Z","updated_at":"2025-02-19T14:24:37.000Z","dependencies_parsed_at":"2022-07-12T15:50:36.524Z","dependency_job_id":"08922ea1-68cd-4f29-aa2a-9805c85c41dc","html_url":"https://github.com/ember-fastboot/ember-cli-fastboot","commit_stats":{"total_commits":1229,"total_committers":136,"mean_commits":9.036764705882353,"dds":0.8429617575264443,"last_synced_commit":"8af9ba7928200eb3a978d7246285fb79f9b5586a"},"previous_names":[],"tags_count":91,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ember-fastboot%2Fember-cli-fastboot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ember-fastboot%2Fember-cli-fastboot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ember-fastboot%2Fember-cli-fastboot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ember-fastboot%2Fember-cli-fastboot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ember-fastboot","download_url":"https://codeload.github.com/ember-fastboot/ember-cli-fastboot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247366400,"owners_count":20927501,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastboot","hacktoberfest"],"created_at":"2024-08-02T05:01:04.594Z","updated_at":"2025-04-11T11:37:56.776Z","avatar_url":"https://github.com/ember-fastboot.png","language":"JavaScript","readme":"# Ember FastBoot\n\n[![npm version](https://badge.fury.io/js/ember-cli-fastboot.svg)](https://badge.fury.io/js/ember-cli-fastboot)\n[![Actions Status](https://github.com/ember-fastboot/ember-cli-fastboot/workflows/CI/badge.svg)](https://github.com/ember-fastboot/ember-cli-fastboot/actions)\n\nFastBoot allows you to render and serve Ember.js apps on the server.\nUsing FastBoot, you can serve rendered HTML to browsers and\nother clients without requiring them to download JavaScript assets.\n\nWhile FastBoot is has decent support in the Ember ecosystem these days, some\napplication code, add-ons or other dependencies may need to be modified to work\nwhen being rendered serverside (e.g. you cannot call the `window` object during\nFastBoot).\n\n## Installation\n\nFastBoot requires Ember 2.3 or higher. It is also preferable that your app is running `ember-cli` 2.12.0 and higher.\n\nFrom within your Ember CLI application, run the following command:\n\n```sh\nember install ember-cli-fastboot\n```\n\n## Running\n\nIf your app is running `ember-cli` 2.12.0-beta.1+ you can run as follows:\n\n* `ember serve`\n* Visit your app at `http://localhost:4200`\n\nYou may be shocked to learn that minified code runs faster in Node than\nnon-minified code, so you will probably want to run the production\nenvironment build for anything \"serious.\"\n\n```sh\nember serve --environment production\n```\n\nYou can also specify the port (default is 4200):\n\n```sh\nember serve --port 8088\n```\n\nSee `ember help` for more.\n\n### Disabling FastBoot with `ember serve`\n\nOptionally you can even disable the fastboot serving at runtime using the `fastboot` query parameter. Example to turn off fastboot serving,\nvisit your app at `http://localhost:4200/?fastboot=false`. If you want to turn on fastboot serving again, simply visit at `http://localhost:4200/?fastboot=true` or `http://localhost:4200/`.\n\nYou can even disable serving fastboot with `ember serve` using an environment flag: `FASTBOOT_DISABLED=true ember serve`. If you have disabled building fastboot assets using the same flag as described [here](https://github.com/ember-fastboot/ember-cli-fastboot#double-build-times-and-no-incremental-builds), remember to also disable serving fastboot assets when using `ember serve`.\n\n### FastBoot Configuration\n\nWhen running locally using `ember serve` you can pass options into FastBoot instance via `config/fastboot.js` file. The configuration file is applicable only for applications, addons are not supported.\n\n```js\nmodule.exports = function(environment) {\n  let myGlobal = environment === 'production' ? process.env.MY_GLOBAL : 'testing';\n\n  return {\n    buildSandboxGlobals(defaultGlobals) {\n      return Object.assign({}, defaultGlobals, {\n        myGlobal,\n      });\n    }\n  };\n}\n```\n\nThere are several options available, see FastBoot's [README](./packages/fastboot/#usage) for more information, but be aware that `distPath` is provided internally by `ember-cli-fastboot`, hence it can not be modified by this file.\n\n### FastBoot App Server Configuration\n\nWhen using [FastBoot App Server](./packages/fastboot-app-server/README.md) for production environment you have to manually pass options from `config/fastboot.js` file.\n\n```js\nconst FastBootAppServer = require('fastboot-app-server');\nconst config = require('./config/fastboot')(process.env.NODE_ENV);\n\nlet server = new FastBootAppServer({\n  distPath: 'dist',\n  ...config,\n});\n\nserver.start();\n```\n\n## Using Node/npm Dependencies\n\n### Whitelisting Packages\n\nWhen your app is running in FastBoot, it may need to use Node packages\nto replace features that are available only in the browser.\n\nFor security reasons, your Ember app running in FastBoot can only access\npackages that you have explicitly whitelisted.\n\nTo allow your app to require a package, add it to the\n`fastbootDependencies` array in your app's `package.json`:\n\n```js\n{\n  \"name\": \"my-sweet-app\",\n  \"version\": \"0.4.2\",\n  \"devDependencies\": {\n    // ...\n  },\n  \"dependencies\": {\n    // ...\n  },\n  \"fastbootDependencies\": [\n    \"rsvp\",\n    \"path\"\n  ]\n}\n```\n\nThe `fastbootDependencies` in the above example means the only node\nmodules your Ember app can use are `rsvp` and `path`.\n\nIf the package you are using is not built-in to Node, **you must also\nspecify the package and a version in the `package.json` `dependencies`\nhash.** Built-in modules (`path`, `fs`, etc.) only need to be added to\n`fastbootDependencies`.\n\n### Using Dependencies\n\nFrom your Ember.js app, you can run `FastBoot.require()` to require a\npackage. This is identical to the CommonJS `require` except it checks\nall requests against the whitelist first.\n\n```js\nlet path = FastBoot.require('path');\nlet filePath = path.join('tmp', session.getID());\n```\n\nIf you attempt to require a package that is not in the whitelist,\nFastBoot will raise an exception.\n\nNote that the `FastBoot` global is **only** available when running in\nFastBoot mode. You should either guard against its presence or only use\nit in FastBoot-only initializers.\n\n## FastBoot Service\n\nFastBoot registers the `fastboot` service. This service allows you to\ncheck if you are running within FastBoot by checking\n`fastboot.isFastBoot`. There is also a request object under\n`fastboot.request` which exposes details about the current request being\nhandled by FastBoot\n\n### Delaying the server response\n\nBy default, FastBoot waits for the `beforeModel`, `model`, and\n`afterModel` hooks to resolve before sending the response back to the\nclient. If you have asynchrony that runs outside of those contexts, your\nresponse may not reflect the state that you want.\n\nTo solve this, the `fastboot` service has `deferRendering` method that accepts\na promise. It will chain all promises passed to it, and the FastBoot server will\nwait until all of these promises resolve before sending the response to\nthe client. These promises must be chained before the rendering is\ncomplete after the model hooks. For example, if a component that is\nrendered into the page makes an async call for data, registering a\npromise to be resolved in its `init` hook would allow the component to\ndefer the rendering of the page.\n\nThe following example demonstrates how the `deferRendering` method can be\nused to ensure posts data has been loaded asynchronously by a component before\nrendering the entire page. Note how the call should be wrapped in a `fastboot.isFastBoot`\ncheck since the method will throw an exception outside of that context:\n\n```js\nimport Component from '@glimmer/component';\n\nexport default class MyComponent extends Component {\n  @service fastboot;\n  @service model;\n\n  constructor(owner, args) {\n    super(owner, args);\n\n    let promise = this.store.findAll('post').then((posts) =\u003e {\n      this.posts = posts;\n    });\n\n    if (this.fastboot.isFastBoot) {\n      this.fastboot.deferRendering(promise);\n    }\n  }\n}\n```\n\n### Cookies\n\nYou can access cookies for the current request via `fastboot.request`\nin the `fastboot` service.\n\n```js\nimport Route from '@ember/routing/route';\n\nexport default class MyRoute extends Route {\n  @service fastboot;\n\n  model() {\n    let authToken = this.fastboot.request.cookies.auth;\n    // ...\n  }\n}\n```\n\nThe service's `cookies` property is an object containing the request's\ncookies as key/value pairs.\n\n### Headers\n\nYou can access the headers for the current request via `fastboot.request`\nin the `fastboot` service. The `headers` object implements part of the\n[Fetch API's Headers\nclass](https://developer.mozilla.org/en-US/docs/Web/API/Headers), the\nfunctions available are\n[`has`](https://developer.mozilla.org/en-US/docs/Web/API/Headers/has),\n[`get`](https://developer.mozilla.org/en-US/docs/Web/API/Headers/get), and\n[`getAll`](https://developer.mozilla.org/en-US/docs/Web/API/Headers/getAll).\n\n```js\nimport Route from '@ember/routing/route';\n\nexport default class MyRoute extends Route {\n  @service fastboot;\n\n  model() {\n    let headers = this.fastboot.request.headers;\n    let xRequestHeader = headers.get('X-Request');\n    // ...\n  }\n}\n```\n\n### Host\n\nYou can access the host of the request that the current FastBoot server\nis responding to via `fastboot.request` in the `fastboot` service. The\n`host` property will return the host (`example.com` or `localhost:3000`).\n\n```js\nimport Route from '@ember/routing/route';\n\nexport default class MyRoute extends Route {\n  @service fastboot;\n\n  model() {\n    let host = this.fastboot.request.host;\n    // ...\n  }\n}\n```\n\nTo retrieve the host of the current request, you must specify a list of\nhosts that you expect in your `config/environment.js`:\n\n```js\nmodule.exports = function(environment) {\n  var ENV = {\n    modulePrefix: 'host',\n    environment: environment,\n    baseURL: '/',\n    locationType: 'auto',\n    EmberENV: {\n      // ...\n    },\n    APP: {\n      // ...\n    },\n\n    fastboot: {\n      hostWhitelist: ['example.com', 'subdomain.example.com', /^localhost:\\d+$/]\n    }\n  };\n  // ...\n};\n```\n\nThe `hostWhitelist` can be a string or RegExp to match multiple hosts.\nCare should be taken when using a RegExp, as the host function relies on\nthe `Host` HTTP header, which can be forged. You could potentially allow\na malicious request if your RegExp is too permissive when using the `host`\nwhen making subsequent requests.\n\nRetrieving `host` will error on 2 conditions:\n\n 1. you do not have a `hostWhitelist` defined\n 2. the `Host` header does not match an entry in your `hostWhitelist`\n\n### Query Parameters\n\nYou can access query parameters for the current request via `fastboot.request`\nin the `fastboot` service.\n\n```js\nimport Route from '@ember/routing/route';\n\nexport default class MyRoute extends Route {\n  @service fastboot;\n\n  model() {\n    let authToken = this.fastboot.request.queryParams.auth;\n    // ...\n  }\n}\n```\n\nThe service's `queryParams` property is an object containing the request's\nquery parameters as key/value pairs.\n\n### Path\n\nYou can access the path (`/` or `/some-path`) of the request that the\ncurrent FastBoot server is responding to via `fastboot.request` in the\n`fastboot` service.\n\n```js\nimport Route from '@ember/routing/route';\n\nexport default class MyRoute extends Route {\n  @service fastboot;\n\n  model() {\n    let path = this.fastboot.request.path;\n    // ...\n  }\n}\n```\n\n### Protocol\n\nYou can access the protocol (`http:` or `https:`) of the request that the\ncurrent FastBoot server is responding to via `fastboot.request` in the\n`fastboot` service.\n\n```js\nimport Route from '@ember/routing/route';\n\nexport default class MyRoute extends Route {\n  @service fastboot;\n\n  model() {\n    let protocol = this.fastboot.request.protocol;\n    // ...\n  }\n}\n```\n\n### The Shoebox\n\nYou can pass application state from the FastBoot rendered application\nto the browser rendered application using a feature called the \"Shoebox\".\nThis allows you to leverage server API calls made by the FastBoot\nrendered application on the browser rendered application. Thus preventing\nyou from duplicating work that the FastBoot application is performing.\nThis should result in a performance benefit for your browser application,\nas it does not need to issue server API calls whose results are available\nfrom the Shoebox.\n\nThe contents of the Shoebox are written to the HTML as strings within\n`\u003cscript\u003e` tags by the server rendered application, which are then\nconsumed by the browser rendered application.\n\nThis looks like:\n\n```html\n\u003cscript type=\"fastboot/shoebox\" id=\"shoebox-main-store\"\u003e\n{\"data\":[{\"attributes\":{\"name\":\"AEC Professionals\"},\"id\":106,\"type\":\"audience\"},\n{\"attributes\":{\"name\":\"Components\"},\"id\":111,\"type\":\"audience\"},\n{\"attributes\":{\"name\":\"Emerging Professionals\"},\"id\":116,\"type\":\"audience\"},\n{\"attributes\":{\"name\":\"Independent Voters\"},\"id\":2801,\"type\":\"audience\"},\n{\"attributes\":{\"name\":\"Staff\"},\"id\":141,\"type\":\"audience\"},\n{\"attributes\":{\"name\":\"Students\"},\"id\":146,\"type\":\"audience\"}]}\n\u003c/script\u003e\n```\n\nYou can add items into the shoebox with `shoebox.put`, and you can retrieve\nitems from the shoebox using `shoebox.retrieve`. In the example below we use\nan object, `shoeboxStore`, that acts as our store of objects that reside in\nthe shoebox. We can then add/remove items from the `shoeboxStore` in the\nFastBoot rendered application as we see fit. Then in the browser rendered\napplication, it will grab the `shoeboxStore` from the shoebox and retrieve\nthe record necessary for rendering this route.\n\n```js\nimport Route from '@ember/routing/route';\n\nexport default class MyRoute extends Route {\n  @service fastboot;\n\n  model(params) {\n    let shoebox = this.fastboot.shoebox;\n    let shoeboxStore = shoebox.retrieve('my-store');\n\n    if (this.fastboot.isFastBoot) {\n      return this.store.findRecord('post', params.post_id).then(post =\u003e {\n        if (!shoeboxStore) {\n          shoeboxStore = {};\n          shoebox.put('my-store', shoeboxStore);\n        }\n        shoeboxStore[post.id] = post.toJSON();\n      });\n    } else {\n      return shoeboxStore \u0026\u0026 shoeboxStore[params.post_id];\n    }\n  }\n}\n```\n\n### Think out of the Shoebox\n\nShoebox gives you great capabilities, but using it in the real app is pretty rough. Have you ever thought that such kind of logic should be done behind the scenes? In a large codebase, defining `fastboot.isFastBoot` conditionals can be a daunting task. Furthermore, it generates a lot of boilerplate code, which obscures the solution. Sooner or later coupling with `shoebox` will spread over all routes.\n\n#### Solution: Application Adapter\n\nOne way to abstract the shoebox data storage mechanics is to move the logic into\nthe Application Adapter as shown below.\n\n```js\nexport default class ApplicationAdapter extends JSONAPIAdapter.extend(\n  // ...snip...\n\n  cacheKeyFor([, model, id]) {\n    return (model.modelName \u0026\u0026 id) ? `${model.modelName}-${id}` : 'default-store';\n  }\n\n  async findRecord() {\n    const key = this.cacheKeyFor(arguments);\n\n    if (this.fastboot.isFastBoot) {\n      let result = await super.findRecord(...arguments);\n\n      // must deep-copy for clean serialization.\n      result = JSON.parse(JSON.stringify(result));\n\n      this.fastboot.shoebox.put(key, result);\n\n      return result;\n    }\n\n    let result = this.fastboot.shoebox.retrieve(key);\n\n    if (!result) {\n      result = await super.findRecord(...arguments);\n    }\n\n    // must deep-copy for clean serialization.\n    return JSON.parse(JSON.stringify(result));\n  }\n}\n```\n\nWith this strategy, any time an ember-data `findRecord` request happens while in\nFastboot mode, the record will be put into the shoebox cache and returned. When\nsubsequent calls are made for that record in the hydrated application, it will\nfirst check the shoebox data.\n\n#### Solution: Use an Addon (ember-storefront)\n\nAdditionally, there is an addon called [ember-data-storefront](https://embermap.github.io/ember-data-storefront/) that can help to alleviate this pain, thanks to its Fastboot mixin: https://embermap.github.io/ember-data-storefront/docs/guides/fastboot.\n\nAfter installing the addon and applying the mixin, your routes can look like this:\n\n`app/routes/my-route.js`:\n\n```javascript\nimport Route from '@ember/routing/route';\n\nexport default class MyRoute extends Route {\n  @service fastboot;\n\n  model() {\n    // first call in a server makes actual ajax request.\n    // second call in a browser serves cached response\n    return this.store.findAll('posts')\n  }\n}\n```\nAnd they still take advantage of caching in the `shoebox`. No more redundant AJAX for already acquired data. Installation details are available in the addon [documentation](https://embermap.github.io/ember-data-storefront/docs).\n\n### Rehydration\n\nWhat is Rehydration?\n\nThe rehydration feature means that the Glimmer VM can take a DOM tree\ncreated using Server Side Rendering (SSR) and use it as the starting\npoint for the append pass.\n\nSee details here:\n\nhttps://github.com/glimmerjs/glimmer-vm/commit/316805b9175e01698120b9566ec51c88d075026a\n\nIn order to utilize rehydration in Ember.js applications we need to ensure that\nboth server side renderers (like fastboot) properly encode the DOM they send to\nthe browser with the serialization format (introduced in the commit above) AND\nthat the browser instantiated Ember.js application knows to use the rehydration\nbuilder to consume that DOM.\n\nRehydration is 100% opt-in, if you do not specify the environment flag your\napplication will behave as it did before!\n\nWe can opt-in to the rehydration filter by setting the following environment\nflag:\n\n```\nEXPERIMENTAL_RENDER_MODE_SERIALIZE=true\n```\n\nThis flag is read by Ember CLI Fastboot's dependency; fastboot to alert it to\nproduce DOM with the glimmer-vm's serialization element builder.  This addon\n(Ember CLI Fastboot) then uses a utility function from glimmer-vm that allows\nit to know whether or not the DOM it received in the browser side was generated\nby the serialization builder.  If it was, it tells the Ember.js Application to\nuse the rehydration builder and your application will be using rehydration.\n\nRehydration is only compatible with fastboot \u003e 1.1.4-beta.1, and Ember.js \u003e 3.2.\n\n## Build Hooks for FastBoot\n\n### Disabling incompatible dependencies\n\nThere are two places where the inclusion of incompatible JavaScript libraries could\noccur:\n\n#### `app.import` in the application's `ember-cli-build.js`\n\nIf your Ember application is importing an incompatible Javascript library,you can use `app.import` with the `using` API.\n\n```js\napp.import('vendor/fastboot-incompatible.js', {\n  using: [\n    {\n      transformation: 'fastbootShim'\n    }\n  ]\n});\n```\n#### `app.import` in an addon's `included` hook\n\nYou can include the incompatible Javascript libraries by wrapping them with a `FastBoot` variable check. In the browser, `FastBoot` global variable is not defined.\n\n```js\nvar map = require('broccoli-stew').map;\n\ntreeForVendor(defaultTree) {\n  var browserVendorLib = new Funnel(...);\n\n  browserVendorLib = map(browserVendorLib, (content) =\u003e `if (typeof FastBoot === 'undefined') { ${content} }`);\n\n  return new mergeTrees([defaultTree, browserVendorLib]);\n}\n\nincluded() {\n  // this file will be loaded in FastBoot but will not be eval'd\n  app.import('vendor/\u003cbrowserLibName\u003e.js');\n}\n```\n\n*Note*: `ember-cli-fastboot` will no longer provide the `EMBER_CLI_FASTBOOT` environment variable to differentiate browser and fastboot builds with rc builds and FastBoot 1.0 and above.\n\n### Loading additional assets in FastBoot environment\n\nOften addons require to load libraries that are specific to the FastBoot environment and only need to be loaded on the server side. This can include loading\nlibraries before or after the vendor file is loaded in the sandbox and/or before or after the app file is loaded in the sandbox. Since the FastBoot manifest defines\nan array of vendor and app files to load in the sandbox, an addon can define additional vendor/app files to load in the sandbox as well.\n\nIf your addon requires to load something in the sandbox: you can define the `updateFastBootManifest` hook from your addon (in `index.js`):\n\n```js\nupdateFastBootManifest(manifest) {\n  /**\n   * manifest is an object containing:\n   * {\n   *    vendorFiles: [\u003cpath of the vendor file to load\u003e, ...],\n   *    appFiles: [\u003cpath of the app file to load\u003e, ...],\n   *    htmlFile: '\u003cpath of the base page that should be served by FastBoot\u003e'\n   * }\n   */\n\n   // This will load the foo.js before vendor.js is loaded in sandbox\n   manifest.vendorFiles.unshift('\u003cpath to foo.js under dist\u003e');\n   // This will load bar.js after app.js is loaded in the sandbox\n   manifest.appFiles.push('\u003cpath to bar.js under dist\u003e');\n\n   // remember to return the updated manifest, otherwise your build will fail.\n   return manifest;\n}\n```\n\n*Note*: `process.env.EMBER_CLI_FASTBOOT` will be removed in RC builds and FastBoot 1.0.\nTherefore, if you are relying on this environment variable to import something in the fastboot environment, you should instead use `updateFastBootManifest` hook.\n\n### Conditionally include assets in FastBoot asset\n\nOften your addon may need to conditionally include additional app trees based on ember version. Example, Ember changed an API and in order to have your addon be backward compatible for the API changes you want to include an asset when the ember version is x. For such usecases you could define the `treeForFastBoot` hook in your addon's `index.js` as below:\n\n```js\ntreeForFastBoot: function(tree) {\n  let fastbootHtmlBarsTree;\n\n  // check the ember version and conditionally patch the DOM api\n  if (this._getEmberVersion().lt('2.10.0-alpha.1')) {\n    fastbootHtmlBarsTree = this.treeGenerator(path.resolve(__dirname, 'fastboot-app-lt-2-9'));\n    return tree ? new MergeTrees([tree, fastbootHtmlBarsTree]) : fastbootHtmlBarsTree;\n  }\n\n  return tree;\n},\n```\n\nThe `tree` is the additional fastboot asset that gets generated and contains the fastboot overrides.\n\n### Providing additional config\n\nBy default `ember-cli-fastboot` reads the app's config and provides it in the FastBoot sandbox as a JSON object. For the app in browser, it respects `storeConfigInMeta` and either reads it from the config meta tag or inlines it as JSON object in the `app-name/config/environment` AMD module.\n\nAddons like ember-engines may split the app in different bundles that are loaded asynchronously. Since each bundle is loaded asynchronously, it can have its own configuration as well. In order to allow FastBoot to provide this config in the sandbox, it exposes a `fastbootConfigTree` build hook.\n\nAddons wishing to use this hook simply need to return a unique identifier for the configuration with the configuration.\n\n```js\nfastbootConfigTree() {\n  return {\n    '\u003cengine-name\u003e': {\n      'foo': 'bar'\n    }\n  }\n}\n```\n\nThe above configuration will be available in Node via the `FastBoot.config()` function. Therefore, in order to get the above config, the addon/app can call `FastBoot.config('\u003cengine-name\u003e')`.\n\n## Known Limitations\n\nThere are a few key restrictions developers should be aware of with FastBoot.\n\n### No `didInsertElement`\n\nSince `didInsertElement` hooks are designed to let your component\ndirectly manipulate the DOM, and that doesn't make sense on the server\nwhere there is no DOM, we do not invoke either `didInsertElement` or\n`willInsertElement` hooks. The only component lifecycle hooks called in\nFastBoot are `init`, `didReceiveAttrs`, `didUpdateAttrs`, and `willDestroy`.\n\n### No jQuery\n\nRunning most of jQuery requires a full DOM. Most of jQuery will just not be\nsupported when running in FastBoot mode. One exception is network code for\nfetching models, which we intended to support, but doesn't work at\npresent.\n\n### Prototype extensions\n\nPrototype extensions do not currently work across node \"realms.\"  Fastboot\napplications operate in two realms, a normal node environment and a [virtual machine](https://nodejs.org/api/vm.html).  Passing objects that originated from the normal realm will not contain the extension methods\ninside of the sandbox environment. For this reason, it's encouraged to [disable prototype extensions](https://guides.emberjs.com/v2.4.0/configuring-ember/disabling-prototype-extensions/).\n\n## Troubleshooting\n\nBecause your app is now running in Node.js, not the browser, you'll\nneed a new set of tools to diagnose problems when things go wrong. Here\nare some tips and tricks we use for debugging our own apps.\n\n### Verbose Logging\n\nEnable verbose logging by running the FastBoot server with the following\nenvironment variables set:\n\n```sh\nDEBUG=ember-cli-fastboot:* ember serve\n```\n\nPRs adding or improving logging facilities are very welcome.\n\n### Developer Tools\n\nThanks to recent improvements in NodeJS it is now possible to get a\ndebugging environment that you can connect to with Chrome DevTools (version 55+).\nYou can find more information on the new debugging method on Node's\n[official documentation](https://nodejs.org/en/docs/inspector/) but here is a quick-start guide:\n\nFirst let's start up the FastBoot server with Node in debug mode. One thing\nabout debug mode: it makes everything much slower.\n\n```sh\nnode --inspect-brk ./node_modules/.bin/ember serve\n```\n\nThis starts the FastBoot server in debug mode. Note that the `--inspect-brk` flag will cause your\napp to start paused to give you a chance to open the debugger.\n\nOnce you see the output `Debugger listening on ws://127.0.0.1:\u003cport\u003e/\u003cguid\u003e`, open Chrome\nand visit [chrome://inspect](chrome://inspect). Once it loads you should see an Ember target\nwith a link \"inspect\" underneath. Click inspect and it should pop up a Chrome inspector\nwindow and you can click the ▶︎ icon to let FastBoot continue loading.\n\nAssuming your app loads without an exception, after a few seconds you\nwill see a message that FastBoot is listening on port 3000. Once you see\nthat, you can open a connection; any exceptions should be logged in the\nconsole, and you can use the tools you'd expect such as `console.log`,\n`debugger` statements, etc.\n\n#### Note Regarding Node Versions\n\nThe above method only started working for the v8.x track of Node after version v8.4.0,\nwhich has a fix to [this issue](https://github.com/nodejs/node/issues/7593). If you\nare using any versions between v8.0 and v8.4 we would recommend upgrading to at least v8.4.0\n\nFor any versions prior to 6.4 the previous version of this documentation is still valid.\nPlease follow those instructions [here](https://github.com/ember-fastboot/ember-cli-fastboot/tree/v1.0.4#developer-tools)\n\n#### Debugging via VS Code\n\nMake sure you have `.vscode/launch.json` with minimal configuration that looks like below:\n```json\n{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"type\": \"pwa-node\",\n            \"request\": \"launch\",\n            \"name\": \"Debug Ember App\",\n            \"skipFiles\": [\n                \"\u003cnode_internals\u003e/**\"\n            ],\n            \"program\": \"./node_modules/ember-cli/bin/ember\",\n            \"args\": \"s\"\n        }\n    ]\n}\n```\n\n## Tests\n\nRun the automated tests by running `npm test`.\n\n### Debugging Integration Tests\n\nRun the tests with the `DEBUG` environment variable set to\n`fastboot-test` to see verbose debugging output.\n\n```sh\nDEBUG=fastboot-test npm test\n```\n\n### Questions\n\nReach out to us via [Ember Community Discord](https://discordapp.com/invite/zT3asNS) in the `#fastboot` channel.\n","funding_links":[],"categories":["JavaScript","Packages"],"sub_categories":["SSR / Server Side Rendering"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fember-fastboot%2Fember-cli-fastboot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fember-fastboot%2Fember-cli-fastboot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fember-fastboot%2Fember-cli-fastboot/lists"}