Having the same robust environment used across the team on different projects increases consistency, wipes out repetitive work, reduces chances of forgetting important details, increases quality and fosters productivity.
This article will guide you to setting up your own JS dev environment
- Built-in terminal. This keeps you in a single window.
To be used in demo: VS Code
One way to maintain consistency across the different IDEs is through editorconfig. Creating a file named .editorconfig in the root of your directory helps you define common settings like tabs/spaces.
Every popular language has a package manager to manage the process of installing, upgrading, deleting packages (reusable piece of software that can be downloaded) in a consistent manner.
To be used in demo: npm
Development Web Server.
It is simple, lightweight and requires no configuration. You can start the server with a single command and it serves the current directory.
Also lightweight and supports live-reloading capabilities. This means your changes are immediately visible anytime you hit save.
Also considered lightweight and is much more comprehensive and has more features than the above two. It is also highly configurable, it is not only used with static files. You can fire up complex APIs with Express.
One advantage of Express is that you can use it in production as well. This means you can have a common configuration and use it in all environments.
If you use Webpack as your bundler, you can use its already built-in server. Advantage to this is you avoid pulling in another dependency. It is also fast since it serves from memory and does not require generating any physical files. Supports hot-reloading.
Depending on the bundler you use (Browserify, Webpack) there are dev server options for each.
One of the compelling features of Browsersync is that it automatically sets up a dedicated IP address over a network. This means anyone with the address can be able to view your app. When you hit the IP in multiple devices, all the instances of the app remain in sync. Pretty cool. This is great for cross-platform/device testing, just to ensure everything is rendering properly.
Browsersync can also integrate with Webpack, Gulp, Browserify, Express etc. You can use BrowserSync independently as a dev server, or as a platform to integrate to your existing dev server and add additional features.
All the above dev server options with the exception of Express are only used in development environment in your local machine.
To be used in demo: Express.
Automation is bliss in every developer’s workflow. It ensures consistency, rapid feedback and enhances productivity.
You can simply use your custom OS command line to run commands but as things get more complex, shell scripts may have you re-inventing the wheel.
Was the first JS task-runner to become popular. Grunt is configured via a gruntfile in JSON format which configures grunt to work with your plugins. The file is configuration based over code. Grunt is also file oriented. It writes files to disk after every step, this means it also reads from disk before subsequent steps. Since it has been around for a while, it has a large plugin ecosystem.
Gulp improves on Grunt’s plugin model in the following areas:
npm scripts are declared in the scripts section of your package.json. With this option, you can directly leverage the power of your OS command line. You can also use anything that you can install as an npm package. This comes in handy when you want to write scripts for tasks that run differently across different platforms i.e Windows, Mac, Linux. One example is deleting files. You can also call separate Node scripts independently. It also offers convention-based hooks to run other scripts before and after your main script. By using npm scripts you are also leveraging into the world’s current largest package manager.
You can read more here on why npm scripts over Grunt/Gulp.
To be used in demo: npm scripts
A transpiler as defined in this article:
Both are excellent options to consider.
To be used in demo: Babel
npm packages use the CommonJS format. Node can handle this, but the browser cannot understand. Bundlers convert this to a format that the browser can understand.
First bundler to reach mass adoption. Takes all the npm packages that you have referenced and bundles them up in a format that can be used on the web i.e bundles code that uses the CommonJS pattern. Its design is plugin based therefore it boasts of a large ecosystem of plugins i.e to add minification, linting, transpiling etc.
To be used in demo: Webpack
Linting also prevents mistakes while programming. Examples include: Overwriting functions by declaring a function with an existing name, adding extra parenthesis, doing an assignment instead of a comparison in a conditional, leaving debugging related junk in your code i.e debugger/console.log statements.
Was the original linter and very opinionated. However, the public has moved on to more powerful and configurable linters.
It offers more configurability in comparison to JSLint.
Currently most powerful and configurable linter. If you are using TypeScript the alternative is TSLint.
To be used in demo: ESLint.
- Focuses on testing a single function/module in an automated fashion.
- Often asserts that a specific function returns a certain value when passed certain parameters.
- Mock out external dependencies like database calls/APIs/file interactions.
Focuses on testing interactions between multiple modules.
Tests UI functionality by automating clicks and keystrokes and asserting that it interacts in expected ways. One popular tool in this space is Selenium.
Testing decisions to make:
- Testing Framework.
Mocha: Popular and highly configurable. Has a large ecosystem of support.
Jasmine: Quite similar to Mocha , but it includes a built-in assertion library.
Tape: Lean, simple with minimal configuration.
QUnit: An older option designed to test JQuery.
Jest: From Facebook and popular among React developers. Wrapper over Jasmine.
Ava: Simple to set up and runs your tests in parallel, this means it is fast. It supports ES6 by default (no transpiling eh?)
All the above options are valid. You can review each and select which will work best for you.
To be used in demo: Mocha
2. Assertion Libraries.
Some frameworks i.e Jasmine and Jest come with libraries built in, others e.g Mocha require you to get an assertion library. An assertion declares what to expect i.e
Chai.js (most popular)
Core difference in the above is merely syntactic, therefore any will work fine.
3. Helper Libraries.
It is an implementation of the browser’s DOM and it can run in Node.js. This enables you to run browser related tests without a browser. This makes it faster.
4. Where to run tests?
Headless browser is a browser that does not have a visible UI, making it faster. PhantomJS is an option for this.
JSDOM is an example. It simulates an actual DOM in-memory to be interacted with. It can be considered an lighter-weight alternative to PhantomJS. Faster and quick to set up.
To be used in Demo: JSDOM
5. Where do test files belong?
The two approaches to this are:
Centralized: This means putting all your tests in a separate folder at the root of your directory (probably named test), making them independent from your source code.
Reasons: To have less noise in src folder.
Alongside: This means placing your tests files along your source file.
Reason: Easier to import. Clear visibility. Convenient to open. No recreating folder structure.
Mocha by default pushes for option one since it looks for test files at the root of your directory in a folder named test.
file.spec.js and file.test.js are also the two common methods of naming test files.
6. When should tests run?
Unit tests should run immediately you hit save for rapid feedback, to facilitate TDD (Test Driven Development) and to enhance test visibility.
This image gives a better explanation of when to run your tests (integration vs unit)
That’s it for this article. In our next article, we will look at Http Calls, Project Structure, Production build and Production deploy.