Skip to main content Accessibility Feedback

How I structure my JavaScript projects in 2022

One of the things I get the most questions about from my students is about what the “best way” to structure code is.

The truth is, there is no best way. But I do have a series of conventions and rough guidelines that I follow. Today, I thought I’d share them with you.

Let’s dig in!

The JavaScript patterns I use

I have a small handful of JavaScript patterns I use, depending on the needs of the project.

I used to use revealing module patterns a lot more often, but these days, I tend to use ES modules instead (more on that in a bit).

The build tools I use

I used to use Gulp.js, and CodeKit before that.

Now, I’m a big fan of running NPM scripts directly. It gives me more control than CodeKit, but a much smaller set of dependencies (and less things breaking all the time) than Gulp.

Every single one of my projects now uses my Build Tool Boilerplate.

It’s setup to let me easily drop out the stuff I don’t need, and customize the stuff I do through a configurations object. It includes rollup.js for JavaScript, Sass for CSS, and a handful of SVG and image optimization tools.

I don’t use webpack, because it’s confusing and complicated. I also don’t use TypeScript, because it’s an added layer of dependencies, and solves problems I don’t personally have.

How I organize code within a file

I tend to maintain a specific structure to my files…

  • Variables at the top of the page
  • Functions and methods in the middle
  • Initializations and event listeners at the end

This makes it really easy for me to open any particular file and have a rough idea of how it’s organized and how to find what I’m looking for relatively easily.

// 
// Variables
// 

let name = 'Merlin';
let spells = {
	teapots: 'Dancing teapots', 
	fish: 'Turn into a fish'
};


//
// Methods
// 

/**
 * Cast the spell
 * @param  {String} spell The spell to cast
 */
function castSpell (spell) {
	alert(spell);
}


// 
// Inits & Event Listeners
// 

document.addEventListener('click', function (event) {
	castSpell(spells.fish);
});

I use JSDoc to document my code. Some text editors will use this to pull out information about functions when used in other places in your code, which is quite nice!

I maintain a similar structure within functions as well.

How I modularize and organize files

I’m a big fan of ES modules. They help me keep my code more structured and organized.

But I’ve also seen people go too modular for my liking, creating deeply nested file trees with each function in its own little file. This creates, in my opinion, a different kind of organizational challenge (that I’ve been guilty of myself).

To avoid doing this, I tend to start all of my projects as a single JavaScript file.

At some point, it may start to feel too big. I’m doing a lot of scrolling up-and-down, or I open the file a second time in another tab to easily reference different parts of it.

That’s usually my sign that it’s time to break things up a bit.

  • For JavaScript libraries, I organize my functions and files by what they do: event-listeners.js, dom.js, constructor.js, and so on.
  • For websites and apps, I tend to keep each library or discrete piece of functionality in its own file, and import them into files specific to the pages they’re needed on: search.js, table-of-contents.js, and so on.

I keep all of my build files in a src directory, and compile them with rollup.js and my Build Tools Boilerplate into a dist directory.

What did I miss?

That’s a rough overview of how I work, but I’m sure I missed some details.

Is there anything you’d like me to dig into more about my work setup that I didn’t cover in this article? Send me an email and let me know!