A while back, I built a custom .node loader for Next.js. Older versions of Next.js didn't handle .node modules very well, and the built-in Node loader wasn't helpful due to the framework's unique way of managing assets. During this time, I also participated in a discussion in the Next.js community about how best to support native modules in the framework.

For a time, my loader was a practical solution, and I'm grateful to all the projects that adopted it. While I only received 16 stars on GitHub, it still feels pretty awesome to know that major projects like FastGPT and Supabase used it. I might not have 15,000 stars, but hey, it feels like I do! 😄

However, with recent versions of Next.js, you no longer need this custom loader. The solution is much simpler now. To work with native modules in the current Next.js, you just need to update your configuration like this in 14:

  experimental: {
    serverComponentsExternalPackages: ['yournativemodule'],
  },
const nextConfig = {
  serverExternalPackages: ["yournativemodule"],
};

In version 15, option is part of default configuration

As one user mentioned in this GitHub issue, Next.js now provides native support for external packages in server components, which eliminates the need for the custom loader I originally built.

If you've got a dependency that's built with neon bindings like I do, you have one additional step. I don't know why it doesn't work out of the box like it does for other native modules, but try:

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ['msnodesqlv8','robotjs', 'node-el-slugify'],
  },
  /** @type {import('webpack').Configuration} */
  webpack: (config, context) => {
    if (context.isServer) {
      config.externals = [
        ...config.externals,
        {'node-el-slugify': 'commonjs node-el-slugify'},
      ]
    }
    return config;
  },
};

export default nextConfig;

node-el-slugify was the problematic one

This configuration tells Webpack to treat node-el-slugify as an external module and not bundle it. This resolves my issue of module not found.

Gratitude for the Open Source Community

I want to take a moment to thank everyone who reported issues and provided feedback over the course of this project. Your input is invaluable, and contributing to open source has always felt like a rewarding experience.

While the community feedback is gratifying, maintaining open-source libraries as a solo contributor comes with its own set of challenges, which I'd like to touch on.

A Shift in Focus: The Reality of Maintaining Open Source Libraries

One issue many open-source maintainers face is sustainability. Over time, I’ve created several open-source libraries, and as a sole maintainer, the challenge of keeping up with user demands and evolving project needs can be overwhelming.

When only one person maintains a project, it often becomes difficult to keep up with the demands of users and the project's evolving needs. There's also the reality that, as my own needs change, I may no longer rely on or actively use the library. When that happens, my attention to the project naturally dwindles, and responses to issues or pull requests can become delayed. It's not that I don't care — it’s just that balancing a full-time job with open source is tough. Two weeks might go by before I even see an issue report, and for that, I apologize.

Benefit of open sourcing

Even with the challenges, open source has its rewards. As I mentioned, feedback from the community is very much rewarding - stars, commits, issue reports. You don't get paid in money, but it's not all about the money. One often overlooked perk is the direct exposure to startups that might reach out to you with job offers. They find your library useful, review your code, and recognize you as a good technical fit. That's right, the startups reach out to you directly, rather than through recruiters. Personally, I always have a higher appreciation for companies that approach me directly rather than through intermediaries.

In my experience, recruiters tend to rely on checklists to determine if you meet the requirements for a role. I'm taking Python for example. It can be any other language position.

For instance, a Python position might require >=5 years of experience. How do you quantify that? If you’ve used Python on and off or as a secondary language in your projects? What if your experience comes from side projects, open source contributions, or a library you built? Even if you haven’t used the language in a professional setting, these experiences still demonstrate your technical abilities. But they don’t always fit neatly into a recruiter’s checkbox.

Another challenge is the endless rounds of interviews. I know they're important, but they're also exhausting. I'll stop here on this topic, as it’s outside the scope of this post. To sum it up - receiving a direct message from a company itself is cool!

Encouraging Contributions to Your Open Source Projects

Throughout my experience with open source, I’ve been fortunate to receive contributions, ranging from detailed issue reports with reproducible test cases to actual commits. I still remember my excitement when someone contributed to the Rust crate I built for Actix, just a few days after I published it.

If you want contributions, make it clear in your repository’s README.md. Here's the same boilerplate I use in all my repositories (except in the Next.js .node loader, which I forgot to update).

To make your project contribution-friendly:

  1. Add a contributing section: Include it in your README.md, and link to a contributing guide and a code of conduct (optional). This helps set clear expectations.
  2. Update your CONTRIBUTING.md: Be specific about the kind of help you’re looking for.
  3. Consider adding a code of conduct: This is optional, but GitHub provides community guidelines, and in my experience, most people I’ve interacted with on GitHub are nice.
opensource contribution guidelines

The Responsibility and Dilemma of Package Deprecation

As much as I value the libraries I’ve built, it’s important to recognize when a project needs to be deprecated. Managing multiple projects as a solo contributor is tough, and sometimes stepping back is necessary. I’m not proud that some of my repositories are neglected, but I know it’s my responsibility to decide their future.

So, how does one gracefully deprecate an npm package? Here’s a quick guide for those of you in the same boat:

  • Mark the package as deprecated:
npm deprecate your-package-name@"<version>" "This package is no longer maintained. Please use [alternative package] instead."

# check it 
npm info your-package-name@<version>
  • Update documentation: Make it clear in the README that the package is deprecated and suggest alternatives or explain the reason for deprecation.
  • Thank your users: It's polite to acknowledge the community's involvement and support.
  • Archive the repository: On GitHub you can archive the repository to indicate that it’s no longer actively maintained.

Maintaining open source projects is rewarding, but it’s also challenging if you're a solo maintainer. Balancing personal life, work, and community expectations can be tough, but as long as you’re transparent with your users and provide alternatives, stepping back when necessary is okay.

Recently, I’ve shifted my focus toward demo projects rather than creating new libraries. These demos are simple solutions to common problems that don't necessarily need a dedicated library. They offer practical ways to solve issues, like migrate your expo sqlite database, how to publish a monorepo etc.