A lot of the projects that I work with use a fairly standard setup of tools and scripts. Rather than reinstall them every time and have to fix paths and install dependencies outside the Node ecosystem I've created a script that will perform the following actions:
- Check if
package.jsonexists. If it doesn't then create one with default values
- Install packages explaining what it's doing when installing each group
- Run an additional script that will create configuration files
- Remove the .git directory and recreate it for the current directory
This way I can initialize a new project using 2 files that will create a reproducible starting point yet retaining a degree of flexibility.
That's why we don't force an ESLint configuration. If I'm writing React I'll use Airbnb preset as it is geared towards working with React. For most other projects I'll use Google's preset; it is what I became comfortable with when developing PWA content and I think it's still the one that makes most sense.
There are two directories and a file that I've included to use for my type of projects. I create a
src directory with the structure of files that I will use in the Gulpfile.
The first thing we do is check if there is a
package.json file in the directory we're running the script in. If there is one we exit. I'd rather not overwrite the file that is there.
If there isn't one we initialize a default package.json file that we'll install packages to.
echo "Checking if package.json exists"
if [ -f package.json ]
echo "package.json exists."
echo "package.json doesn't exists... creating"
npm init --yes
The rest of this script installs different sets of packages. I will only highlight any specifics that I think are important.
echo "installing NPM packages "
echo "Installing Gulp 4.0 and load-plugins"
npm i -D gulp@next gulp-load-plugins
The first big change I've made is to fully embrace Gulp 4.0. I will modify the file to take into account the new methods it uses.
echo "Installing PostCSS and related plugins"
npm i -D postcss autoprefixer cssnano gulp-postcss
echo "Installing Babel Core and Preset Env"
npm i -D @babel/core @babel/preset-env
echo "Installing Browser Sync"
npm i -D browser-sync connect-history-api-fallback
echo "Installing ESLint"
npm i -D eslint gulp-eslint
It's important to notice that we're only installing eslint. We'll handle the preset installation later
echo "Installing SASS and related plugins"
npm i -D gulp-sass gulp-sourcemaps
echo "Installing critical and uncss"
npm i -D critical uncss
echo "Installing Remarkable and related plugins. I use Remarkable and associated plugins to generate production-ready HTML"
npm i -D remarkable gulp-remarkable gulp-wrap
I use Markdown as my authoring tool. I then use
gulp-remarkable to convert it to HTML and
echo "Installing miscelaneous plugins"
npm i -D gulp-concat gulp-debug gulp-exec gulp-run gulp-size
echo "The following plugins are optional. "
echo "Installs Google Cloud utilities to upload content to google cloud storage. Including gulp-gzip for compression. Separating them to make sure this is still the best option"
npm i -D gulp-gcloud-publish gulp-gzip
The original project created PDF assets that were the uploaded to a Google Cloud storage bucket. I haven't decided if I want to continue using GCloud Storage that way or if I want to move to Firebase hosting instead.
echo "Utility Opentype adds classes for using Opentype font options"
npm i -D utility-opentype
echo "Cheerio provides the means to query HTML and XML structures from a Gulp file."
npm i -D cheerio
echo "Axe is an accessibility evaluation tool."
npm i -D gulp-axe-webdriver
echo "Evaluates your node_modules file for vulnerabilities. This is the tool that NPM runs when using npm audit."
npm i -D gulp-snyk snyk
echo "External Dependecies Required"
echo "SASSDoc and SCSS Lint depend on external Ruby dependencies."
npm i -D sassdoc scss-lint gulp-scss-lint gulp-scss-lint-stylish
echo "Running configuration script"
Rather than make the script longer than it needs to be I call a second script to do configuration. This script is more complex and uses some Bash tricks.
# Configure ESLint
echo "ESLint configuration"
if [ -f .eslintrc.js ]
echo ".eslintrc.json exists."
echo ".eslintrc.json not found. Creating... "
echo "Please answer the questions below:"
npx eslint --init
.eslintrc.js file exists then we tell the user and exit. If it doesn't exist then we run
npx eslint --init to configure eslint based on our preferences and the needs of the project.
# Creating .babelrc file
if [ -f .babelrc ]
echo ".babelrc exists"
echo "creating .babelrc"
cat > .babelrc <<- "EOF"
"browsers": ["last 2 versions", "safari >= 7"]
Configuring babel is slightly different. We test like we did with ESLint. When it doesn't then we create the file using the
touch command and then append the content of the file.
# Create and populate .editorconfig
if [ -f .editorconfig ]
echo ".editorconfig exists"
echo ".editorconfig doesn't exist"
cat > .editorconfig <<- "EOF"
root = true
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
# Use 4 spaces for the Python files
indent_size = 4
max_line_length = 80
# The JSON files contain newlines inconsistently
insert_final_newline = ignore
indent_style = ignore
insert_final_newline = ignore
# Makefiles always use tabs for indentation
indent_style = tab
# Batch files use tabs for indentation
indent_style = tab
trim_trailing_whitespace = false
editorconfig provides a standard way to tell your editor how to behave. The (defacto) standard is supported by most modern text editors.
The file we're adding to the project is a basic default that we can use for most projects. Check the website for additional information.
# Git configuration has to be the last step to make sure
# that we get all the files we want are committed to the repo
echo "Reseting GIT configuration.Because I downloaded this as a Git Repo clone I want to remove it and start over"
echo "If you're working with an existing project this may loose your project's history"
echo "Removing .git directory"
rm -rf .git
echo "creating empty git repository"
echo "creating .gitignore"
echo "adding node_modules and shell files to .gitignore"
echo "node_modules" >> .gitignore
echo "install.sh" >> .gitignore
echo "configure.sh" >> .gitignore
echo "adding files to repository"
git add .
echo "commit initial files"
git commit -am "initial commit"
Working with Git in this setup is the last step in the process. It is important to note that if you're working on an existing project this will blow up your project's local history.
The first step of the process is to remove the existing
.git directory. I choose to do it tto make sure that the next steps are done on what, for Git, is a clean repository.
Next we create a
.gitignore file and add the files we don't want to upload to Git. In this case I've chosen not to upload the shell (
configure.sh files and the
Then we add the files to the repository and commit them. All that is left is to push them to your Git or Github repo.