Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking react-notion vs react-notion-x #36

Closed
19 tasks done
transitive-bullshit opened this issue Oct 7, 2020 · 1 comment
Closed
19 tasks done

Tracking react-notion vs react-notion-x #36

transitive-bullshit opened this issue Oct 7, 2020 · 1 comment

Comments

@transitive-bullshit
Copy link
Contributor

React Notion X

Context

The purpose of this thread is to give some context between these two projects and track their differences, with the goal of ultimately converging on a single solution for the React Notion community going forwards.

I've spent the past few months working to improve react-notion for Notion2Site. Towards that end, I've had several conversations with @tobiaslins and @timolins who did a lot of the amazing legwork in creating the first version of react-notion.

I was working on a fork of react-notion with all of my changes in a Next.js project (not a Git fork, unfortunately), and I finally found the time to move this fork back out into its own set of standalone packages: react-notion-x.

Summary of changes

The largest changes can be broken into a few themes:

  • structural => isolating functionality into distinct packages
  • new functionality => new blocks, solid collection support, dark mode, etc
  • robustness => dozens of bug fixes
  • testing => test suite covering as much notion functionality as possible

I'll go into a bit more depth on some of these below.

Packages

One of the biggest changes is structural. Instead of relying on a CF worker and having types and utilities duplicated between react-notion and notion-api-worker, all of this has been split into isolated packages:

Package NPM Docs Environment Description
react-notion-x NPM docs Browser + SSR Fast React renderer for Notion.
notion-client NPM docs Server-side* Robust TypeScript client for the Notion API.
notion-types NPM docs Universal Core Notion TypeScript types.
notion-utils NPM docs Universal Useful utilities for working with Notion data.

imho it makes a lot more sense to expose a Notion API wrapper as notion-client that can be used from Node.js (and Next.js SSR), Deno, etc instead of just CF workers.

The goal is that hopefully once Notion releases its public API, these packages should only require minor updates with react-notion-x not having to change much if at all.

New Blocks

  • table of contents
  • checklists
  • figma
  • google maps
  • google drive
  • tweet
  • pdf
  • audio
  • file
  • equation (block & inline)
  • table collection view
  • gallery collection view
  • list collection view
  • board collection view
  • collection view page

General Improvements

  • dark mode
  • lazy loading heavy portions of the code via next/dynamic as a peer dep (eg, PDF support, collection support, equations / katex, etc)
  • support for LQIP images
  • formula support

Performance

I know one of the things that Tobias and Timo expressed very fair concerns about has been how to manage the tradeoffs between react-notion's original goal of being extremely lightweight and focused on embeddable use cases versus react-notion-x's goal of faithfully supporting all Notion content with both embedded and full page use cases.

This is very closely related to perf and bundle size, two things which I've spent a lot of time working on with react-notion-x, though there are definitely lots of tradeoffs to consider here.

I go into a bit more depth about my approach here, but in general I think that lazy loading larger optional dependencies like react-pdf, react-katex, as well as heavier portions of react-notion like collection views and equation support, gets us the best of both worlds.

The first load JS and total JS bundle size for most pages is comparable with react-notion, with larger optional dependencies only being loaded if needed by any given page.

The net result is that it's pretty easy to get solid lighthouse perf scores.

One downside of this approach is that I'm not sure how adding next/dynamic as a peer dependency works for devs who may want to use React Notion from non-Next.js projects. Does anyone have any good examples of large third-party React libraries that support loading portions of their bundle dynamically (and work regardless of if the consuming app is using Webpack or another bundler)?

Design

react-notion-x started as a fork of react-notion, and although 90% of the code has changed, the core NotionRenderer and Block classes should look very similar.

I took a very similar approach to #30 via @cball in supporting the ability to override specific components via a components prop on NotionRenderer.

Conversely, I ended up finding that as the number of components and their complexity grew, it became significantly simpler to expose an internal-only NotionContext that gives sub-components access to this configuration. It also became necessary for some interesting cases where when you render some subtrees, you want to completely negate the possibility of using <a> tags even though that subtree could contain any type of blocks. You can see an example of this in CollectionCard which can contain lots of different types of property content that we want to ensure doesn't contain any links so we override components.link and components.pageLink with a dummy link component.

Closing Thoughts

I hope this gives a good overview of my changes to react-notion-x with an emphasis on the most important design decisions.

I would've loved to have this be a real Git fork, but as I explained above this just wasn't in the cards for practical reasons as I learned about the scope of the changes needed as I went along.

Anyhow, I'm hoping that this public thread opens up a productive discussion that will benefit both projects and anyone interested in hacking on Notion in the future.

I'm very open to ideas about the best way to move both projects forward and hopefully merge them into a single react-notion solution that will provide the most long-term benefits.

Thanks!

@timolins
Copy link
Member

timolins commented Oct 7, 2020

Wow, thanks for sharing all your hard work! A lot of great improvements have been made with react-notion-x.

Moving forwards I'd love to leverage a lot of the stuff you built. I outlined some of my thoughts on how to implement those changes, while remaining true to the vision of providing a minimal content renderer for Notion in #37.

Those are the things I think make sense to look into:

  • Leverage the notion-types & notion-utils packages. They are quite unopinionated, and mostly dictated by what Notion does. Makes sense to solve those problems on dedicated packages, like you did. 👍
  • Look into notion-client for notion-api-worker (cc @tobiaslins). Same as above, makes sense to focus that work in one central point, and make it reusable for other projects. As you mentioned is a good idea to directly talk to the API when using Next.js. For projects that are not using Node or need client-side communication, I still think the worker still has it's place. Also the /table functionality is not handled by notion-client - not sure if it should, since I like the idea of it being just the a bare Notion API client without a lot of custom logic. Maybe the need for the /table endpoints will be redundant once they launch the official API.
  • Start looking into the new block types and merge them over again.

Lazy loading complex blocks is definitely a good idea. I would try to avoid depending on next/dynamic, since this rules out applications in other environments like Gatsby or manual SSR. I will put the new custom component system to the test, maybe it can provide a way to bring your own™ lazy load system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants