They mostly come at night; mostly.
Express + React + Babel + Webpack + Prettier + ESLint + Jest + Puppeteer
mostly is a full-stack web application starter kit built on Node.js. It uses Express for the server and React for the user interface.
Its purpose is to serve as a lightweight, easy-to-comprehend starting point, with a focus on providing a great developer experience while helping you get high quality and maintainable apps deployed rapidly.
Nothing is hidden, nothing is magical, and all of the "plumbing" is accessible and relatively simple.
- Uses a minimal set of UI development tools (via React and CSS modules)
- Uses a familiar Node.js HTTP server library (via Express)
- Lets you use the latest and greatest ECMAScript everywhere (via Babel)
- Provides a fast development workflow (via hot-reloading on the client and server)
- Helps you write unit, functional, and end-to-end tests with ease (via Jest and Puppeteer)
- Keeps your code clean and consistent (via Prettier and ESLint)
- Gives you simple dev, test, build, and deploy scripts (via NPM and bash)
- Runs on Node.js v6+ (via Babel runtime)
Clone the repository:
git clone --depth=1 https://github.com/justinsisley/mostly.git your-project-name
Initialize your own repository:
$ cd your-project-name
$ rm -rf .git && git init
Install dependencies:
$ npm install
Configurations for Babel, ESLint, lint-staged, and prettier are contained within the package.json
file.
Configurations for Webpack can be found in the scripts/config
directory.
Configuration for CircleCI is contained in the .circleci/config.yml
file.
Run the application in development mode:
npm run dev
Note: The dev server runs on port 3320 by default. Feel free to change it in
scripts/config/webpack.dev.js
.
Run unit and functional tests:
npm test
Note: Both test suites will run concurrently. End-to-end tests will not be run.
Run unit tests:
npm run test:unit
Note: Jest will run any file that matches the following pattern:
src/**/__tests__/unit.js
Run functional tests:
npm run test:func
Note: Jest will run any file that matches the following pattern:
src/**/__tests__/func.js
Run end-to-end tests:
npm run test:e2e
Note: Jest/Puppeteer will run any file that matches the following pattern:
src/**/__tests__/e2e.js
Run a test suite in watch mode:
npm run test:unit -- --watch
# or
npm run test:func -- --watch
Note: This option is simply passing the
watch
option directly to Jest. End-to-end tests do not support thewatch
option.
Run the unit test suite and generate a coverage report:
npm run test:unit -- --coverage
Note: Like
watch
, this option is passing thecoverage
option directly to Jest. Functional and end-to-end tests do not support thecoverage
option.
Create a static build:
npm run build
Note: This script will use Babel and Webpack to compile code within the
src
directory into adist
directory.
Run the application in production mode:
npm start
Note: This script requires you to first create a build by running
npm run build
.
The production application will run on port 3325 by default. If you'd like to run it on another port, use the PORT
environment variable. For example:
PORT=8080 npm start
Deploy to now.sh:
npm run deploy
Note: now.sh is one of the quickest and easiest ways to get your app deployed. It also offers a free plan. Nevertheless, like every other part of this starter kit, I encourage you to modify
deploy.sh
to suit your needs.
This starter kit is pre-configured with a git pre-commit hook, which will automatically clean up your staged code using Prettier and ESLint, then execute your unit and functional tests. This is done using lint-staged and husky.
You can modify the pre-commit workflow using the lint-staged
property in package.json
and the scripts/precommit.sh
file.
CircleCI was chosen as the continuous integration provider because it's one of the more popular CI's in use across GitHub and it offers a free plan.
No matter which CI you decide to use in the long run, the configuration is code-based, which should make it relatively easy to migrate if and when you decide to use another provider.
For information about setting up your repository in CircleCI, sign up for a free account, then check out the documentation.
Once you've set up your repository in CircleCI, you'll need to get a token from now.sh in order to automate your deployment. Once you've got your token, add it to your CircleCI project as an environment variable named NOW_TOKEN
.
Now, when you push new commits, CircleCI will run the lint
, test:unit
, test:func
, and test:e2e
scripts, then deploy your app to now.sh with zero downtime using the deploy
script.
It'll be up to you to configure a custom domain, promote from staging to production, etc., but this configuration gets you most of the way there; mostly.
This project is the successor of another project, clear. I considered making this the v2
of clear but decided that because mostly handles client-side web application development as well as server development, it would not be in line with clear's raison d'être.
It's still "clear", in this context meaning "straightforward", but there's some additional complexity, therefore it's mostly clear.
I told you at the start of this that there's no magic, so try not to be too disappointed.
That's not a question, but ok. It's a line from the movie Aliens and was made humorous by South Park.
No. I have no affiliation with either of those companies. In fact, at the time of first publishing this project, they're both new to me.
Bottom line: they're both free to use until you need to scale, and they're both very easy to work with. That puts them in perfect alignment with the purpose of this project.
I've used several other end-to-end testing frameworks, and I've used them on one-person "teams", in small and medium-sized startups, and in large engineering organizations. In my experience, I've seen several themes repeat themselves:
- Adding another test framework and/or assertion library does not lend itself to increased velocity or a better developer experience.
- Choosing a single assertion library for all types of tests, if possible, leads to higher-quality testing, as teams build cohesive expertise over time.
- If tests aren't easy to write, they tend to be avoided*.
- If tests are brittle, they tend to be avoided*.
*Avoided, in this context, means not written, not maintained, not trusted, not run regularly, or any combination thereof.
Due to these experiences and observations, I've become a fan of Jest, as it contains the test runner, the assertion library, and the code coverage utility all in one easy-to-use package.
I've also become a fan of Puppeteer, especially when combined with jest-puppeteer, as it allows me to easily automate Chrome while writing the exact same style of assertions I use for my unit and functional tests.
Is Puppeteer perfect? Of course not. For one, it's built on Chrome/Chromium, so you're not getting multi-browser testing like some other libraries. Nevertheless, the API is straightforward and easy-to-use, and when combined with jest-puppeteer, it creates a good enough developer experience that I end up writing a more complete end-to-end test suite, which ultimately boils down to a more trustworthy codebase and a more reliable product being delivered to the end user.
Absolutely. It's quite likely that there are better libraries than what this project is using, and if that's the case, please open an issue, or better yet, a PR.
If your suggestion truly improves and/or simplifies this project, there's a strong guarantee it will make the cut.
There's a redux branch, but in addition to redux, it uses react-redux, redux-thunk, and redux-actions, so it's a bit more opinionated in library choice, architecture, and configuration.
It's also configured to use Redux DevTools, which can be quite useful during development and debugging.
For this project, I just don't think it's necessary. The install steps are relatively simple, and three shell commands get you the most up-to-date starter kit checked out in a brand new repository.