{"id":19479220,"url":"https://github.com/pmb0/express-tsx-views","last_synced_at":"2025-04-07T10:26:53.669Z","repository":{"id":37799722,"uuid":"283710377","full_name":"pmb0/express-tsx-views","owner":"pmb0","description":"Server-side JSX/TSX rendering for your express or NestJS application -- without Babel 🚀","archived":false,"fork":false,"pushed_at":"2025-03-20T18:52:23.000Z","size":2080,"stargazers_count":34,"open_issues_count":21,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-31T09:04:13.425Z","etag":null,"topics":["express","nestjs","react","ssr","template-engine","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/pmb0.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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":"2020-07-30T08:12:31.000Z","updated_at":"2025-02-14T14:05:06.000Z","dependencies_parsed_at":"2024-02-15T19:26:57.631Z","dependency_job_id":"5bde88e6-56b6-406f-850a-76d9f050ae17","html_url":"https://github.com/pmb0/express-tsx-views","commit_stats":{"total_commits":425,"total_committers":5,"mean_commits":85.0,"dds":"0.42823529411764705","last_synced_commit":"9f1a9d90b3714bc0a1c8eff9387ebd63c38bcb4e"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmb0%2Fexpress-tsx-views","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmb0%2Fexpress-tsx-views/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmb0%2Fexpress-tsx-views/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmb0%2Fexpress-tsx-views/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pmb0","download_url":"https://codeload.github.com/pmb0/express-tsx-views/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247634245,"owners_count":20970491,"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":["express","nestjs","react","ssr","template-engine","typescript"],"created_at":"2024-11-10T19:53:23.391Z","updated_at":"2025-04-07T10:26:53.633Z","avatar_url":"https://github.com/pmb0.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cp\u003eServer-side JSX/TSX rendering for your express or NestJS application\u003c/p\u003e\n\u003c/div\u003e\n\n[![npm version](https://badge.fury.io/js/express-tsx-views.svg)](https://www.npmjs.com/package/express-tsx-views)\n[![Test Coverage][coveralls-image]][coveralls-url]\n[![Build Status][build-image]][build-url]\n\n# Description \u003c!-- omit in toc --\u003e\n\nWith this template engine, TSX files can be rendered server-side by your Express application. Unlike other JSX express renderers, this one does not rely on JSX files being transpiled by `babel` at runtime. Instead, TSX files are processed once by the `tsc` compiler.\n\nFor this to work, the templates are imported dynamically during rendering. And for this **you have to provide a default export in your main TSX files**. (Embeddable TSX components don't have to use a default export).\n\n# Highlights \u003c!-- omit in toc --\u003e\n\n- Fast, since the JSX/TSX files do not have to be transpiled on-the-fly with every request\n- Works with compiled files (`.js` / `node`) and uncompiled files (`.tsx` / `ts-node`, `ts-jest`, ...)\n- Provides the definition of React contexts on middleware level\n- Supports execution of GraphQL queries from JSX components\n\n# Table of contents \u003c!-- omit in toc --\u003e\n\n- [Usage](#usage)\n  - [Express](#express)\n  - [NestJS](#nestjs)\n- [Render Middlewares](#render-middlewares)\n  - [Prettify](#prettify)\n  - [Provide React Context](#provide-react-context)\n  - [GraphQL](#graphql)\n- [License](#license)\n\n# Usage\n\n```sh\n$ npm install --save express-tsx-views\n```\n\nYou have to set the `jsx` setting in your TypeScript configuration `tsconfig.json` to the value `react` and to enable `esModuleInterop`:\n\n```json\n{\n  \"compilerOptions\": {\n    \"jsx\": \"react\",\n    \"esModuleInterop\": true\n  }\n}\n```\n\nThis template engine can be used in express and NestJS applications. The function `setupReactViews()` is provided, with which the engine is made available to the application.\n\n```ts\nimport { setupReactViews } from \"express-tsx-views\";\n\nconst options = {\n  viewsDirectory: path.resolve(__dirname, \"../views\"),\n};\n\nsetupReactViews(app, options);\n```\n\nThe following options may be passed:\n\n| Option           | Type                       | Description                                                                                                                                                                                                                           | Default             |\n| ---------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |\n| `viewsDirectory` | `string`                   | The directory where your views (`.tsx` files) are stored. Must be specified.                                                                                                                                                          | -                   |\n| `doctype`        | `string`                   | [Doctype](https://developer.mozilla.org/en-US/docs/Glossary/Doctype) to be used.                                                                                                                                                      | `\u003c!DOCTYPE html\u003e\\n` |\n| `transform`      | `(html: string) =\u003e string` | With this optional function the rendered HTML document can be modified. For this purpose a function must be defined which gets the HTML `string` as argument. The function returns a modified version of the HTML string as `string`. | -                   |\n| `middlewares`    | `TsxRenderMiddleware[]`    | A list of `TsxRenderMiddleware` objects that can be used to modify the render context. See [Render middlewares](#render-middlewares)                                                                                                  | -                   |\n\n## Express\n\nExample express app (See also `example/app.ts` in this project):\n\n```js\nimport express from \"express\";\nimport { resolve } from \"path\";\nimport { setupReactViews } from \"express-tsx-views\";\nimport { Props } from \"./views/my-view\";\n\nexport const app = express();\n\nsetupReactViews(app, {\n  viewsDirectory: resolve(__dirname, \"views\"),\n  prettify: true, // Prettify HTML output\n});\n\napp.get(\"/my-route\", (req, res, next) =\u003e {\n  const data: Props = { title: \"Test\", lang: \"de\" };\n  res.render(\"my-view\", data);\n});\n\napp.listen(8080);\n```\n\n`views/my-view.tsx`:\n\n```tsx\nimport React, { Component } from \"react\";\nimport MyComponent from \"./my-component\";\nimport { MyLayout } from \"./my-layout\";\n\nexport interface Props {\n  title: string;\n  lang: string;\n}\n\n// Important -- use the `default` export\nexport default class MyView extends Component\u003cProps\u003e {\n  render() {\n    return \u003cdiv\u003eHello from React! Title: {this.props.title}\u003c/div\u003e;\n  }\n}\n```\n\n## NestJS\n\nSee [nestjs-tsx-views](https://github.com/pmb0/nestjs-tsx-views).\n\nexpress-tsx-views can also be used in [NestJS](https://nestjs.com/). For this purpose the template engine must be made available in your `main.ts`:\n\n# Render Middlewares\n\n## Prettify\n\nPrettifies generated HTML markup using [prettier](https://github.com/prettier/prettier).\n\n```ts\nsetupReactViews(app, {\n  middlewares: [new PrettifyRenderMiddleware()],\n});\n```\n\n## Provide React Context\n\nProvides a react context when rendering your react view.\n\n```ts\n// my-context.ts\nimport {createContext} from 'react'\n\nexport interface MyContextProps = {name: string}\n\nexport const MyContext = createContext\u003cMyContextProps | undefined\u003e(undefined)\n```\n\nUse `addReactContext()` to set the context in your route or in any other middleware:\n\n```ts\n// app.ts\n\n// Route:\napp.get(\"/\", (request: Request, res: Response) =\u003e {\n  addReactContext(res, MyContext, { name: \"philipp\" });\n\n  res.render(\"my-view\");\n});\n\n// Middleware:\napp.use((req: Request, res: Response, next: NextFunction) =\u003e {\n  addReactContext(res, MyContext, {\n    name: \"philipp\",\n  });\n  next();\n});\n```\n\nNow you can consume the context data in any component:\n\n```tsx\n// my-component.tsx\nimport { useContext } from \"react\";\nimport { MyContext } from \"./my-context\";\n\nexport function MyComponent() {\n  const { name } = useContext(MyContext);\n  return \u003cspan\u003eHallo, {name}!\u003c/span\u003e;\n}\n```\n\n## GraphQL\n\nThis module supports the execution of GraphQL queries from the TSX template. For this purpose `graphql`, `@apollo/client` and `cross-fetch` have to be installed separately:\n\n```sh\n$ npm install --save @apollo/client cross-fetch\n```\n\nNow you can create an `ApolloRenderMiddleware` object and configure it as a middleware within `express-tsx-views`:\n\n```ts\nimport { ApolloClient, createHttpLink, InMemoryCache } from \"@apollo/client\";\nimport { ApolloRenderMiddleware } from \"express-tsx-views/dist/apollo\";\n// needed to create a apollo client HTTP link:\nimport { fetch } from \"cross-fetch\";\n\n// Apollo client linking to an example GraphQL server\nconst apollo = new ApolloClient({\n  ssrMode: true,\n  link: createHttpLink({\n    uri: \"https://swapi-graphql.netlify.app/.netlify/functions/index\",\n    fetch,\n  }),\n  cache: new InMemoryCache(),\n});\n\nsetupReactViews(app, {\n  viewsDirectory: resolve(__dirname, \"views\"),\n  middlewares: [new ApolloRenderMiddleware(apollo)],\n});\n```\n\nExample view (see the example folder in this project):\n\n```ts\nexport interface Film {\n  id: string;\n  title: string;\n  releaseDate: string;\n}\n\nexport interface AllFilms {\n  allFilms: {\n    films: Film[];\n  };\n}\n\nconst MY_QUERY = gql`\n  query AllFilms {\n    allFilms {\n      films {\n        id\n        title\n        releaseDate\n      }\n    }\n  }\n`;\n\nexport interface Props {\n  title: string;\n  lang: string;\n}\n\nexport default function MyView(props: Props): ReactElement {\n  const { data, error } = useQuery\u003cAllFilms\u003e(MY_QUERY);\n\n  if (error) {\n    throw error;\n  }\n\n  return (\n    \u003cMyLayout lang={props.lang} title={props.title}\u003e\n      \u003ch2\u003eFilms:\u003c/h2\u003e\n      {data?.allFilms.films.map((film) =\u003e (\n        \u003cul key={film.id}\u003e\n          {film.title} ({new Date(film.releaseDate).getFullYear()})\n        \u003c/ul\u003e\n      ))}\n    \u003c/MyLayout\u003e\n  );\n}\n```\n\n# License\n\nexpress-tsx-views is distributed under the MIT license. [See LICENSE](./LICENSE) for details.\n\n[coveralls-image]: https://img.shields.io/coveralls/pmb0/express-tsx-views/master.svg\n[coveralls-url]: https://coveralls.io/r/pmb0/express-tsx-views?branch=master\n[build-image]: https://github.com/pmb0/express-tsx-views/workflows/Tests/badge.svg\n[build-url]: https://github.com/pmb0/express-tsx-views/actions?query=workflow%3ATests\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmb0%2Fexpress-tsx-views","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpmb0%2Fexpress-tsx-views","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmb0%2Fexpress-tsx-views/lists"}