shuding / nextra

Simple, powerful and flexible site generation framework with everything you love from Next.js.
https://nextra.site
MIT License
11.71k stars 1.27k forks source link

Proposal: replace `_meta.json` in favor of `_meta.{js,jsx,ts,tsx}` #852

Closed dimaMachina closed 1 year ago

dimaMachina commented 2 years ago

First of all why?

  1. to have the possibility to include repeated top content in main block

image

  1. to have possibility to include bottom content in main block

currently it's possible via main.extraContent property but the source code became ugly since we have to check in which page we are and what we need to show

https://github.com/dotansimha/graphql-yoga/blob/1b018c3d2d347d3ca02eb0ca0175025325db6886/website/theme.config.tsx#L51-L64

  1. to have possibility to sort sidebar items with the default eslint rule sort-keys and with eslint comment /* eslint sort-keys: error */ and omit installation of some JSON plugin to do it

  2. have type safe _meta file since we can import Meta type and have autocomplete

Example: current _meta file with included some top and bottom content will looks like

before

https://github.com/shuding/nextra/blob/1a029e615a851d6ad7c1ad4238f455fee551b030/examples/swr-site/pages/docs/advanced/_meta.en-US.json#L1-L13

after

export default {
  "*": {
    theme: {
      footer: false,
      main: {
        topContent: <div>foo</div>,
        bottomContent: <span>bar</span>
      }
    },
  },
  "--- yoo": {
    title: "Do Not Use",
    type: "separator",
  },
  more: "More: A Super Super Super Super Long Directory",
  "file-name.with.DOTS": "Filenames with Dots",
};

@shuding any thoughts? :)

dimaMachina commented 2 years ago

πŸ’‘ Also, we need to find a way to ignore accessing _meta file since Next.js will treat it as page. Example: accessing /docs/_meta route should return a 404 error

shuding commented 2 years ago

I like the idea! Allowing _meta to be JavaScript brings more dynamicity indeed. And I'm a big fan of the type safety feature. Although I assume that it will be a bit tricky to support anything other than _meta.js, because we need the data inside the loader logic which is Node.js and can't make it easy to support TS and JSX there (and ESM too).

Like you said, the Next.js routing is also a problem. I think we can explore a solution here and if it's doable, 100% agree that we should add it!

dimaMachina commented 2 years ago

Although I assume that it will be a bit tricky to support anything other than _meta.js

You are right, I guess _meta.mjs will be a better extension since Next.js will treat .js files under the /pages directory as Page and since it's not exporting React component, Next.js throw an error

I didn't find a way to ignore _meta.js to treating as a page πŸ˜…

can't make it easy to support TS and JSX there (and ESM too)

I think for now we can skip support TypeScript and use JSDoc comment for validations types, it's better than nothing

The main blocking problem for now, is to figure out how to import _meta.mjs when there are React components inside or JSX markup

And also we make JSON.stringify of pageMap (with content of meta file) here

https://github.com/shuding/nextra/blob/09b4102c9141944b4b67b072cc5566993d78a44b/packages/nextra/src/loader.ts#L185-L196

https://github.com/shuding/nextra/blob/09b4102c9141944b4b67b072cc5566993d78a44b/packages/nextra/src/loader.ts#L213

shuding commented 1 year ago

I didn't find a way to ignore _meta.js to treating as a page πŸ˜…

I started to think again about this because I want to land this feature for remote MDX + versioning. I think I got an idea implementation, but it relies on _meta.js and some changes to i18n (https://github.com/shuding/nextra/issues/1152).

I guess we can just make _meta.js a Next.js page (so we got .js, .jsx and .tsx support), and inject rewrites to force /_meta routes being /404.

dimaMachina commented 1 year ago

Closed https://github.com/shuding/nextra/pull/1168