{"id":17974076,"url":"https://github.com/wayfair/bagel","last_synced_at":"2025-03-25T14:31:57.193Z","repository":{"id":35022665,"uuid":"180820458","full_name":"wayfair/bagel","owner":"wayfair","description":"🥯 Flexible rendering service for server-rendered React applications ⚛︎","archived":false,"fork":false,"pushed_at":"2025-03-07T21:58:42.000Z","size":612,"stargazers_count":12,"open_issues_count":17,"forks_count":6,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-20T12:07:16.417Z","etag":null,"topics":["hacktoberfest","hypernova","reactjs","server-side-rendering","ssr","websockets"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wayfair.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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":"2019-04-11T15:24:44.000Z","updated_at":"2024-06-23T19:06:13.000Z","dependencies_parsed_at":"2023-10-01T16:07:36.758Z","dependency_job_id":"44eec346-3bc9-4960-b917-1db2affdd848","html_url":"https://github.com/wayfair/bagel","commit_stats":{"total_commits":13,"total_committers":3,"mean_commits":4.333333333333333,"dds":"0.46153846153846156","last_synced_commit":"a117d84a1280e2d3b25f4bbe57ea2ab41c2e94f9"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wayfair%2Fbagel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wayfair%2Fbagel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wayfair%2Fbagel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wayfair%2Fbagel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wayfair","download_url":"https://codeload.github.com/wayfair/bagel/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245480486,"owners_count":20622325,"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":["hacktoberfest","hypernova","reactjs","server-side-rendering","ssr","websockets"],"created_at":"2024-10-29T17:06:14.934Z","updated_at":"2025-03-25T14:31:56.769Z","avatar_url":"https://github.com/wayfair.png","language":"JavaScript","readme":"```\n _                      _\n| |                    | |\n| |__   __ _  __ _  ___| |\n| '_ \\ / _` |/ _` |/ _ \\ |\n| |_) | (_| | (_| |  __/ |\n|_.__/ \\__,_|\\__, |\\___|_|\n              __/ |\n             |___/\n```\n\nBagel is a flexible rendering service for server-rendered React applications.\n\nBagel was built to solve a specific set of problems at [Wayfair](https://tech.wayfair.com/):\n\n- **React rendering as a service.** If you have an existing non-JavaScript backend and want to render React applications, Bagel can help.\n- **Configurable network transport layer.** Maybe you want to use HTTP to communicate with your service. Maybe you want to use WebSockets, maybe TCP, maybe Morse code over telegraph. Bagel makes it easy to use whatever you want.\n- **Extremely flexible [module loading](./packages/bagel-module-loader/README.md).** Code built to run in a browser may not run correctly in a server environment where all modules are singletons shared across requests. Frontend code may rely on module formats (haste-style flat namespaces, for example) that don't work out-of-the-box in a Node environment. You may need to have fine-grained control over which specific modules are singletons, shared across requests, and which are reloaded every time.\n\n## Getting Started\n\nBagel is designed to be run as an imported library.\n\n`yarn install bagel`\n\n```\nimport bagel from 'bagel'\n\nbagel({\n    moduleResolvers: [],\n    interceptors: [],\n    sourceCodeTransformers: [],\n    port: 3030\n});\n\n// bagel is now ready to serve requests\n\n```\n\nThe code above will only be able to load modules using the default Node.js module resolver, which means you will only be able to render React components that are in your project's `node_modules` directory. For more flexibility with how your root components are loaded, you'll need to supply a module resolver. See the `Resolver` type in the [module loader index file](./packages/bagel-module-loader/src/index.js) file or examples in [tests](./packages/bagel/src/__tests__/example.spec.js) for details on what a module resolver should look like.\n\nBagel should work with any [Hypernova client](https://github.com/airbnb/hypernova/blob/master/docs/clients.md). Please see [tests](./packages/bagel/src/__tests__/example.spec.js) for a good selection of examples.\n\n## Plugins\n\nDevelopers can create plugins to tap into Bagel's core operation. With plugins, you are able to hook into actions before and after they happen. Plugins have access to a context object which they are able to write to and use within various stages of the request.\n\nFlow types for plugins:\n\n```javascript\ntype LifeCycleMethod\u003cT\u003e = T =\u003e Promise\u003cvoid\u003e | void;\n\ntype Plugin = {\n  beforeBatch?: LifeCycleMethod\u003cBatchHandlerRequest\u003e,\n  afterBatch?: LifeCycleMethod\u003cBatchHandlerResponse\u003e,\n  beforeJob?: LifeCycleMethod\u003cJobHandlerRequest\u003e,\n  afterJob?: LifeCycleMethod\u003cJobHandlerResponse\u003e,\n  beforeLoadModule?: LifeCycleMethod\u003cJobHandlerRequest\u003e,\n  afterLoadModule?: LifeCycleMethod\u003cRenderHandlerRequest\u003e,\n  beforeRender?: LifeCycleMethod\u003cRenderHandlerRequest\u003e,\n  afterRender?: LifeCycleMethod\u003cJobHandlerResponse\u003e\n};\n```\n\n## Request and Response Types\n\nA Bagel request / response cycle is encompassed in a BatchRequest and a BatchResponse. These objects, and the associated JobRequest / JobResponse objects, are the primary means by which data flows through the Bagel application during a request.\n\nA batch is a single request / response cycle from a client application. A batch may contain one or more jobs. A job corresponds to a single root React component which needs to be rendered.\n\nMost of the hooks provided by Bagel (plugins, module loader interceptors, module resolvers) have access to job and batch requests and response objects.\n\n### Metadata\n\nApplications may pass request-related metadata into Bagel, where Bagel returns response-related metadata. Example uses of metadata inlude supplying a request ID to Bagel, and supplying performance profile data to a client application.\n\n### Batch Context\n\nEach batch has its own 'global' context object which is present during the entire life cycle of the batch. We know unstructured globals are a madness-inducing antipattern, but sometimes you need an escape hatch. If you need to share arbitrary data between different parts of the system during a request, the context object will permit this.\n\n### Flow Types\n\n```javascript\ntype BatchRequest = {\n  jobs: {[string]: JobRequest},\n  // context is a single object, 'global' to the batch, shared between the BatchRequest and BatchReponse object\n  context: {[string]: any}\n};\n\ntype BatchResponse = {\n  jobs: {[string]: JobResponse},\n  // context is a single object, 'global' to the batch, shared between the BatchRequest and BatchReponse object\n  context: {[string]: any}\n};\n\ntype JobRequest = {\n  name: string,\n  props: {},\n  metadata: {\n    jobId: string,\n    [string]: any\n  }\n};\n\ntype JobResponse = {\n  htmlStream: Readable,\n  metadata: {[string]: any}\n};\n```\n\n## Built With\n\n- [Babel](https://babeljs.io/)\n- [Flow](https://flow.org/)\n- [Jest](https://jestjs.io/)\n\n## Contributing\n\nPlease read [Code of Conduct.md](CODE_OF_CONDUCT.md) for details on our Code of Conduct.\n\nTo contribute, please open an issue or submit a pull request with appropriate test coverage.\n\n## Building\n\n`yarn build`\n\n## Running the tests\n\n```\nyarn test\nyarn test-watch\nyarn test-watch-debug\nyarn test-debug\n```\n\n## Running eslint\n\n`yarn lint`\n\n## Checking Flow Types\n\n`yarn flow`\n\n## Deploying\n\nIn a production environment, you'll want to have a process manager such as [PM2](http://pm2.keymetrics.io/) to keep the correct number of Bagel workers running.\n\n## Authors\n\n[Artem Ruts](https://github.com/artemruts)\n\n[Claudio Herrara](https://github.com/claudioherrera)\n\n[Morgan Packard](https://github.com/morganpackard)\n\n[Nick Dreckshage](https://github.com/ndreckshage)\n\n## License\n\nThis project is licensed under the BSD-2-Clause license. See the [License](./LICENSE) file for details.\n\n## History\n\nBagel began as a fork of Airbnb's [Hypernova](https://github.com/airbnb/hypernova) renderer (thanks Airbnb!). By default, it implments the same API as Hypernova, and can be used with any Hypernova client. Wayfair uses a version of our own publically available [PHP client](https://github.com/wayfair/hypernova-php) which has been modified to use WebSockets instead of HTTP.\n\nWe chose the name Bagel because:\n\n- Rather than going large, hard, powerful, and industrial with the name, we opted for modest, simple, and tasty.\n- Riffing on the name of Bagel's main inspiration, Hypernova, we thought about nova lox, which is a kind of smoked salmon, which tastes great on bagels.\n\n```\n\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwayfair%2Fbagel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwayfair%2Fbagel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwayfair%2Fbagel/lists"}