FRONT-END CI/CD AUTOMATION. PART 1
Let's start with a small educational. CI / CD stands for Continuous Integration and Continuous Delivery aka Deployment - that is, continuous integration and continuous delivery. Why is this needed?
Most often, the ultimate goal of development is the application. To use it, people must get access to it: either download from the store and install it. If this is a website - put the URL into the address bar and open the page. In order for the mobile application to get to the store, you need to download it there. In the case of websites, you need to download our HTML / JS / CSS files.
Everything seems to be simple. But downloading files manually is at least inconvenient:
- you need to be at the computer on which these files are
- when a person uploads files, he may forget to upload something or upload something wrong
So it would be nice to automate the process - this is the deployment, the yellow loop in the picture. In the article, we recalled the deployment and release steps.
The blue loop, CI, is what we do after we have finalized the new functionality, and before it goes to deploy to become available to users.
What is included in CI
- preparation of the production build.
- preparation of the production build.
Linters are static code analyzers that test it without launching it. They allow you to reduce the time for code review and save developers from routine tasks: checking the style of the code (spaces, semicolons, and line length); search for problems and potential bugs: unused fragments of code, obviously dangerous or over-complicated constructions.
TSLint - was the main linter for TypeScript, however, developers refuse to support it in favor of ESLint.
Prettier - is not quite a linter, but rather a formatter that follows a single code style; integrates seamlessly with ESLint and TSLint.
Stylelint - a linter for CSS and its most popular dialects (SASS, LESS), for which it has plugins.
Before deploying the application, or pouring it into the master, we want to make sure that it is stable. We want to know that the application will not break after launch and that the main use cases work. And we want to do it automatically.
- Jest, Mocha, Jasmine - frameworks for organizing and running tests; Jest has been the most popular recently, as it comes out of the box with the Create React App.
- Testing Library, Enzyme - utilities primarily aimed at testing web applications (rendering, click simulation, etc.).
- Selenium- web driver, Cypress - tools for testing end-to-end, that is, when the browser will actually start and their commands will be sent that emulate user actions (clicks, keystrokes, etc.).
Production build preparation
Build a transformation of the source files so that they can be distributed by the server as a website (that is, as a set of HTML / JS / CSS files that the browser understands), published in the package manager (if you are writing a library, framework or utility), used as browser extensions, application on Electron, etc.
During the development process and in production, the application starts and works in different ways. And the characteristics are important to us different. In the development process, we want the application to be quickly rebuilt and we will see an updated result. It doesn’t matter how much it weighs, because it is distributed from the local machine. In production, it doesn’t matter to us (within reasonable limits, of course) how much time the application is going to build, because we collect it once and then simply distribute it with the server.
Conditionally production build consists of the following stages:
• Permission for imports. Browsers began to understand modularity only recently, and that is still not all. You need to figure out in which order to run the scripts and how to transfer the results of their execution to other scripts.
• Minification and obfuscation. The assembled code weighs less than the source and is more difficult to analyze. This complicates reverse engineering.
• Stitching environment variables. The same application can work in different environments. The simplest example is on a test server and on production: in this case, it is necessary to build applications two times, once - when the API leads to the test server, and second time - to the production server.
- Webpack, Parcel, Rollup, SystemJS, gulp, Grunt are the main application builders that solve most of the problems mentioned.
- Dotenv, dotenv-cli - npm packages that simplify working with environment variables, especially during development.
It is very useful to create a version.json file after the build and before the deployment. This file will contain information about the version of the application, about the build time, a fragment of the hash of the commit from which the application was built.
Store this file so that it is easily accessible next to the web application. For example, at: https://your-site.com/version.json.
Such a simple action will help you and other team members (primarily testers) quickly determine the version of the application that is running in this environment and tracking deployments.
Summary. NPM scripts.
All these processes are integration from CI, but so far not very continuous. To automate them, you need to spend time (once) and configure them so that they are launched with a single command on the command line.
Npm scripts are great for this. As a result, all 3 previous processes can be reduced to the launch of three commands, which will look like something like:
npm run lint
npm run test
npm run build
Thus, we get a few simple commands that you can run for each new version of the application to catch problems and errors in advance and automatically.