shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 3

In this article, I discuss how Blocks page is built on ui.shadcn.com. Blocks page has a lot of utilities used, hence I broke down this Blocks page analysis into 5 parts.

shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 1

shadcn-ui…


This content originally appeared on DEV Community and was authored by Ramu Narasinga

In this article, I discuss how Blocks page is built on ui.shadcn.com. Blocks page has a lot of utilities used, hence I broke down this Blocks page analysis into 5 parts.

  1. shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 1
  2. shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 2
  3. shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 3
  4. shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 4 (Coming soon)
  5. shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 5 (Coming soon)

In part 3, I will explain how createTempSourceFile, createSourceFile and extractVariable work in order to understand getBlockCode completely. Keep in mind, we still need to get back to getBlock since this is used in BlockDisplay .

_getBlockCode function code:

async function \_getBlockContent(name: string, style: Style\["name"\]) {
  const raw = await \_getBlockCode(name, style)

  const tempFile = await createTempSourceFile(\`${name}.tsx\`)
  const sourceFile = project.createSourceFile(tempFile, raw, {
    scriptKind: ScriptKind.TSX,
  })

  // Extract meta.
  const description = \_extractVariable(sourceFile, "description")
  const iframeHeight = \_extractVariable(sourceFile, "iframeHeight")
  const containerClassName = \_extractVariable(sourceFile, "containerClassName")

  // Format the code.
  let code = sourceFile.getText()
  code = code.replaceAll(\`@/registry/${style}/\`, "@/components/")
  code = code.replaceAll("export default", "export")

  return {
    description,
    code,
    container: {
      height: iframeHeight,
      className: containerClassName,
    },
  }
}

In part 2, we looked at _getBlockCode in great detail. Let’s understand createTempSourceFile.

createTempSourceFile

createTempSourceFile function creates a unique temporary directory.

async function createTempSourceFile(filename: string) {
  const dir = await fs.mkdtemp(path.join(tmpdir(), "codex-"))
  return path.join(dir, filename)
}

tempdir is imported from “os”, since shadcn-ui/ui uses Next.js, all this code is executed on server, hence it has access to “os” node.js package. lib/blocks.ts has “use server” at the top of file.

Basically, what this code means is that a temporary file with block file name is temporarily placed in a temporary folder.

createSourceFile

createSourceFile is a function called using project object

const sourceFile = project.createSourceFile(tempFile, raw, {
    scriptKind: ScriptKind.TSX,
})

Hang on a minute, what is project object?

const project = new Project({
  compilerOptions: {},
})

At the top of the file, this project variable is initiated with a Project instance. Now what is Project? Project is imported from ts-morph? What is ts-morph? Let’s find out.

ts-morph

ts-morph is a library that wraps the TypeScript compiler API to simplify setup, navigation and manipulation of the Typescript AST. This article has a good explanation what Typescript AST means.

When the TypeScript compiler compiles your code, it creates an Abstract Syntax Tree (AST) of it. Essentially, an AST can be thought of as a tree representation of the syntax of your source code, with each node being a data structure representing a construct in the relating source code. The tree is complete with nodes of all the elements of the source code.

I definitely need to more research on this ts-morph concept and provide some examples in the best practices module and also talk about this a bit more in part 4.

const sourceFile = project.createSourceFile(tempFile, raw, {
    scriptKind: ScriptKind.TSX,
})

ts-morph.com documentation provides an example that uses project.createSourceFile, just like how shadcn-ui/ui does it.

We know how tempFile is created, raw is variable containing the file code returning by getBlockCode, for example, code sitting at https://github.com/shadcn-ui/ui/blob/main/apps/www/_registry__/new-york/block/authentication-04.tsx

I will provide an example project that uses ts-morph and performs the similar operations that shadcn-ui/ui does to understand createSourceFile and extractVariable. getBlock also uses these similar functions in part 4.

Conclusion:

shadcn-ui/ui performs some additional operations using ts-morph after reading the code from registry folder’s blocks file. Why not just read the file directly? this is an interesing question. I will find out why there is a need to use ts-morph to extract the code further from the read file in part 4.

This is the beauty of reading/studying OSS code, you are exposed to a lot of new technical concepts. I do not know what ts-morph is yet… but I will find out soon and provide an example project after running some experiments. I will keep this example limited to the similar operations used in shadcn-ui/ui.

This part 3 does provide insights into creating a temporary folder using “os” package since lib/block.ts has “use server” at the top of this file.

Want to learn how to build shadcn-ui/ui from scratch? Check out build-from-scratch

About me:

Website: https://ramunarasinga.com/

Linkedin: https://www.linkedin.com/in/ramu-narasinga-189361128/

Github: https://github.com/Ramu-Narasinga

Email: ramu.narasinga@gmail.com

References:

  1. https://github.com/shadcn-ui/ui/blob/main/apps/www/lib/blocks.ts#L107
  2. https://github.com/shadcn-ui/ui/blob/main/apps/www/lib/blocks.ts#L102
  3. https://github.com/shadcn-ui/ui/blob/main/apps/www/lib/blocks.ts#L16
  4. https://github.com/shadcn-ui/ui/blob/main/apps/www/lib/blocks.ts#L135


This content originally appeared on DEV Community and was authored by Ramu Narasinga


Print Share Comment Cite Upload Translate Updates
APA

Ramu Narasinga | Sciencx (2024-06-19T20:41:49+00:00) shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 3. Retrieved from https://www.scien.cx/2024/06/19/shadcn-ui-ui-codebase-analysis-how-is-blocks-page-built-part-3/

MLA
" » shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 3." Ramu Narasinga | Sciencx - Wednesday June 19, 2024, https://www.scien.cx/2024/06/19/shadcn-ui-ui-codebase-analysis-how-is-blocks-page-built-part-3/
HARVARD
Ramu Narasinga | Sciencx Wednesday June 19, 2024 » shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 3., viewed ,<https://www.scien.cx/2024/06/19/shadcn-ui-ui-codebase-analysis-how-is-blocks-page-built-part-3/>
VANCOUVER
Ramu Narasinga | Sciencx - » shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 3. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/06/19/shadcn-ui-ui-codebase-analysis-how-is-blocks-page-built-part-3/
CHICAGO
" » shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 3." Ramu Narasinga | Sciencx - Accessed . https://www.scien.cx/2024/06/19/shadcn-ui-ui-codebase-analysis-how-is-blocks-page-built-part-3/
IEEE
" » shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 3." Ramu Narasinga | Sciencx [Online]. Available: https://www.scien.cx/2024/06/19/shadcn-ui-ui-codebase-analysis-how-is-blocks-page-built-part-3/. [Accessed: ]
rf:citation
» shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 3 | Ramu Narasinga | Sciencx | https://www.scien.cx/2024/06/19/shadcn-ui-ui-codebase-analysis-how-is-blocks-page-built-part-3/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.