What is a Symlink?

Hello and happy new year! I hope that your 2023 is off to a great start. As I'm writing this, there are pots on the stove percolating away, filled with collard greens, Hoppin' John, and a fresh batch of bone broth. The house smells amazing.

This month I am participating in Bring Back Blogging, a little effort for blogging creatives to commit to posting at least three times during January, sharing those posts with their networks, and getting into or supporting the habit of writing to their blogs. Having been on the internet for some time, I've seen platforms like Myspace and Livejournal come and go. Tumblr seems to be making a valiant comeback. Even if they don't fully die, social media platforms can become stale and less visited, take Facebook for example. Because of this, I'm a big proponent of owning the content that means the most to you and controlling your hometurf. Even if it doesn't get the biggest readership, I am quite proud of my little tech blog here and I am so happy to share it with the world, and to keep learning out loud.

So if you're here for the first time from Bring Back Blogging, welcome! My name is Joey, and I've been doing professional web development for the last 7 years or so. You can read more about my background on my About page, but this blog is where I have tried to catalog things I'm learning or little challenges I've found solutions for.

In the communal spirit of Bring Back Blogging, I also want to highlight other blogs I find interesting through BBB in my posts this month. The first blog that caught my eye is called Transit Maps. It's run by Cameron Booth, and is devoted entirely to the design of transit map diagrams – real, historical, proposed, fictional, whatever! It's certainly a fun and unique concept for a blog. The earliest post is February 2010, so it's been going for nearly 13 years, which is impressive. From a tech standpoint, it looks to be a pretty standard WordPress site hosted on Bluehost. A neat little easter egg is that the tagline under the blog title is randomized, so it will change out when you reload the page. James seems to have accomplished this by having about ten or so logo images with these various taglines embedded in the image, and on page load a random one is selected to be rendered.

Anyway, enough about other blogs and the start of the year, I'm here to talk briefly about Symlinks.

A symlink is nothing more than a shortcut on a computer. The term itself is a portmanteau for "symbolic link", and it's really just a way to connect or "link" a file or a directory on one part of your computer to a file or directory in another location on your computer. Although the target file or directory lives in location A, a symlink can be created in location B to access those files as though they actually live in location B.

The main reason for using a Symlink is convenience. Say you have a JavaScript library living deep in a nested folder /directory-a/ on your computer, but you're building an HTML file over in directory-b:

- directory-a/
  - libraries/
    - utils/
      - dist/
        - script.js
- directory-b/
  - index.html

If you want to go about importing script.js in index.html, the traditional way would be to go through the relative directory path:

<script src="../directory-a/libraries/utils/dist/script.js"></script>

Now that is a huge pain. Wouldn't it just be a lot easier if script.js existed in directory-b? We could copy it over, but what if I needed to work within the directory-a library and update script.js? Then I'd have to copy over the new version of the file.

Addressing this pain point is where symlinks come in.

To create our symlink, we simply need to run the following Linux command in our shell terminal:

ln -s <path to file/folder we want to link> <path to where we want that linked file/folder to be available>

So for the directory-a/ directory-b example above, I can run the following in directory-b:

ln -s ../directory-a/libraries/utils/dist/script.js ./

Having run this command I can now run:

ls

And voilà, script.js now shows up in directory-b. I can even go into Finder on my Macbook and see it:

Directory B's contents, with index.html and script.js, but script.js is aliased.

Most importantly, in my index.html file, I can eliminate that long relative folder path and just have:

<script src="./script.js"></script>

You'll notice that script.js is aliased, because it's not actually there, just linked (wait for it) symbolically to its actual source over in directory-a/libraries/utils/dist/. Now if that library changes and a new script.js is produced, it "auto-updates" wherever it is symlinked, so directory-b will always have the latest and greatest version of script.js, and you don't have to manually copy it over.

This is immensely powerful and useful if you are working in several different directories or services at once. I can offer a real world use case for this. At Sprout Social we have a few utility CSS libraries that are published as private NPM packages that get used in our frontend development. If I am working on a page that needs one of those CSS libraries to be changed, then normally I would have to update the CSS library, publish the new version of it on NPM, and then change the dependency in the repo where I'm using that library, and then install the new version before I could actually use that change. If I were testing out CSS changes in the library, at the same time I was building the page in the other repo, that workflow would get super annoying super quickly. Instead, I can symlink that CSS library, tell the working repo to use the symlink instead of the dependency installed from NPM, and be able to work on both at the same time easily.

As useful as symlinks are, they definitely have a lifecycle. If you don't clean up your symlinks every so often, you may run into issues in your development process. You can avoid this by removing your symlinks whenever you are done with them.

Before removing a symlink, you should check that the file you're looking to remove is, in fact, actually a symlink. You can do so with the following command:

ls -l <path to file you think is a symlink>

If I am looking to clean things up in directory-b, this would look like:

ls -l script.js

This command will tell you the properties of the specified file. If it is a symlink, the first letter of the entire file properties statement will be the letter l, and the file name will be followed by an arrow -> and the path to the source file, like: script.js -> ../directory-a/libraries/utils/dist/script.js.

Safe with the knowledge that we are actually removing a symlink, we can run the following command:

unlink <path to symlink>

So, still in directory-b, this would be:

unlink script.js

And now our symlink is gone and script.js cannot be seen either in Finder or by running ls. The file still exists over in directory-a/libraries/utils/dist/ though, should we need to symlink it again!

It's also worth calling out that the commands listed here represent just one way to manage symlinks in a Linux environment. There are other ways to do so in different environments or using different tools. For example, yarn has yarn link, which enables you to do the same kind of work as the basic Linux command.