I’ve been working on our build tools at work. Our tools were somewhat outdated, and we were wanting to move away from Grunt. I ultimately decided to go with npm scripts (although the speed of Gulp was tempting). Now that I’m wrapping up, I wanted to write down some notes for things that took a bit of research to figure out.
If you are looking for a complete walkthrough on setting up npm scripts as build tools, here are some articles that helped me:
- Why npm Scripts?
- Helpers and tips for npm run scripts
- Comparison of npm scripts vs Gulp
- Why I Left Gulp and Grunt for npm Scripts
- Using Npm Scripts as a Build Tool
Reusing an npm script with additional options
You can reduce duplication by reusing scripts and adding --
and then additional options (e.g -- --flag
). In the example below, I have a script to build my CSS files with Sass. Then I have a script that watches my Sass files for changes by running the same build script with the --watch
option.
"build:css": "node-sass --output-style expanded --precision 6 src/css -o build/css"
"watch:css": "npm run build:css -- --watch"
Using config variables in package.json
If you are building scrips for use on a single platform, then using configuration variables in the package.json
file is easy. It gets a bit more complicated when trying to make scripts that work for both Mac/Unix and Windows, because Windows needs a different format for the variables ($npm_package_name
for Mac/Unix and %npm_package_name%
for Windows).
The best way I found to get around this obstacle is to use the cross-env
package. I use the cross-env-shell
feature to run the scripts using config variables. You can access any values in the package.json
file by adding $npm_package_
to the name (e.g. $npm_package_name
).
{
"name": "my-package",
"config": {
"src": {
"path": "src",
"cssPath": "src/css"
},
"build": {
"path": "build",
"cssPath": "build/css"
},
"scripts": {
"build": ""cross-env-shell 'sass -s expanded --no-source-map $npm_package_config_src_cssPath:$npm_package_config_build_cssPath'""
}
}
}
Using cross-env-shell
with copyfiles
I used the copyfiles
package to copy static assets from the source directory to the build directory. I had trouble getting this to work with cross-env-shell
at first when using something like this:
"copy": "cross-env-shell \"copyfiles -u 1 -e \"$npm_package_config_src_path/**/*.{scss,js}\" \"$npm_package_config_src_path/**/*\" $npm_package_config_build_path\""
At some point, I realized that I could use cross-env-shell
with single quotes instead of using escaped double quotes (\"
) as they show in the cross-env
documentation. Switching to single quotes made everything work again:
"copy": "cross-env-shell 'copyfiles -u 1 -e \"$npm_package_config_src_path/**/*.{scss,js}\" \"$npm_package_config_src_path/**/*\" $npm_package_config_build_path'"
Using package.json
variables in a webpack config
The package.json
values and variables can be accessed inside a webpack config. Just import the file at the top of the config.
const PACKAGE = require('./package.json')
module.exports = {
entry: `./${PACKAGE.config.src.jsPath}/${PACKAGE.name}/${PACKAGE.name}.js`
}
npm rum
I made one happy little discovery from a typo: npm rum
works just the same as npm run
. 🍹