{"id":18637790,"url":"https://github.com/engineerapart/stencil-lift","last_synced_at":"2025-07-22T04:04:31.455Z","repository":{"id":57111582,"uuid":"136852337","full_name":"engineerapart/stencil-lift","owner":"engineerapart","description":"Stencil Lift - An SSR-safe data loading \u0026 injection utility for Stencil apps","archived":false,"fork":false,"pushed_at":"2018-06-14T22:51:52.000Z","size":34,"stargazers_count":5,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-01T08:19:02.453Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/engineerapart.png","metadata":{"files":{"readme":"readme.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-10T23:24:34.000Z","updated_at":"2018-12-28T02:11:40.000Z","dependencies_parsed_at":"2022-08-21T00:00:58.447Z","dependency_job_id":null,"html_url":"https://github.com/engineerapart/stencil-lift","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/engineerapart/stencil-lift","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/engineerapart%2Fstencil-lift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/engineerapart%2Fstencil-lift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/engineerapart%2Fstencil-lift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/engineerapart%2Fstencil-lift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/engineerapart","download_url":"https://codeload.github.com/engineerapart/stencil-lift/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/engineerapart%2Fstencil-lift/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266424014,"owners_count":23926123,"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","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-11-07T05:37:52.331Z","updated_at":"2025-07-22T04:04:31.424Z","avatar_url":"https://github.com/engineerapart.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Built With Stencil](https://img.shields.io/badge/-Built%20With%20Stencil-42bc98.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjIuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI%2BCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI%2BCgkuc3Qwe2ZpbGw6I0ZGRkZGRjt9Cjwvc3R5bGU%2BCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik00MjQuNywzNzMuOWMwLDM3LjYtNTUuMSw2OC42LTkyLjcsNjguNkgxODAuNGMtMzcuOSwwLTkyLjctMzAuNy05Mi43LTY4LjZ2LTMuNmgzMzYuOVYzNzMuOXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTQyNC43LDI5Mi4xSDE4MC40Yy0zNy42LDAtOTIuNy0zMS05Mi43LTY4LjZ2LTMuNkgzMzJjMzcuNiwwLDkyLjcsMzEsOTIuNyw2OC42VjI5Mi4xeiIvPgo8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNDI0LjcsMTQxLjdIODcuN3YtMy42YzAtMzcuNiw1NC44LTY4LjYsOTIuNy02OC42SDMzMmMzNy45LDAsOTIuNywzMC43LDkyLjcsNjguNlYxNDEuN3oiLz4KPC9zdmc%2BCg%3D%3D\u0026colorA=16161d\u0026style=for-the-badge)](https://github.com/ionic-team/stencil)\n\n[![npm (scoped)](https://img.shields.io/npm/v/@engineerapart/stencil-lift.svg?style=for-the-badge)](https://www.npmjs.com/package/@engineerapart/stencil-lift)\n[![npm bundle size (minified + gzip)](https://img.shields.io/bundlephobia/minzip/@engineerapart/stencil-lift.svg?style=for-the-badge)](https://www.npmjs.com/package/@engineerapart/stencil-lift)\n[![npm](https://img.shields.io/npm/l/@engineerapart/stencil-lift.svg?style=for-the-badge)](https://www.npmjs.com/package/@engineerapart/stencil-lift)\n\n\n# Stencil\n\n[Stencil](https://github.com/ionic-team/stencil) is a compiler for building fast web apps using Web Components.\n\nStencil combines the best concepts of the most popular frontend frameworks into a compile-time rather than run-time tool.  Stencil takes TypeScript, JSX, a tiny virtual DOM layer, efficient one-way data binding, an asynchronous rendering pipeline (similar to React Fiber), and lazy-loading out of the box, and generates 100% standards-based Web Components that run in any browser supporting the Custom Elements v1 spec.\n\nStencil components are just Web Components, so they work in any major framework or with no framework at all.\n\n\n# Stencil Lift\n\nBecause Stencil is so new, there are several features it does not yet support: Service injection (I have a library for that too!) and Data serialization \u0026 rehydration for SSR are two big ones.\n\nThis library aims to solve the second problem: For an SSR app (which you may have chosen for SEO, for example), you need to be able to load data on the server, render your components, and pass that data to the client in order to retain the rendered components as well as \"continue\" where you left off.\n\nYou also don't want such a library to be intrusive: I have been building these kinds of apps for years and data orchestration code can get very messy, very quickly. Introducing __Stencil Lift__!\n\nThis project is specifically designed to be used in [Stencil applications](https://github.com/ionic-team/stencil-app-starter), but there is no particular reason it can't be used in a vanilla JS app. Instructions for doing this are below.\n\n\n## Installing\n\nTo start building a new web component using Stencil, clone this repo to a new directory:\n\n```bash\nnpm i @engineerapart/stencil-lift\n```\n\nor\n```bash\nyarn add @engineerapart/stencil-lift\n```\n\n## Using the component + data services\n\nYou don't have to set up anything. No, really. Just connect your components and go.\n\n\n## Connecting Components\n\nThere are 3 steps to getting up and running.\n\n1. In your main application element (usually app.tsx - your top-level element), wrap the entire tree with the `\u003cstencil-lift\u003e` component:\n\n```js\n@Component(...)\nexport class MyApp {\n  constructor() {\n    // whatever\n  }\n\n  render() {\n    \u003cstencil-lift\u003e\n      \u003cyour-app-tree\u003e\u003c/your-app-tree\u003e\n    \u003c/stencil-lift\u003e\n  }\n}\n```\n\n2. Wrap a component you want to connect in the `Lift` decorator (or export your class wrapped with Lift({key: 'blah'})(YourComponent) as a Higher Order Component):\n\n```js\nimport { Lift } from '@engineerapart/stencil-lift/';\n\n@Lift({ key: 'YourDescriptiveKey' })\n@Component(...)\nexport class MyComponent {\n\n}\n\n// Alternatively:\nexport default Lift({key: 'YourDescriptiveKey'})(YourComponent);\n\n```\n\n3. If you want to load data in that component on the server, and receive it on the client, add a `getInitialProps` function to your component (yes, inspired by [Next.js](https://github.com/zeit/next.js)) that returns the data in the same shape you want to receive it:\n\n```js\nimport { Lift } from '@engineerapart/stencil-lift/';\n\n@Lift({ key: 'YourDescriptiveKey' })\n@Component(...)\nexport class MyComponent {\n\n  // You can use @Prop() here too.\n  @State() someKey: any; // if you know the type, put the type!\n\n  async getInitialProps({ Lift, isServer }) =\u003e {\n    const response = await fetch('http://yourapi/resource/1');\n    const data = await response.json();\n    // Note that 'someKey' matches the State property above!\n    return { someKey: data };\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        {this.someKey.field}\n      \u003c/div\u003e\n    );\n  }\n}\n```\n\nThat's it. That is literally it. You thought that was going to be harder.\n\n\n\n### Receiving data from the store without `getInitialProps`\n\nYou remember that data key you put in the `Lift({key})` decorator? You can receive any data you want. No really. Let's say you have a loader that executes at the top level of your app on the server. You can push this data directly into `stencil-lift` and receive it in any component that wants it.\n\n_This also means you can load data in one component and display it in any other component_.\n\n\n#### Adding data to the `\u003cstencil-lift\u003e` top-level component:\n\n```js\n// This can come from wherever you want it to.\nconst initialState = {\n  bubble: {\n    title: 'Hello world',\n    text: 'I am the very model of a modern major general!',\n  }\n}\n\n@Component(...)\nexport class MyApp {\n\n  @State() initialState2: any;\n\n  async componentWillLoad() {\n    this.initialState2 = fetch(...);\n  }\n\n  render() {\n    return (\n      \u003cstencil-lift initialState={{...initialState, ...initialState2}}\u003e\n        \u003cyour-app-tree\u003e\u003c/your-app-tree\u003e\n      \u003c/stencil-lift\u003e\n    );\n  }\n}\n```\n\n\n#### Receive the data wherever you want:\n\nSame as the original example. No really.\n\n```js\nimport { Lift } from '@engineerapart/stencil-lift/';\n\n@Lift({ key: 'bubble' })\n@Component(...)\nexport class MyComponent {\n\n  @State() title: string;\n  @State() text: string;\n\n  render() {\n    return \u003cdiv\u003e{this.title}\u003cspan\u003e{this.text}\u003c/span\u003e\u003c/div\u003e;\n  }\n}\n\n```\n\n\n# Other Uses\nIf it hadn't already occurred to you, you can also use Stencil Lift on the client without any data loading capabilities. Say for example you have a JSON data blob that you have in your bundle; you can inject that directly into `\u003cstencil-lift\u003e` to disburse it to the component tree. This allows you to have a single entry point for your data and the components simply declare what they need, instead of configuring each component with its data.\n\n# Does this work with prerendering?\nYes, although, I think this needs work. If you find any issues don't hesitate to file an issue.\n\n# Does this work client side?\nRight now, it only works if you use SSR and send your SSR'd page to the client. The next release will allow you to use this on the client as well (e.g. as a pure client app).\n\n\n# API\n\n## `stencil-lift` Properties\n\n| Prop\t| Default\t| Description  \t|\n|---\t|---\t|---\t|\n| initialState  \t| {}\t| The initial data you want pushed to the store. The object's high-level keys correspond to the `key` argument used in the `Lift` decorator.  \t|\n| mergeState  \t| false\t| Merge your initialState argument with loaded data if `true`, or force it to be used wholly if `mergeState` is `false` and `initialState` is defined.  \t|\n| deleteOnClientLoad  \t| false\t| For sensitive data, you may not wish it to remain available to the Window context. This will cause it (and the corresponding JS) to be deleted from the window.  \t|\n\nAll `stencil-lift` properties are optional.\n\n## `Lift` decorator properties\n\n| Prop\t| Default\t| Description  \t|\n|---\t|---\t|---\t|\n| key  \t| ''\t| [required] The redux state slice under which this component's data will be stored. You can receive data from ANY state slice - not just the one you generate.  \t|\n\n\n\n# Example\nThere is a working example of all of these concepts in the `src/components/example` folder.\n\n\n# TODO List:\n- [ ] Wire up the components to receive data changes from the redux store on the client. This is easy to do and will be in the next version.\n  - This includes making this work on client as well, no ssr - a simple switch with isServer on the decorator should do it.\n- [ ] Allow a Lift decorator to receive data from several state slices: Incorporate `reselect` for this.\n- [ ] Support generic Redux reducers. Let you reshape your data however you see fit before it is stored.\n- [ ] Support side effects in actions. This is less useful, since you can generate the side effect in your component, but you may wish to dispatch an action on the client that is consumed by a different component\n\n\n# Building/Contributing\n\nClone the project and install dependencies:\n```\ngit clone https://github.com/engineerapart/stencil-lift.git\ncd stencil-lift\nnpm i \u0026\u0026 npm start (or npm start:ssr)\n- or -\nyarn \u0026\u0026 yarn start (or yarn start:ssr)\n```\n\n### IMPORTANT NOTE\n\n__This note applies only to building `stencil-lift`. You can do whatever you want in your client application.__\n\nFor now, there is a bug in the Stencil compiler that causes the lift component to lose its script tag. Make sure you do not remove the line `logLevel: 'debug'` from the `stencil.config.js` file. Specifically the bug is actually in `uglify-es` when using `beautify:false` and will likely take some time to track down. Using `logLevel: debug` causes `beautify: true` to be set which prevents the problem.\n\nThe ONLY effect this has is that the built packages retain their whitespace - but since gzip compression largely takes care of this it is not a big issue.\n\nYou can disable `logLevel: 'debug'` when running the server if you want, but it must be enabled for the build step.\n\n\n# License\nMIT","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fengineerapart%2Fstencil-lift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fengineerapart%2Fstencil-lift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fengineerapart%2Fstencil-lift/lists"}