Giter Site home page Giter Site logo

Custom JSX/TSX components about nue HOT 2 OPEN

mszmida avatar mszmida commented on June 4, 2024 1
Custom JSX/TSX components

from nue.

Comments (2)

tipiirai avatar tipiirai commented on June 4, 2024

Documentation is indeed very laconic currently. It's both lagging behind the code and fails to explain some of the core concepts.

Here is a JSX working test case for building a custom Nuemark extension:

https://github.com/nuejs/nue/blob/master/packages/nuemark/test/nuemark.test.js#L430

That's all there is now with regards to extension. Hope that helps. The idea is to finish the core pieces first and launch a v1.0, before moving into extensions and integrations. Nue is still an early beta.

from nue.

mszmida avatar mszmida commented on June 4, 2024

Thank you very much for your response and advice @tipiirai!

At the beginning I would like to sorry for my late response and share my results so maybe it can help also other developers to understand better the problem and solution.

Zag integration results

Let's forget about Zag. I was able to implement working integration with a simple Number Input component by myself, but I was not happy with the code. One of the biggest reason is the lack of the spread properties feature available in JSX/TSX. I had to implement my own solution for that. Another reason is that this library has its own logic implementation for each component based on the state machines. This is another custom abstraction layer and the library itself is also very much tightly coupled to the React, Solid, Vue and heavily relies on the concepts from these frameworks.

Because the main reason of the Nue framework is to be closer to the web standards I decided to search something else and I found Shoelace which is a collection of UI components build on web components standard. Thanks to this the components implementation is fully framework agnostic. Library looks mature and I am going to test these components together with Nue and built SPA with forms. It should eliminate any need to create custom integrations and so on.

Custom JSX/TSX components

Coming back now to the original problem. I decided to investigate further the custom components problem inspired by the Custom components section and especially TSX components section. My main idea was to create custom TSX components and render them on the client side in the browser in my SPA. In my previous attempts, I didn't know how to properly import Nuemark API. The reason was that I didn't read carefully Unbundled distribution section which says:

The default is to build, but not bundle. That is: the imported dependencies are not inlined into the file itself to form a single, bigger JS bundle.

So I decided to bundle the Nuemark API. Unfortunately the Bundled distribution section was not quite clear for me. I couldn't understand how the bundle: [ index.ts ] option works. Whenever I tried to import Nuemark API like this:

// *.nue file
import { nuemarkdown } from "nuemark";

nothing happened... After transpiling the project files, the import statement remained unchanged. To understand what was going on, I had to debug Nue CLI code to realize that the *.nue files are not processed by Bun.build() at all. The are just compiled by your custom mechanism into *.js files. Only the *.js and *.ts files are processed by Bun.build() and the bundle option inside *.yaml config files is used to determine in which files from the project, import statements should be inlined after transpilation process. It was eureka! After that I created index.ts file in my SPA project root with the content:

// index.ts
export { nuemarkdown } from "nuemark";

The Nuemark API has been finally inlined into generated index.js file. Victory! ✌

The next step was to create TSX components that I could render in my SPA. According to the TSX components section I added following dependencies to the project folder:

// run in terminal
bun add react
bun add react-dom

and created TSX components library:

// components.tsx

// import of the React SSR (server-side rendering)
import { renderToString } from "react-dom/server";

// first custom tag
function MyTag(props: { message: string }) {
  return <h1 style={{ color: "red" }}>{props.message}</h1>;
}

// second custom tag
function MyTag2(props: { message: string }) {
  return <h1 style={{ color: "blue" }}>{props.message}</h1>;
}

const components = { MyTag, MyTag2 };

// Make lib compatible with Nuemark
export const tsx_lib = Object.keys(components).map((name) => {
  return {
    name,
    render: function (data, lib) {
      return renderToString(components[name](data, lib));
    },
  };
});

After debugging your code I already knew that Nue CLI treats *.tsx files as static and copies them as is to the .dist/dev directory so I had to transpile the file manually with Bun:

bun build ./components.tsx --outdir ./.dist/dev

After that the components.js file appeared with all React dependencies inlined in place and I could finally create custom Nue component that gives possibility to render custom TSX components in my SPA:

// tsx-component.nue
<script>
  import { nuemarkdown } from './index.js'
  import { tsx_lib } from './components.js'
</script>

<div @name="tsx-component">
  <script>
    mounted({ name, data }) {
      const html = nuemarkdown(`[${name}]`, {
        data,
        lib: tsx_lib,
      });

      /**
       * The this.mountChild() method unfortunately is not documented enough
       * so I had to use this ugly solution:
       */
      this.$el.innerHTML = html
    }
  </script>
</div>

All I had to do was consume my amazing custom Nue component in SPA:

// home-view.nue
<section @name="home-view">
  <script>
    tag = { message: "My first custom tag!" }
    tag2 = { message: "My second custom tag!" }
  </script>

  <h1>Hello, World!</h1>

  <tsx-component name="my-tag" :data="tag" />

  <tsx-component name="my-tag2" :data="tag2" />
</section>

The results are visible on the screenshot 🎉

image

Conclusions

I am sorry for such a long answer, but I wanted to share my solution with you @tipiirai and other developers. It might help to shed some light on the problems I faced during implementation of the custom JSX/TSX components and possible solutions. This PoC opens possibility to implement integrations with different frameworks, however I have no idea if your intention was to use Nuemark API in a such way on the client-side components. I have the impression that you prepared this API for server-side components, despite the fact that there is no mention of them in the documentation.

I am fully aware of that the idea is to finish the core pieces first and launch a v1.0, before moving into extensions and integrations, but just wanted to check if I implemented custom TSX components as intended or maybe you had different vision behind it.

Regards

from nue.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.