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

Imports in MDX files #143

Closed
dustinlacewell opened this issue May 13, 2021 · 11 comments
Closed

Imports in MDX files #143

dustinlacewell opened this issue May 13, 2021 · 11 comments
Labels
feature-request New feature or request

Comments

@dustinlacewell
Copy link

I know that the README's caveats mention this isn't currently possible and #48 is closed but:

Hopefully this makes sense, since in order to work, imports must be relative to a file path, and this library allows content to be 
loaded from anywhere, rather than only loading local content from a set file path.

But why not just let us tell next-mdx-remote where to load them from?

@jescalan
Copy link
Collaborator

There are a variety of technical hurdles that stand in the way of this. If you are interested in tackling them, we'd very much welcome a contribution!

@jescalan jescalan added the feature-request New feature or request label May 13, 2021
@jescalan
Copy link
Collaborator

jescalan commented Aug 6, 2021

Just want to update here that we are planning on implementing this as soon as we're able to prioritize it. Still quite a difficult task, but it should be possible.

@spcbfr
Copy link

spcbfr commented Jan 4, 2022

Any updates on this issue ?

@lingdocs
Copy link

lingdocs commented Feb 13, 2022

Yes please, 🙇‍♂️ for me this feature is a deal breaker and I would looove to use this tool to create a blog that relies heavily on import statements and local variables in mdx docs through export statements. Otherwise I think I'll have to be resigned to using Gatsby (which has great support for loading mdx blog posts), but I much prefer Next.js.

Also, I see that export statements don't currently work either. This would be great to have because that's currently the only way to define local variables in mdx files, ie:

export const myVar = "foo";

I will use {myVar} here.

@jescalan
Copy link
Collaborator

Sorry, no updates here. It's very difficult to pull this off properly loading from a remote source, and would require a fairly large time investment - afaik there is not a use case for this specifically at HashiCorp right now so there's not a lot of motivation to put tons of work into it.

If you are using this for something small that it not intended to go to high scale, you can still get away with loading from webpack the way that next-mdx-enhanced does, and that's the approach I'd recommend. The only issue with picking up mdx-enhanced right now is that it uses a babel transform which will trigger a deopt from swc, and it needs some webpack updates to even work with the latest version at all, so you'd have to either use a previous version of next or put some work into getting it into shape.

If you're making a personal blog, you could also look into nextra!

@dustinlacewell
Copy link
Author

We believe in you!

@brianespinosa
Copy link
Contributor

@jescalan I feel like I might be able to come up with something using node fs when encountering an import statement... but before I jump in to trying something out, I want to understand if there is a reason you would recommend against that or if that would preclude those efforts from getting merged based on HashiCorp's use case.

I am guessing I would need to poke around in the plugin that removes import and export statements from the MDX as we will need the import statements for using getting the imported components.

If either of the above ideas is incorrect or not in alignment with this project, let me know. Otherwise, I happen to have some time off before starting a new role and I might find some time to see if I can get something working. I am also not that good with Typescript so this would be something fun to level up on a bit.

@BRKalow
Copy link
Contributor

BRKalow commented Feb 17, 2022

Hey @brianespinosa! The main difficulty with supporting import statements with this library is that it operates after the application is bundled. This is by design, as at HashiCorp we treat the MDX content as data which is fetched at runtime, instead of a different module format. When the application gets bundled import foo from 'bar' might turn into __webpack_require__(76), losing the reference to the initial module name. This is why we support passing scope as well as components.

If we want to share code between the application bundle and the imports in our MDX, we need a way to map the module being requested from an MDX import to that module in our app bundle. An fs-based approach could work in a node environment, but we'd be out of luck when executing the code on the client. We could support passing some sort of import map into our methods, using a combination of https://webpack.js.org/api/module-methods/#requireresolveweak and a plugin to rewrite imports to __webpack_require__ calls. 👈 That seems like it might be the most promising path.

Another approach might be to use dynamic imports and attempt to resolve from external modules, e.g.:

import foo from 'unpkg.com/package@1.0.0'

// vvvv

(await import('unpkg.com/package@1.0.0')).foo

With this though, we change the MDX rendering from sync to async, so we'd need Suspense support on the server.

Hopefully this helps give some context, if you're interested in giving this a shot let me know!

@brianespinosa
Copy link
Contributor

@BRKalow thank you for taking the time to put this thoughtful write up together about the limitations with my proposal and some pointers of where this might still work.

I'll check back in when I sit back down at a computer in a couple weeks and update you on if I have some bandwidth to tinker with this.

@Robbie-Cook
Copy link

A very makeshift workaround for now could be:

  • import the files you need in a .tsx file (e.g. the page)
  • pass them to a component in a page,
  • then pass that component to MDX via the components prop.

e.g. Here is an example of rendering JSON files in graph components. I was trying to import the JSON files directly in the MDX.

import ChartSnapshot from "~/components/ChartSnapshot";
import decemberSnapshotNz from "~/snapshots/december-2022-nz.json";
import decemberSnapshotAu from "~/snapshots/december-2022-au.json";

const components = {
  ChartSnapshotDecemberNz2022: () => (
    <ChartSnapshot
      snapshotData={decemberSnapshotNz}
      label="Number of Open IT Jobs over Dec 2022, NZ"
      description="50.2% decrease in New Zealand IT jobs over December 2022."
    />
  )
};

...

<MDXRemote {...source} components={components} />

And then in the MDX file

## Numbers

#### Foo Bar

<ChartSnapshotDecemberNz2022 />

@BRKalow
Copy link
Contributor

BRKalow commented Feb 11, 2023

Hey y'all, I know this issue has been open for quite some time and supporting import statements is a common question/feature when folks start using next-mdx-remote.

As mentioned above, here at HashiCorp we treat our MDX content as data that gets loaded and rendered at runtime, potentially independent of our application's compilation steps. This is fundamentally at odds with supporting imports to local application code. Given that, I'm going to close this issue as it's not something we have a need to support at this time.

If all of your content is local to your repository, it might be worth looking at @next/mdx, which is integrated with Next's compiler and more naturally supports treating your MDX as an extension of your source.

As we continue to evolve our content platform, this might be something we revisit. With React Server Components support now available, this opens interesting opportunities to use async server components to support imports of external modules. Anyone is of course welcome to contribute support for this if they're up for it! 🙏

@BRKalow BRKalow closed this as completed Feb 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request New feature or request
Projects
None yet
Development

No branches or pull requests

6 participants