How I setup my vanilla JavaScript projects
I don’t use module loaders or bundlers like RequireJS, Webpack, and so on (for simplicity). I also don’t use the ES6 import
statement (for browser compatibility reasons).
As a result, one of the most common questions I get is how I set up my projects.
Today, I’m going to show you.
Standard caveat: This is the setup that works best for me personally. I’m not dogmatic about this. If you have a setup you use and like, keep at it! Let’s stop chasing tools and start making more cool stuff for the web.
Folder Structure
My typical project folder structure looks a bit like this…
my-app/
|—— dist/
| |—— css/
| | |—— main.css
| | |—— main.min.css
| |—— img/
| | |—— # image files
| |—— js/
| | |—— someStandaloneScript.js
| | |—— someStandaloneScript.min.js
| | |—— main.js
| | |—— main.min.js
| |—— svg/
| | |—— icons.svg
| |—— # other static assets
|—— src/
| |—— js/
| | |—— someStandaloneScript.js
| | |—— main/
| | | |—— atomic.js
| | | |—— smooth-scroll.js
| | | |—— fluid-vids.js
| | | |—— app.js
| | | |—— zzz_inits.js
| |—— sass/
| | |—— _config.scss
| | |—— _mixins.scss
| | |—— components/
| | | |—— _normalize.scss
| | | |—— _grid.scss
| | | |—— _typography.scss
| | | |—— _overrides.scss
| | |—— main.scss # imports config.scss, mixins.scss, and all components
| |—— static/
| | |—— img/
| | | |—— # image files
| | |—— # other static files and folders
| |—— svg/
| | |—— # svgs
|—— .travis.yml
|—— gulfile.js
|—— package.json
|—— README.md
Gulp.js
I use a custom Gulp.js configuration to manage all of my source files and build them into distribution/production files. It…
- Lints my CSS and JS.
- Concatenates and minifies my CSS and JS.
- Optimizes my SVG files
- Injects headers into the files with copyright info, version numbers, etc.
Here are my gulp configuration and package.json
files.
- Run
gulp
to run the build. - Run
gulp watch
to automatically run the build whenever you change a file.
I used to use CodeKit, which is still awesome. But the Gulp build let’s me more easily customize things and I’m finally comfortable enough with command line that I can use it reasonably.
The Details
All of my source code lives in the src
directory, and production code is in the dist
directory.
Sass
I use Sass mainly just for variables (I use variables for colors like $color-primary
and $color-secondary
, as well as breakpoints like $bp-small
, $bp-medium
) so that I can easily change a few things without doing a massive find-and-replace.
It also lets me keep my files modular and combine them into one file easily.
JavaScript
For JavaScript, any file directly under the js
directory is copied over to dist
as standalone files (linted and minified).
Any subdirectory in js
has its contents combined into a single file with the same name as the directory itself (ie. everything in js/main
is output to main.js
and main.min.js
).
To force certain files (polyfills, for example) to be included first, I prefix them with an underscore (_
). To force certain files to show up last (maybe some plugin initializations), I prefix them with zzz_
.
_closest.polyfill.js
_matches.polyfill.js
myPlugin.js
zzz_inits.js
Is it as fancy as a module loader? Of course not.
But it’s simple and it works. Every time.
SVGs
SVGs are run through SVGO to remove any junk and make them smaller (by quite a bit in some cases).
Configuration
There’s also an option in my gulp.js
file to turn on or off a bunch of features, including adding cache-busting to the minified files.
var settings = {
scripts: true, // Turn on/off script tasks
styles: true, // Turn on/off style tasks
svgs: true, // Turn on/off SVG tasks
images: true, // Turn on/off image tasks
docs: false, // Turn on/off documentation generation
cacheBust: false // Turn on/off cache busting (adds a version number to minified files)
};
When that’s turned on, it adds the version number to the file. So main.min.js
would instead by main.min.1.2.1.js
.
Including third-party scripts
I don’t really use any libraries and barely use third-party stuff. Anything I need to add I copy/paste or download from the Vanilla JS Toolkit or it’s GitHub repo, respectively.
I also add polyfill.io to basically every site I build these days. It just works, and its awesome.
I include it with a script
element in the footer. Those work just fine!