{"id":19593031,"url":"https://github.com/thoughtbot/humid","last_synced_at":"2025-04-06T07:15:04.435Z","repository":{"id":56877025,"uuid":"384579075","full_name":"thoughtbot/humid","owner":"thoughtbot","description":"Javascript Server Side Rendering for Rails","archived":false,"fork":false,"pushed_at":"2025-02-20T02:21:14.000Z","size":319,"stargazers_count":45,"open_issues_count":1,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-30T06:09:01.169Z","etag":null,"topics":["rails","react","ssr"],"latest_commit_sha":null,"homepage":"","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/thoughtbot.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":"CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"thoughtbot"}},"created_at":"2021-07-10T00:32:22.000Z","updated_at":"2025-03-27T07:16:42.000Z","dependencies_parsed_at":"2024-03-14T23:28:33.711Z","dependency_job_id":"c9b102fc-0301-4bda-8389-68b90886f371","html_url":"https://github.com/thoughtbot/humid","commit_stats":{"total_commits":28,"total_committers":4,"mean_commits":7.0,"dds":0.2857142857142857,"last_synced_commit":"2eae4b6c3da22348e371ff925cfbcdcb429f3d64"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtbot%2Fhumid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtbot%2Fhumid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtbot%2Fhumid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtbot%2Fhumid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thoughtbot","download_url":"https://codeload.github.com/thoughtbot/humid/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247445681,"owners_count":20939961,"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":["rails","react","ssr"],"created_at":"2024-11-11T08:37:53.323Z","updated_at":"2025-04-06T07:15:04.413Z","avatar_url":"https://github.com/thoughtbot.png","language":"JavaScript","funding_links":["https://github.com/sponsors/thoughtbot"],"categories":["JavaScript"],"sub_categories":[],"readme":"# Humid\n\n![Build Status](https://github.com/thoughtbot/humid/actions/workflows/build.yml/badge.svg?branch=main)\n\nHumid is a lightweight wrapper around [mini_racer] used to generate Server\nSide Rendered (SSR) pages from your js-bundling builds. While it was built\nfor React, it can work with any JS function that returns a HTML string.\n\n## Caution\n\nThis project is in its early phases of development. Its interface,\nbehavior, and name are likely to change drastically before a major version\nrelease.\n\n## Installation\n\nAdd Humid to your Gemfile.\n\n```\ngem 'humid'\n```\n\nFor source-map support, also add\n\n```\nyarn add source-map-support\n```\n\n\n## Configuration\n\nAdd an initializer to configure\n\n```ruby\nHumid.configure do |config|\n  # Path to your build file located in `app/assets/build/`. You should use a\n  # separate build apart from your `application.js`.\n  #\n  # Required\n  config.application_path = Rails.root.join('app', 'assets', 'build', 'server_rendering.js')\n\n  # Path to your source map file\n  #\n  # Optional\n  config.source_map_path = Rails.root.join('app', 'assets', 'build', 'server_rendering.js.map')\n\n  # Raise errors if JS rendering failed. If false, the error will be\n  # logged out to Rails log and Humid.render will return an empty string\n  #\n  # Defaults to true.\n  config.raise_render_errors = Rails.env.development? || Rails.env.test?\n\n  # The logger instance.\n  # `console.log` and friends (`warn`, `error`) are delegated to\n  # the respective logger levels on the ruby side.\n  #\n  # Defaults to `Logger.new(STDOUT)`\n  config.logger = Rails.logger\n\n  # Options passed to mini_racer.\n  #\n  # Defaults to empty `{}`.\n  config.context_options = {\n    timeout: 1000,\n    ensure_gc_after_idle: 2000\n  }\nend\n\n# Capybara defines its own puma config which is set up to run a single puma process\n# with a thread pool. This ensures that a context gets created on that process.\nif Rails.env.test?\n  # Use single_threaded mode for Spring and other forked envs.\n  MiniRacer::Platform.set_flags! :single_threaded\n  Humid.create_context\nend\n```\n\nThen add to your `config/puma.rb`\n\n```\nworkers ENV.fetch(\"WEB_CONCURRENCY\") { 1 }\n\non_worker_boot do\n  Humid.create_context\nend\n\non_worker_shutdown do\n  Humid.dispose\nend\n```\n\nIf you'd like support for source map support, you will need to\n1. Add the following to your entry file, e.g, `server_rendering.js`.\n2. set `config.source_map_path`.\n\n```javascript\nrequire(\"source-map-support\").install({\n  retrieveSourceMap: filename =\u003e {\n    return {\n      url: filename,\n      map: readSourceMap(filename)\n    };\n  }\n});\n```\nA [sample] webpack.config is available for reference.\n\n## The mini_racer environment.\n\n### Functions not available\n\nThe following functions are **not** available in the mini_racer environment\n\n- `setTimeout`\n- `clearTimeout`\n- `setInterval`\n- `clearInterval`\n- `setImmediate`\n- `clearImmediate`\n\n### `console.log`\n\n`console.log` and friends (`info`, `error`, `warn`) are delegated to the\nrespective methods on the configured logger.\n\n## Usage\n\nIn your entry file, e.g, `server_rendering.js`, pass your HTML render function\nto `setHumidRenderer`. There is no need to require the function.\n\n```javascript\n// Set a factory function that will create a new instance of our app\n// for each request.\nsetHumidRenderer((json) =\u003e {\n  const initialState = JSON.parse(json)\n\n  return ReactDOMServer.renderToString(\n    \u003cApplication initialPage={initialState}/\u003e\n  )\n})\n```\n\nAnd finally call `render` from ERB.\n\n```ruby\n\u003c%= Humid.render(initial_state).html_safe %\u003e\n```\n\nInstrumentation is included:\n\n```\nCompleted 200 OK in 14ms (Views: 0.2ms | Humid SSR: 11.0ms | ActiveRecord: 2.7ms)\n```\n\n### Puma\n\n`mini_racer` is thread safe, but not fork safe. To use with web servers that\nemploy forking, use `Humid.create_context` only on forked processes. On\nproduction, There should be no context created on the master process.\n\n```ruby\n# Puma\non_worker_boot do\n  Humid.create_context\nend\n\non_worker_shutdown do\n  Humid.dispose\nend\n```\n\n### Server-side libraries that detect node.js envs.\nYou may need webpacker to create aliases for server friendly libraries that can\nnot detect the `mini_racer` environment. For example, in `webpack.config.js`.\n\n```diff\n...\n  resolve: {\n    alias: {\n      'html-dom-parser': path.resolve(__dirname, '../../node_modules/html-dom-parser/lib/html-to-dom-server')\n    }\n  }\n...\n```\n\n## Writing universal code\n[Vue has a resource][vue_ssr] on how to write universal code. Below\nare a few highlights that are important to keep in mind.\n\n### State\n\nHumid uses a single context across multiple request. To avoid state pollution, we\nprovide a factory function to `setHumidRenderer` that builds a new app instance on\nevery call.\n\nThis provides better isolation, but as it is still a shared context, polluting\n`global` is still possible. Be careful of modifying `global` in your code.\n\n### Missing browser APIs\n\nPolyfills and some libraries that depend on browser APIs will fail in the\n`mini_racer` environment because of missing browser APIs. Account for this by\nmoving the `require` to `useEffect` in your component.\n\n```\n  useEffect(() =\u003e {\n    const svgPanZoom = require('svg-pan-zoom')\n    //...\n  }, [])\n```\n\n## Contributing\n\nPlease see [CONTRIBUTING.md](/CONTRIBUTING.md).\n\n## License\n\nHumid is Copyright © 2021-2024 Johny Ho.\nIt is free software, and may be redistributed under the terms specified in the\n[LICENSE](/LICENSE.md) file.\n\n\u003c!-- START /templates/footer.md --\u003e\n## About thoughtbot\n\n![thoughtbot](https://thoughtbot.com/thoughtbot-logo-for-readmes.svg)\n\nThis repo is maintained and funded by thoughtbot, inc.\nThe names and logos for thoughtbot are trademarks of thoughtbot, inc.\n\nWe love open source software!\nSee [our other projects][community].\nWe are [available for hire][hire].\n\n[community]: https://thoughtbot.com/community?utm_source=github\n[hire]: https://thoughtbot.com/hire-us?utm_source=github\n\n\n\u003c!-- END /templates/footer.md --\u003e\n\n[mini_racer]: https://github.com/rubyjs/mini_racer\n[vue_ssr]: https://ssr.vuejs.org/\n[sample]: ./webpack.config.js\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthoughtbot%2Fhumid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthoughtbot%2Fhumid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthoughtbot%2Fhumid/lists"}