<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Cristian Tabacitu</title>
    <description>The latest articles on Forem by Cristian Tabacitu (@tabacitu).</description>
    <link>https://forem.com/tabacitu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F475142%2F9fb1939b-cabe-46c0-9655-187c897d1535.jpeg</url>
      <title>Forem: Cristian Tabacitu</title>
      <link>https://forem.com/tabacitu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/tabacitu"/>
    <language>en</language>
    <item>
      <title>You Might Not Need NPM: A Simpler Way to Load Assets</title>
      <dc:creator>Cristian Tabacitu</dc:creator>
      <pubDate>Tue, 27 Jan 2026 08:12:13 +0000</pubDate>
      <link>https://forem.com/tabacitu/you-might-not-need-npm-a-simpler-way-to-load-assets-3e6b</link>
      <guid>https://forem.com/tabacitu/you-might-not-need-npm-a-simpler-way-to-load-assets-3e6b</guid>
      <description>&lt;p&gt;A post of mine on LinkedIn blew up recently. I said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Hot take: NPM has done more harm to web development than good. It normalized treating 500MB of node_modules as "normal." It made devs forget how to write 10 lines of code because there's a package for that. It turned "Hello World" into a dependency tree with 847 packages. 15 years in web dev. I've seen the before and after. We traded simplicity for convenience, and got neither.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some people agreed. Some wanted my head on a plate. One person wrote "&lt;em&gt;worst take on LinkedIn today and this platform is chock-full of terrible takes&lt;/em&gt;". Another simply said "&lt;em&gt;spoons made me fat&lt;/em&gt;" - liked that one - fair enough! 😅&lt;/p&gt;

&lt;p&gt;This article isn't about being right. It's about showing that &lt;strong&gt;alternatives exist&lt;/strong&gt; - simpler ways to build web apps that some people might not know about. Everything here is opinion, and relates specifically to how NPM is used for front-end development (loading CSS, JS, and other assets in your web app). Not server-side JavaScript - that's a different conversation.&lt;/p&gt;

&lt;p&gt;Let's dive in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Let Me Be Fair: What NPM Did RIGHT
&lt;/h2&gt;

&lt;p&gt;Before I start throwing punches, let me give credit where it's due. Before NPM, things were... rough.&lt;/p&gt;

&lt;p&gt;Remember loading jQuery from a CDN and hoping it was still there next month? Remember manually downloading zip files, extracting them, and copying files to your &lt;code&gt;/js&lt;/code&gt; folder? Remember having three different versions of the same library because you couldn't keep track? I do. It wasn't fun.&lt;/p&gt;

&lt;p&gt;NPM solved real problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dependency management&lt;/strong&gt; - You could finally declare what you needed and get it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versioning&lt;/strong&gt; - Lock files meant reproducible builds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discoverability&lt;/strong&gt; - A central place to find and share packages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community&lt;/strong&gt; - Developers could build on each other's work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NPM helped JavaScript grow from "&lt;em&gt;that language for image rollovers&lt;/em&gt;" to... well, everything. It enabled an entire ecosystem. And for large teams working on complex applications, it provided structure that was genuinely needed.&lt;/p&gt;

&lt;p&gt;So yes, NPM did good things. A lot of good things. Let's acknowledge that.&lt;/p&gt;




&lt;h2&gt;
  
  
  But Let's Also Be Honest: What Went Wrong
&lt;/h2&gt;

&lt;p&gt;Here's where it gets spicy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 500MB node_modules folder became "normal."&lt;/strong&gt; A fresh &lt;code&gt;create-react-app&lt;/code&gt; can easily have 200MB+ of dependencies. For a Hello World (granted using a huge framework, but that's the problem - using huge frameworks for anything even presentation websites is now &lt;em&gt;normal&lt;/em&gt;). Someone in my LinkedIn comments said "&lt;em&gt;500MB? Gotta get those numbers up. If it's not 3GB+ it's probably just another todo list app&lt;/em&gt;". Funny because it's true.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency trees went insane.&lt;/strong&gt; 847 packages for a simple app isn't a joke - it's reality. Each package has dependencies, which have dependencies, which have dependencies... You're not just trusting one maintainer, you're trusting hundreds. Thousands, even.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The left-pad incident happened.&lt;/strong&gt; In 2016, one developer unpublished an 11-line package from NPM, and broke thousands of projects worldwide - including Facebook and Netflix. Eleven. Lines. Of code. That could have been written in 2 minutes. But it had millions of downloads because... why write 11 lines when there's a package? I truly hope that AI will prevent people from using such small packages nowadays.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build tools became mandatory.&lt;/strong&gt; Webpack. Then Webpack was too slow, so Vite. Then whatever comes next. Each with its own config files, its own learning curve, its own quirks. Developers just wanted to load a CSS file. Instead, they got a 200-line webpack config and a PhD in module bundling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security vulnerabilities multiplied.&lt;/strong&gt; Every dependency is a potential attack vector. Supply chain attacks are real - malicious code has been found in NPM packages. When you have 847 packages, you have 847 potential problems.&lt;/p&gt;

&lt;p&gt;Now, before you write that angry comment... I know what you're going to say.&lt;/p&gt;




&lt;h2&gt;
  
  
  "It's Not NPM's Fault, It's the Developers!"
&lt;/h2&gt;

&lt;p&gt;I heard this a lot in the LinkedIn comments. And honestly? &lt;strong&gt;You're partially right.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One commenter said: "&lt;em&gt;Don't blame NPM for stupid developer discipline. The same bloat happens in any ecosystem with weak discipline.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;Another: "&lt;em&gt;NPM didn't remove the importance of architectural awareness, it made it easier to ignore it.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;And my favorite: "&lt;em&gt;spoons made me fat&lt;/em&gt;".&lt;/p&gt;

&lt;p&gt;Fair. The tool isn't inherently evil. Developers made choices. They installed &lt;code&gt;is-odd&lt;/code&gt; instead of writing &lt;code&gt;n % 2 !== 0&lt;/code&gt;. They added React to a landing page. They chose complexity when simplicity would've worked.&lt;/p&gt;

&lt;p&gt;But here's the thing: &lt;strong&gt;tools shape behavior&lt;/strong&gt;. NPM made it &lt;em&gt;so easy&lt;/em&gt; to add dependencies that we stopped asking if we should. The friction to add a package became zero. And when there's no friction... things get out of hand.&lt;/p&gt;

&lt;p&gt;The ecosystem encouraged this. Package count became a badge of honor. "&lt;em&gt;Look how many downloads my package has!&lt;/em&gt;" Tutorials said "&lt;em&gt;just npm install this&lt;/em&gt;". Nobody asked "&lt;em&gt;do you really need this?&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;So yes, it's the developers. But it's also the system that enabled and encouraged it. Both can be true.&lt;/p&gt;




&lt;h2&gt;
  
  
  Even the Creator of Node.js Has Regrets
&lt;/h2&gt;

&lt;p&gt;This isn't just me being grumpy. Ryan Dahl - the guy who &lt;em&gt;created&lt;/em&gt; Node.js - gave a famous talk called "&lt;em&gt;10 Things I Regret About Node.js&lt;/em&gt;". He talked about security, the module system, and yes... how things got complicated.&lt;/p&gt;

&lt;p&gt;He went on to create Deno, which takes a fundamentally different approach: importing directly from URLs, no &lt;code&gt;node_modules&lt;/code&gt; folder, security by default. It's not a 1:1 replacement, but the philosophy is clear: &lt;strong&gt;simpler is better&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the person who started this whole thing thinks the ecosystem went off the rails... maybe it's worth listening?&lt;/p&gt;




&lt;h2&gt;
  
  
  Simpler Alternatives Exist
&lt;/h2&gt;

&lt;p&gt;Here's the part people don't know about. There &lt;em&gt;are&lt;/em&gt; genuine alternatives. Different tools and approaches that let you avoid (or minimize) the NPM complexity. Granted these are runtimes, libraries or techniques, not drop-in replacements, but that's the point - it's possible the change has to be structural:&lt;/p&gt;

&lt;h3&gt;
  
  
  Deno
&lt;/h3&gt;

&lt;p&gt;Created by the guy who made Node.js, as mentioned. &lt;a href="https://deno.com/" rel="noopener noreferrer"&gt;Deno&lt;/a&gt; encourages you to import directly from URLs, has no &lt;code&gt;node_modules&lt;/code&gt;, built-in TypeScript. And it's at v2.6 already!&lt;/p&gt;

&lt;h3&gt;
  
  
  Bun
&lt;/h3&gt;

&lt;p&gt;A faster JavaScript runtime that's compatible with most NPM packages. &lt;a href="https://bun.com/" rel="noopener noreferrer"&gt;Bun&lt;/a&gt; still has &lt;code&gt;node_modules&lt;/code&gt;, but it's much faster at installing and running things. Different philosophy than Deno.&lt;/p&gt;

&lt;h3&gt;
  
  
  Import Maps (Native Browser Feature)
&lt;/h3&gt;

&lt;p&gt;Modern browsers now support &lt;a href="https://www.honeybadger.io/blog/import-maps/" rel="noopener noreferrer"&gt;import maps&lt;/a&gt; - a way to map package names to URLs directly in HTML. You can load JavaScript modules from CDNs without any build step at all. It's built into the browser spec.&lt;/p&gt;

&lt;h3&gt;
  
  
  CDN-Based Loading (esm.sh, unpkg, Skypack)
&lt;/h3&gt;

&lt;p&gt;You can load ES modules directly from CDNs in your browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;confetti&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://esm.sh/canvas-confetti&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;confetti&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No NPM. No build step. Just works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basset (for Laravel)
&lt;/h3&gt;

&lt;p&gt;This is what I built with my team for Laravel apps. More on this below.&lt;/p&gt;

&lt;p&gt;Each of these approaches has tradeoffs. None is perfect. But they exist! And for many projects, they might be exactly what you need.&lt;/p&gt;




&lt;h2&gt;
  
  
  Basset: The Laravel Approach
&lt;/h2&gt;

&lt;p&gt;Okay, let me tell you about &lt;a href="https://github.com/Laravel-Backpack/basset" rel="noopener noreferrer"&gt;Basset&lt;/a&gt;. It's a package we built for Laravel that takes a simple approach to the asset problem.&lt;/p&gt;

&lt;p&gt;The concept is dead simple: &lt;strong&gt;instead of using NPM to download packages, just reference the CDN URL directly - and Basset will download and cache that file on your server.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{-- Instead of npm install + importing + bundling... --}}

{{-- Just do this: --}}
@basset('https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css')
@basset('https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Basset will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download the file from the CDN&lt;/li&gt;
&lt;li&gt;Store it on your server (so you don't depend on the CDN being up)&lt;/li&gt;
&lt;li&gt;Serve it locally on all subsequent requests&lt;/li&gt;
&lt;li&gt;Make sure it's only loaded once per page (no duplicates)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No &lt;code&gt;node_modules&lt;/code&gt;. No &lt;code&gt;package.json&lt;/code&gt;. No webpack. No Vite. No build step. Just... assets. The way it used to be, but with some modern conveniences.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is it similar to what Deno does?
&lt;/h3&gt;

&lt;p&gt;Philosophically, yes - both say "&lt;em&gt;use URLs instead of package managers&lt;/em&gt;". But technically, they're different beasts. Deno is a JavaScript runtime for server-side code. Basset is a Laravel helper for front-end assets. Same philosophy of simplicity and URL-based loading, different implementation and use case.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Numbers
&lt;/h3&gt;

&lt;p&gt;Basset has been around since March 2023. It has &lt;strong&gt;750k+ downloads&lt;/strong&gt; on Packagist. We've been using it in production on Backpack for Laravel and countless client projects. It's not experimental - it's battle-tested.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Basset is NOT
&lt;/h3&gt;

&lt;p&gt;Let me be clear about the limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It's not a package manager.&lt;/strong&gt; It doesn't handle dependencies between packages. It just loads files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's not for server-side JavaScript.&lt;/strong&gt; If you're building Node.js apps, this isn't for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's not for complex SPAs.&lt;/strong&gt; If you're building a React/Vue/Angular app with 50 components, you probably need a real build system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It can't save you from yourself.&lt;/strong&gt; If you cache assets at the wrong time (like only in production, when a CDN can be down), you can still break things.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For complex JavaScript applications with lots of interactivity and client-side routing, you probably still need a build system. Basset is for the &lt;strong&gt;other 80% of web apps&lt;/strong&gt; - the ones that are mostly server-rendered with some JavaScript sprinkled on top.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is This For You?
&lt;/h2&gt;

&lt;p&gt;Ask yourself:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Basset might be great if you:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build Laravel apps (Backpack or not)&lt;/li&gt;
&lt;li&gt;Are a backend developer who dreads touching npm&lt;/li&gt;
&lt;li&gt;Have simple front-end needs (a few libraries, some interactivity)&lt;/li&gt;
&lt;li&gt;Want to load assets from CDNs but also want them cached locally&lt;/li&gt;
&lt;li&gt;Value simplicity and maintainability over "modern" tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❌ Basset probably isn't for you if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're building complex SPAs with React/Vue/Angular&lt;/li&gt;
&lt;li&gt;You need advanced code splitting and lazy loading&lt;/li&gt;
&lt;li&gt;You're working on a large team that already has npm pipelines&lt;/li&gt;
&lt;li&gt;You need server-side JavaScript (Node.js, Deno, Bun)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't a "&lt;em&gt;NPM bad, Basset good&lt;/em&gt;" argument. It's about &lt;strong&gt;using the right tool for the job&lt;/strong&gt;. And for many jobs, a simpler tool works just fine - that's what 15 years of web dev have taught me.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: Spoons, NPM, and Making Choices
&lt;/h2&gt;

&lt;p&gt;Look, the commenter was right: "&lt;em&gt;spoons made me fat&lt;/em&gt;" is a valid response to my original take. Tools don't force us to make bad decisions. We do that ourselves.&lt;/p&gt;

&lt;p&gt;But we also get to choose our tools. And sometimes, choosing a simpler tool leads to simpler outcomes.&lt;/p&gt;

&lt;p&gt;NPM revolutionized web development. It also complicated it. Both things are true. The question isn't "&lt;em&gt;is NPM bad?&lt;/em&gt;" - it's "&lt;strong&gt;do I need NPM for this project?&lt;/strong&gt;"&lt;/p&gt;

&lt;p&gt;For a lot of Laravel projects - especially admin panels, CRUD apps, marketing websites with some interactivity - the answer might be "no". You might not need 500MB of &lt;code&gt;node_modules&lt;/code&gt;. You might not need a build step. You might be able to just... load assets from URLs and be done with it.&lt;/p&gt;

&lt;p&gt;If that sounds appealing, &lt;a href="https://github.com/Laravel-Backpack/basset" rel="noopener noreferrer"&gt;give Basset a try&lt;/a&gt;. It's free, it's open-source, and it might just make your life a little simpler.&lt;/p&gt;

&lt;p&gt;Or don't! Use NPM. Use Vite. Use whatever works for you. I'm not here to convert anyone. I'm just here to say: &lt;strong&gt;alternatives exist&lt;/strong&gt;. And it's worth knowing about them.&lt;/p&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;

&lt;p&gt;Cheers! 🍻&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>webdev</category>
      <category>npm</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
