[Meteor/React] Is it good practice to import things from a symlink directory?

Hi, so in React I need to import something that will be in some folder strictly outside the project’s source directory. So, there is no way for me to traditionally import anything from a file in this external folder.

I seem to have bypassed this by creating a symlink directory in my project linking to that folder, and it seems to be working fine. Here are some observations:

  1. I have not added this symlinked directory into .meteorignore, because then I can’t import anything from it.
  2. I have however added it to .gitignore since I don’t want that sync’ed to my Github repo. I’m not sure how symlinks would behave when cloning repos etc, I need to read up more about this.
  3. Meteor does not hot-reload when there are changes in this symlinked directory, and rightfully so. Adding or deleting things from this directory doesn’t trigger a reload.

Is this acceptable practice in the eyes of Meteor, to use resources from a symlinked directory? I’m curious about a few things:

  1. What does Meteor “see” in this symlinked directory? Does it only see an empty directory, and that’s why it doesn’t hot-reload whenever there are changes in the external directory? Or is this an unintended side-effect of something else?
  2. This seems to have worked out for me because the contents of this directory can change whenever, and it’s not ideal for Meteor to keep reloading every time there’s a change in it. This seems to be the ideal solution because technically I didn’t have to add it to .meteorignore and yet Meteor doesn’t reload when there are changes, so I can use this dynamic content in my app. However it feels a little hacky as I’m not sure if this is an intended feature of symlinks or anything else. Is there anything I should be mindful of with this approach?

Appreciate any insights, thank you.

Symlinking directories into a Meteor project sounds like an odd idea. I wouldn’t do it, and I’m almost sure it’s not standard practice.

If you need to reference a piece of code that normally lives outside your Meteor project, you could turn that thing into an npm package, and add that package to your Meteor project. That also makes it perfectly controllable which version you want to use.

You can have private packages on npmjs.com, or, if you have the infrastructure, you can set up your own private npm repository on your own host, vm or vps. That’s what I do that myself, I set up Nexus Repository OSS for that purpose (among other uses in my case), but there are less heavyweight alternatives out there.

To elaborate more on my use case, I can’t turn this into a package.

I’m using apollinaire:mdx to import .mdx files into my project, basically for a blog.

Right now, I can dynamically import them as such (I truncated the code a little, this logic lies inside a useEffect hook):

const MDXComponent = useRef()
import(`./posts/someFile.mdx`).then(MDX => {
    MDXComponent.current = MDX.default
}, (err) => {
    console.log(err)
})
...
return MDXComponent.current ? <MDXComponent.current /> : null

I will note however that this doesn’t work 100% yet as I need to be able to pass in a variable for the import as such:

const MDXComponent = useRef()
const fileID = "someString"
import(`./posts/${fileID}.mdx`).then(MDX => {
    MDXComponent.current = MDX.default
}, (err) => {
    console.log(err)
})
...
return MDXComponent.current ? <MDXComponent.current /> : null

The second solution won’t work, unfortunately. Path in dynamic import needs to be a static string.

You can use import with dynamic expressions. You just need to whitelist all the possible values of the variable

2 Likes

How exactly is this whitelisting done?

What is if (false) in that example?

I can definitely track a list of all the files needing to be imported in the symlinked directory, but the docs don’t seem very specific on actual implementation of this whitelist.

EDIT: Nevermind - it says that you can just include that code block somewhere.

So I just created a file and threw in that import in an if (false) block and it seems to work. Only caveat though is that whenever I need to update the file, the server would restart. This may be okay, but I need to think about how this affects everything else.

But this imports all of them on compile right? So if I have many blog posts, won’t this significantly add to the overheads and bundle size?

That’s why you are using dynamic imports. To only import the file when the client needs it

1 Like

Okay cool! Thanks for the information. I will proceed with this method then.