preface

This article is an introduction to the overall TypeScript project environment configuration process in algorithms and TypeScript implementations. The configuration includes the following contents:

  • Git Commit Message
  • TypeScript
  • ESLint
  • Prettier
  • Lint Staged
  • Jest
  • Npm Script Hook
  • Vuepress
  • Github Actions

If you are familiar with some of the above configurations, you may want to skip the reading. If you are not sure whether to continue reading some of the configuration information, you can use the engineering question to decide whether to continue reading.

Algorithms and TypeScript implementations about the current configuration on the feat/ Framework branch, hope just interested students can star a wave. The learning document is still an old version of the learning document and will be updated continuously.

Tip: If you want to build a typescript-based utility library for your project, you can use mature “zero-configuration” scaffolding such as TSDX, Microbundles, and typescript-starter. If the functionality doesn’t meet your project needs, you can customize your team based on these tools, such as TS-Lib-Scripts.

Configuration problem

Hopefully, after reading this article, you will be able to understand some of the following questions (which are likely to be asked in an engineering configuration interview, but the devil is in the details) :

  • How to specify Git Commit information when using Git?
  • Describe the structure of an Angular submission specification.
  • How is Commit information associated with Github Issues?
  • How do I generate version logs when designing some library packages?
  • How does TypeScript automatically generate library package declarations?
  • Does TypeScript currently use TSLint or ESLint for code validation, and why?
  • List all the build tools you know and what are their pros and cons? How should these build tools be selected in different scenarios?
  • What are the limitations of Babel’s TypeScript support?
  • List the ESLint features you know?
  • How do I ensure that building and uploading code has no ESLint error messages?
  • What’s the difference between “ESLint” and “Prettier”? Do they cause problems when they work together?
  • What are the two types of verification rules that Linters have?
  • How to effectively identify the format rules ESLint and Prettier may conflict How to resolve such rule conflicts?
  • What is the role of Git hooks in a project?
  • What are the client and server hooks used for in Git hooks?
  • What hooks are commonly used in Git hooks?
  • pre-commitcommit-msgWhat’s the difference between hooks? What can each be used for?
  • How do tools like Husky and Ghook make Git hooks?
  • How to design a Generic Git Hook?
  • Can Git hooks be designed using Node scripts? How?
  • What does Lint-Staged do?
  • What is the difference between a user and a workspace in a VS Code configuration?
  • Can VS Code plug-ins only work for the current project?
  • What do you understand about NPM Scripts? What are its features?
  • What types of tests do you know?
  • What testing frameworks do you know?
  • What is e2E testing? What testing frameworks are available for E2E?
  • Suppose you have an insertion sort algorithm. How do you unit test it?
  • Suppose you implemented the React or Vue component libraries to design the demos, how would you design them? What does the design document need to do?
  • How do you design the API documentation when designing the toolkit package?
  • How can ESLint print validation errors in real time for hot Module replacement in a normal scaffolding project?
  • What are the features of Vuepress?
  • What CI/CD tools do you know? Have you been exposed to a similar process in the project?
  • What is the difference between CI and CD?
  • What will Github Actions feature?

In addition, if you are interested in other relevant knowledge (not relevant to this article), I hope you can explore in additional depth:

  • TypeScript features?
  • What are the differences between CommonJS and ES Module?
  • What does Tree Shaking do? When can YOU use Tree Shaking’s capabilities?
  • How do I import the ES Module library package? What do I need to pay attention to at the build level and package description file level?
  • What do you know about TypeScript declarations? How do I identify the declaration files when making a library package? What are the benefits of external use?
  • How to consider the elegant introduction design of on-demand introduction and full introduction when making the kit?
  • What do you know about making toolbase scaffolding?
  • Do you know the features of Vue CLI 3.x? How do I customize scaffolding for a team project based on Vue CLI 3.x?
  • Do you know React-Scripts?
  • What design stages can engineering configuration design have (for example, react-Scripts and Vue UI design and usage differences)?
  • Engineering configuration monitoring (version information, version compatibility error analysis, function analysis, etc.)?

Tips: Some of the questions can be answered in this article, and some of the questions need to be answered by reading further or looking at the source code. (The author is also a engineering configuration expert, so these questions are asked by himself.)

Configuration framework

Note that the configuration instructions in the documentation may omit some detailed steps (for example, the installation of certain dependent NPM packages, the description of certain configuration files, etc.). For more details, see the Commit information for each configuration:

  • Project initialization (AFAA458)
  • New Git Commit Message specification (D04E259)
  • Framework: New TypeScript compilation capabilities (EBECee9)
  • Framework: New ESLint code validation capability (DCA67D4)
  • Framework: Added Prettier automatic formatting (7F3487a)
  • Lint Upload Verification (B440186)
  • Framework: New Jest unit testing capability (6F086F2)
  • Framework: New Npm Scripts Hook capability (93e597a)
  • Framework: New Vuepress presentation capabilities (66E38D1)
  • Framework: Github Actions (1CC85A4)

Tips: The above version log information is automatically generated by using NPM run Changelog. You can also view it through changelog. md in the warehouse.

Git Commit Message

Commitizen is a CLI tool that provides Git Commit messages. For details, see the Cz toolset usage guide. (This article is very clear about the Commit Message configuration, so I won’t go into it here.) The following tools are mainly used in this project:

  • cz-customizable
  • commitlint
  • conventional-changelog

After the configuration, the following features are generated:

  • usegit czInstead ofgit commitCommit Message that complies with Angular specification
  • The code is checked by Husky and git hooks before committing. If the commit does not comply with Angular specifications, the submission will fail
  • performnpm run changelogWill be generated automatically in the root directoryCHANGELOG.mdVersion of the log

“Husky” means “husky” in Chinese, so you can imagine why this tool is called “husky”, or more 🐶 woof! It will be interesting to see what husky bites once it bites your code. We’ll see what husky bites in the next tool configuration!

For example, if you Commit a non-conforming Commit Message:

PS C:\Code\Git\algorithms> git commit -m "This is a nonconforming Commit Message."
husky > commit-msg (node v1213.1.) ⧗ input: This is an inconsistent Commit Message * Subject May not be empty [subject-empty] * type May not be empty [type-empty] * found2 problems, 0Warnings ⓘ Get help: HTTPS://github.com/conventional-changelog/commitlint/#what-is-commitlint

husky > commit-msg hook failed (add --no-verify to bypass)
Copy the code

Tips: If you do not know what the CLI (command line interface) is, see Using NPM to publish and using the CLI tool.

TypeScript

TypeScript background

The utility libraries are implemented in TypeScript, and in addition to automatically generating TS declaration files for better external prompts, Top 10 JavaScript Errors from 1000+ projects (and How to Avoid them) Thus, the design of the algorithm is more rigorous. Types of TypeScript builds include Webpack, Rollup, Babel, Gulp, etc. Besides native TSC compiler.

  • Webpack is primarily used for the modular build of page applications, and since Webpack builds increase the size of the build library, it is completely pointless to use Webpack for simple tool libraries.
  • Rollup is a great lightweight choice for a build tool library, and its Tree Shaking and build ES Module features make it widely used by TSDX, Microbundle, and even Vue.
  • Babel for TypeScript you can use @babel/preset TypeScript to remove the TypeScript type tag, but don’t do type compilation checking. For more information on Babel’s limitations on TypeScript support, see @babel/ plugin-transform-typescript-caveats or Babel 7 or TypeScript.
  • Gulp is a lightweight build tool and TypeScript’s official recommended build tool. See typescript-building for details, and see TypeScript Chinese-gulp for simple configurations.

Because the algorithm’s function library is very simple, build it with TypeScript’s official recommended Gulp tool.

Tip: More build tools are available for esBuilds, parcels, and backpack. Of course, if you want to learn more about the differences between these build tools and how to select them in any project environment, you can search for comparisons or differences in front end build tools.

TypeScript configuration

This project will build the output CommonJS toolkit (NPM package) for external use. Designing in TypeScript and output declarations will help external use of the resource bundle for API prompt. TypeScript compilation uses the Gulp tool recommended by the official documentation and is paired with gulp-typescript and tsconfig.json configuration files. Create a tsconfig.json file in the root directory and add the following configuration:

{
  "compilerOptions": {
    // Specify the ECMAScript target version "ES3" (default), "ES5", "ES6"/"ES2015", "ES2016", "ES2017", or "ESNext".
    "target": "ES5".// The built object code removes all comments except for the /! * Copyright information at the beginning
    "removeComments": true.// Generates.d.ts files in conjunction with gulp-typescript
    "declaration": true.// Enable all strict type checking options. Enabling --strict is equivalent to enabling --noImplicitAny, --noImplicitThis, --alwaysStrict, -- strictNullChecks - strictFunctionTypes and - strictPropertyInitialization
    "strict": true.Disallow inconsistent references to the same file
    "forceConsistentCasingInFileNames": true.// No output file is generated when an error is reported
    "noEmitOnError": true}}Copy the code

Note: There is no new Module configuration because the default output is the CommonJS specification. For more information about TypeScript configuration, see the TypeScript documentation/compilation options. If the difference between CommonJS and ES Modules is not clear, here are some excellent documents for you to read: ES Modules: A Cartoon Deep-dive, ES6 Modules. For more information on how to provide an ES Module, see pkg.module.

Create a gulpfile.js file in the root directory:

const gulp = require("gulp");
const ts = require("gulp-typescript");
const tsProject = ts.createProject("tsconfig.json");

// Output CommonJS specification to dist directory
gulp.task("default".function () {
  const tsResult = tsProject.src().pipe(tsProject());
  return tsResult.js.pipe(gulp.dest("dist"));
});
Copy the code

Add NPM script to package.json:

"scripts": {
  "build": "rimraf dist && gulp"
},
Copy the code

Where rimFAf is used to clear the contents of the dist directory file prior to build. Add TypeScript source code to SRC directory and use the NPM run build command to build the project and output CommonJS specification object code to dist directory.

In addition, the project wanted to be able to generate declarations quickly for external code prompts, while still being able to generate declarations automatically with the Gulp-typescript tool. Add the following configuration to gulpfile.js

const gulp = require("gulp");
const ts = require("gulp-typescript");
const tsProject = ts.createProject("tsconfig.json");
const merge = require("merge2");

// Output CommonJS specification to dist directory
gulp.task("default".function () {
  const tsResult = tsProject.src().pipe(tsProject());

  return merge([
    tsResult.dts.pipe(gulp.dest("types")),
    tsResult.js.pipe(gulp.dest("dist"))); });Copy the code

Modify the build command so that it also removes the types directory before building:

"scripts": {
  "build": "rimraf dist types && gulp",},Copy the code

Running NPM run build again will generate the types folder in the project root directory, which will hold the automatically generated TypeScript declaration files.

It is important to note that all files of the current project will be published by default when publishing an NPM package, but here you want to publish only the compiled files dist and types required by the consumer. This can be controlled by the files field information in package.json, which specifies which files are included in the published NPM package:

"files": [
  "dist"."types"].Copy the code

Tips: Some files in the published NPM package, such as package.json, LICENSE, and readme.md, will be ignored.

In addition, if the NPM package you want to publish is imported in the form require(‘ index-utils ‘) or import and points to dist/index.js, you need to configure the main field information in package.json:

"main": "dist/index.js"
Copy the code

Tips: Full introduction is not a good choice for toolkits. You can use specific tool methods for on-demand introduction.

ESLint

ESLint background

TSLint and ESLint are the two main types of TypeScript code checking tools. Early TypeScript projects typically used TSLint for checking. TSLint and TypeScript compile in the same AST format, but the main problem is that project support for JavaScript ecology is not friendly. So in 2019, the TypeScript team announced a full switch to ESLint (see the TypeScript repository’s.eslintrc.json configuration). For more details, see:

  • Medium.com/palantir/ts…
  • Github.com/microsoft/T…

TypeScript and ESLint use different AST Parsers, so support for TypeScript code checking in ESLint requires additional Custom Parsers. ESLint’s custom parser functionality needs to be ESTree based) in order to be able to parse TypeScript syntax and convert it to an ESLint-compatible AST. @typescript-eslint/ Parser was born in this context, It handles all esLint-specific configurations and calls @typescript-eslint/typescript-estree to generate estree-compatible AST (note that it’s compatible not only with ESLint but also with Prettier).

@typescript-eslint is a repository of Monorepo structures designed with Lerna. In addition to the NPM packages mentioned above, it contains the following two important NPM packages:

  • @typescript-eslint/eslint-plugin: cooperate with@typescript-eslint/parserESLint plugin to set TypeScript validation rules.
  • @typescript-eslint/eslint-plugin-tslint: Plugins that tsLint migrates to ESLint.

Migrating from TSLint to ESLint: If you are using TSLint and want to be compatible with OR transitioning to ESLint (TSLint and ESLint coexist), check out Migrating from TSLint to ESLint. In addition, the packages described above are shipped with the same version (for compatibility). Extra attention should be paid to the @typescript-esLint version support for typescript and ESLint. See the @typescript-eslint/parser repository for more information.

ESLint configuration

As you can see from the background, New TypeScript projects (ditchingtslint) need to include @typescript-eslint/parser for parsing the AST and @typescript-eslint/eslint-plugin for using validation rules. Here’s what you need to install in your project:

npm i --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
Copy the code

Create an.eslintrc.js configuration file in the root directory and set the following configurations:

module.exports = {
  root: true.parser: "@typescript-eslint/parser".plugins: ["@typescript-eslint"].extends: ["eslint:recommended"."plugin:@typescript-eslint/recommended"]};Copy the code

Among them:

  • parser: '@typescript-eslint/parser'Parse TypeScript syntax using ESLint
  • plugins: ['@typescript-eslint']: Loads a plug-in in ESLint@typescript-eslint/eslint-plugin, which can be used to configure TypeScript validation rules.
  • extends: [ ... ]: used in ESLintConfiguring Share Rules, includingeslint:recommendedIs ESLint’s built-in recommended validation rule configuration (also known as best rule practices),plugin:@typescript-eslint/recommendedIs similar to theeslint:recommendedTypeScript recommended validation rule configuration.

A tip: If you read a little bit of the Restocking source code, you’ll see that internally it’s actually a collection of recommended validation rules. So if you want to customize Rules based on @typescript-eslint/eslint-plugin, see typescript Supported Rules.

After the configuration, set the verification command in package.json

"scripts": {
  "lint": "eslint src",}Copy the code

NPM run Lint will output an error message if incorrect syntax is written in the SRC directory:

> eslint src


C:\Code\Git\algorithms\src\greet.ts
  2:16  warning  Missing return type on function  @typescript-eslint/explicit-module-boundary-types

✖ 1 problem (0 errors, 1 warning)
Copy the code

Output error messages are generated using ESLint Formatters. Check the ESLint source code and debug it. By default, stylish Formatter is used.

ESLint plug-in

If you don’t use plugins, it’s hard to spot code that might have TypeScript errors, because there’s no real-time prompt for writing code other than running NPM Run Lint manually (you can also listen for file changes and run NPM Run Lint via gulp). In order to see TypeScript errors in real time, you can use the VS Code plug-in to handle TypeScript errors. After installing the ESLint plugin, you can get a real-time code prompt, as shown in the figure below:

To prevent files that do not need to be verified, you can configure the.eslintignore file (for example, the following configuration files do not need to be verified) :

# gulp
gulpfile.js

# eslint
.eslintrc.js

# commitizen
commitlint.config.js

# jest
jest.config.js

# build
dist
Copy the code

Lint errors can then be found and displayed in real time in the VS Code editor in the form of plug-ins. In addition, some of ESLint’s format check errors (such as redundant; ) You can configure Save Auto Fix to automatically format the storage. For details on VS Code configuration, see the ESLint plugin documentation. The following configuration should be required:

"editor.codeActionsOnSave": {
  "source.fixAll": true."source.fixAll.eslint": true
}
Copy the code

Tips: VS Code configuration is divided into two types (user and workspace). For the above general configuration, it is mainly placed in the user, and for different projects, different configuration can be placed in the workspace.

ESLint ensures builds

The VS Code plug-in does not ensure that the Code is uploaded or built without any error messages, but it still requires additional process to avoid errors. ESLint checks before a build to ensure that the build is free of errors. If ESLint does not check, the source code will not be built:

"scripts": {
  "lint": "eslint src --max-warnings 0"."build": "npm run lint && rimraf dist types && gulp",}Copy the code

Note that there are strict controls on validation at build time, and if Lint throws a Warning or error, the build is terminated immediately (see the ESLint exit code for details).

Tips: Pay attention to the difference between && and & in Shell. && is mainly used for secondary execution. The next task is executed only when the previous task is successfully executed. The build command waits for the lint command to pass. If Lint fails, the build command will not be executed.

ESLint ensures that code is uploaded

Although ESLint validation scripts and VS Code plug-ins may be configured, some ESLint rule validation cannot be formatted and fixed with Save Auto Fix (such as quality rules). There is an additional layer of assurance needed to ensure that all code will pass ESLint before it is submitted. This configuration is explained in “Lint”.

Prettier

Prettier background

“Prettier” is a common code format tool. If you don’t know Why “Prettier” is used, you can check “Why Prettier”. . Many of you may wonder, ESLint already regulates the style of our code, why do we need Prettier? The distinction is detailed in “Prettier” vs Linters, which have two types of rules:

  • Formatting rules: max-len, keyword-spacing, no-mixed-spaces-and-tabs, etc
  • Code-quality rules: such as no-unused-vars, no-implicit-globals and prefer-promise-reject-errors

ESLint’s rule validation includes both formatting and quality rules, but in most cases only formatting rules can be fixed with a one-click –fix or the VS Code plugin’s Sava Auto Fix function. Quality rules, on the other hand, are more about finding bugs in the code to prevent errors, and they often need to be fixed manually. So format rules are not required, but quality rules are. 13, Prettier The difference between Prettier and ESLint is that while Prettier focuses on uniform formatting rules, Prettier reduces ESLint’s verification of formatting rules, quality rules are left to professional ESLint. 1. Pretty tier for formatting and linters for catching bugs! “(ESLint is required, Prettier is optional!)

If ESLint (TSLint) and Prettier collide, using “Sava Auto Fix” for the editor where “ESLint” (TSLint) and “Prettier” (Prettier) overlap, while “Sava Auto Fix” for the editor where “ESLint” (TSLint) and “Prettier” (Prettier) collide. At this time should let the two to distinguish their focus on the rule function, use ESLint to verify the quality rule, use Prettier to verify the format rule, more information can be seen with Linters.

Note: Matching a rule using ESLint in VS Code will result in a yellow wavy line and a red file name. Prettier wants you to be oblivious to formatting rules so you don’t feel burdened to use them. If you want to know more about Prettier, you can read the Option Philosophy behind Prettier. Personally, I think knowing the design Philosophy of an Prettier product can better guide you to use it.

Prettier configuration

Install the dependencies for Prettier first:

npm i  prettier eslint-config-prettier --save-dev
Copy the code

Among them:

  • eslint-config-prettier: this rule is used when ESLint and Prettier are used togetherFormatting rulesConflict issues, which are used to turn off formatting rules configured in ESLint, among other things@typescript-eslint/eslint-plugin,eslint-plugin-babel,eslint-plugin-react,eslint-plugin-vue,eslint-plugin-standardAnd so on.

In theory, to enable an ESLint extends rule set with formatting rule validation in a project, you need to use the eslint-config-prettier plugin to disable formatting rules that might conflict:

{
  "extends": [
    "plugin:@typescript-eslint/recommended".The format of the / / for close ESLint related rule set, the concrete are available at https://github.com/prettier/eslint-config-prettier/blob/master/index.js
    "prettier".// close the set of formatting rules associated with the @typescript-eslint/eslint-plugin plugin, Specific can see https://github.com/prettier/eslint-config-prettier/blob/master/%40typescript-eslint.js
    "prettier/@typescript-eslint"]},Copy the code

After the configuration, you can run Prettier on the command line interface:

"scripts": {
  "prettier": "prettier src test --write",},Copy the code

The –write argument is similar to the –fix in ESLint (again, it is recommended to use VS Code’s Save Auto fix function) and is used to automatically fix formatting errors. At this point write format error code:

import great from "@/greet";

// So many blank lines in the middle
export default {
  great,
};
Copy the code

Run the NPM run prettier command to repair the format:

PS C:\Code\Git\algorithms> npm run prettier

> algorithms-utils@1.0. 0 prettier C:\Code\Git\algorithms
> prettier src test --write

src\greet.ts 149ms
src\index.ts 5ms
test\greet.spec.ts 11ms
Copy the code

The fixed file format is as follows:

import great from "@/greet";

export default {
  great,
};
Copy the code

If eslint-config-prettier does not exist for an eslint-config-prettier rule set, you can use the CLI Helper tool to check whether a duplicate format rule set takes effect, and then manually configure eslintrc.js to disable the rule set:

PS C:\Code\Git\algorithms> npx eslint --print-config src/index.ts | npx eslint-config-prettier-check
No rules that are unnecessary or conflict with Prettier were found.
Copy the code

For example, if eslint-config-prettier is deleted from the prettier configuration, the duplication rule can be checked:

PS C:\Code\Git\algorithms> npx eslint --print-config src/index.ts | npx eslint-config-prettier-check The following rules  are unnecessary or might conflictwith Prettier:

- @typescript-eslint/no-extra-semi
- no-mixed-spaces-and-tabs

The following rules are enabled but cannot be automatically checked. See:
https://github.com/prettier/eslint-config-prettier#special-rules

- no-unexpected-multiline
Copy the code

If eslint-config-prettier does not have a similar set of closed formatting rules (for example, plugin:jest/recommended), You can then manually turn off the conflicting formatting rules yourself by configuring the.eslintrc.js format.

Note: ESLint can support different rule checks for different files, so –print-config only checks for formatting conflicts for a single file. Since a common project is a set of rules for an entire project, all the rules for the entire project only need to verify whether a file has formatting rule conflicts.

Prettier plug-in

Auto-formatting can be done through the command line interface in the form of –write, but like ESLint, we’d rather have the project automatically format code by saving it while editing in real time (who knows what files –fix and –write format, In this case, you can configure the prettier-code Formatter plug-in of VS Code to Save Auto Fix. For details, see the plug-in document.

Prettier Ensures that the code is uploaded

Like ESLint, although an automatic fix script for Prettier and the VS Code plugin may be configured for Prettier, there is no guarantee that the format is missing, so you need a layer of assurance that an Prettier format can be formatted before Code is submitted. This configuration will be explained in “Lint Passage”, see prettier-pre-commit Hook for more configuration scenarios.

Lint Staged

Lint Staged background

The commitlint tool is used in conjunction with Husky to prevent irregular Git Commit messages from being generated. The idea is to listen to the execution script of the Git Hook (and execute the corresponding script Hook before or after a specific Git execution command such as commit, push, merge, etc.). Git hooks are actually a very useful tool for project constraints. Their functions include but are not limited to:

  • Git Commit Message specification is mandatory
  • ESLint rules are uniform to prevent nonconforming code from being submitted
  • Prettier format an Prettier format for Prettier
  • Code stability commit, make sure all test cases pass before committing
  • Sending Email Notifications
  • CI integration (server-side hooks)

There are many hooks in Git hooks, but two that are likely to be commonly used on the client side are:

  • pre-commit: GitpreA series of hooks allow you to terminate Git operations that are about to occur, whilepostSeries are often used as notification behavior.pre-commitThe hook is typing the commit message (rungit commitgit cz) to check snapshots of code that is currently being committed, such as commit omissions, test cases, and code. If the hook exits with a non-zero value, Git will abandon the commit. You can also configure command-line argumentsgit commit --no-verifyBypass the hook operation.
  • commit-msg: This hook is called after the user enters the Commit Message and receives the current storeCommit MessageAs the only argument, you can use this hook to check Commit Meesage information (it is used in Git Commit messages to verify that Commit information conforms to Angular specifications). The hooks andpre-commitSimilarly, if you exit Git with a non-zero value, the commit will be abandoned.

In addition to the usual client-side hooks mentioned above, there are two common server-side hooks:

  • pre-receive: This hook is received in the remote repositorygit pushWhen the code is pushed (note that it is not a local repository), the hook will be more thanpre-commitMore binding (there will always be one developer or another who doesn’t like the bunch of checks they do when they commit code, and they may choose to bypass the hooks).pre-receiveHooks can be used to enforce specification validation when receiving code if a developer uses an bypasspre-commitThe hook can be set to deny the code submission. Of course, the most common operations of this hook are to check whether there is permission to push the code, not fast forward merge, etc.
  • post-receive: This hook is executed after the push code is successful and is suitable for sending email notifications or triggering CI.

Tips: For more information about Git Hooks, check out the official Git Hook documentation or Git Hooks: Customize your Workflow.

Note that after initializing Git, Shell sample scripts for all Git hooks are generated in the.git/hooks directory by default. These scripts can be customized. It’s very unfriendly for front-end developers to change these sample scripts for front-end projects (most front-end developers don’t design Shell scripts at all, even though it’s a very efficient thing to build tools), so the community has come up with similar enhancement tools. They throw simple hook configurations externally (for example, ghooks in package.json only need simple hook properties to be configured), and internally they make externally configured hooks executable by replacing Git hook sample scripts. Examples include Husky, Ghooks, and pre-commit.

Tips: Git Hook can also customize the language environment for script execution. For example, for the front end, you want to use the familiar Node script design. In this case, you can set #! /usr/bin/env node uses Node as an environment interpreter for executable files. You may be familiar with this environment parser if you have seen NPM distribution and CLI tools before. Here is an example of using the node interpreter: Ghooks – hook.template. Raw, ghooks implementation is very simple, interested students can carefully read some source implementation.

The purpose of this introduction is to make it clear that hooks can be used to do a lot of things in front-end engineering projects (the Git Commit Message would have been appropriate, but since that section refers to another article, this information is included in this section).

As mentioned earlier, using Git hooks can be subject to ESLint specification constraints, so you can probably guess that using pre-commit hooks (with Git Hook enhancements, of course), Husky) can be used with ESLint to verify the rules of a project before it is submitted, but as the project gets larger, ESLint may take longer to verify the rules, which can be a pain for frequent code committers. Lint-staged (Ed) tools can therefore be used to reduce the amount of code being tested.

Lint Staged configuration

Use the CommitLint tool to prevent irregular Git Commit messages from being generated, preventing users from committing Git code. However, if you want to prevent teams from submitting code that does not conform to ESLint, you can do so with the Lint-Passage tool. Lint-passage can use ESLint to check for code information (modified code after Git add) in Git registers before a user commits it (before generating a Git Commit Message). If there is code that does not conform to validation rules like 💩, You can terminate the commit behavior. It is important to note that Lint-Passage does not check the full code of a project (full validation with ESLint can be a relatively time consuming process for large projects), only the code added to Git staging area. Run the following command based on the official document to automatically generate configuration item information:

npx mrm lint-staged
Copy the code

Note that the default generated configuration files are for JavaScript environments. Manually modify the configuration information in package.json for TypeScript adaptation:

// Our Husky is out there again, and this time he's going to bite your ESLint. I'll call it "bite 💩" for short
"husky": {
  "hooks": {
    "pre-commit": "lint-staged"}},"lint-staged": {
  // Note the --max-warnings 0 for the ESLint script
  // Otherwise, the commit behavior will not be terminated even if there is a warning
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  "*.ts": ["npm run lint"."npm run prettier"]}Copy the code

If the code to be submitted has 💩, an error message will be displayed and the submission will be forced to terminate:

husky > pre-commit (node v1213.1.)
[STARTED] Preparing...
[SUCCESS] Preparing...
[STARTED] Running tasks...
[STARTED] Running tasks for*.ts [STARTED] npm run lint-strict [FAILED] npm run lint-strict [FAILED] [FAILED] npm run lint-strict [FAILED] [SUCCESS]  Running tasks... [STARTED] Applying modifications... [SKIPPED] Skipped becauseof errors from tasks.
[STARTED] Reverting to original state because of errors...
[SUCCESS] Reverting to original state because of errors...
[STARTED] Cleaning up...
[SUCCESS] Cleaning up...

× npm run lint-strict:
ESLint found too many warnings (maximum: 0).
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! algorithms-utils@1.0. 0 lint-strict: `eslint src --max-warnings 0 "C:/Code/Git/algorithms/src/greet.ts"`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the algorithms-utils@1.0. 0 lint-strict script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in: npm ERR! C: \ Users \ \ AppData \ son implement Roaming \ NPM - cache \ _logs \2020-07-11T07_25_39_102Z-debug.log

> algorithms-utils@1.0. 0 lint-strict C:\Code\Git\algorithms
> eslint src --max-warnings 0 "C:/Code/Git/algorithms/src/greet.ts"


C:\Code\Git\algorithms\src\greet.ts
  2:16  warning  Missing return type on function  @typescript-eslint/explicit-module-boundary-types
  2:34  warning  Argument 'name' should be typed  @typescript-eslint/explicit-module-boundary-types

✖ 2 problems (0 errors, 2 warnings)

husky > pre-commit hook failed (add --no-verify to bypass)
Copy the code

Husky has both pre-commit and commit-msg Git hooks configured in package.json. The pre-commit hooks are used first to perform ESLint verification, and if the verification fails, ESLint will terminate. If the validation is successful, the commit Message will be executed again. For example, if ESLint passes the validation but the commit Message fails:

PS C:\Code\Git\algorithms> git commit -m "This is a nonconforming Commit Message."
// The pre-commit hook ESLint validates
husky > pre-commit (node v1213.1.)
[STARTED] Preparing...
[SUCCESS] Preparing...
[STARTED] Running tasks...
[STARTED] Running tasks for *.ts
[STARTED] npm run lint-strict
[SUCCESS] npm run lint-strict
[SUCCESS] Running tasks for *.ts
[SUCCESS] Running tasks...
[STARTED] Applying modifications...
[SUCCESS] Applying modifications...
[STARTED] Cleaning up...
[SUCCESS] Cleaning up...
// The commit-msg hook failed to verify the Git commit Message
husky > commit-msg (node v1213.1.) ⧗ input: This is an inconsistent Commit Message * Subject May not be empty [subject-empty] * type May not be empty [type-empty] * found2 problems, 0Warnings ⓘ Get help: HTTPS://github.com/conventional-changelog/commitlint/#what-is-commitlint

husky > commit-msg hook failed (add --no-verify to bypass)
Copy the code

Jest

Test background

If you are not particularly clear about the concepts and frameworks of testing, here are some articles to check out:

  • JavaScript program testing – comprehensive testing basics
  • New to front-end testing? Start from the top of the pyramid! – Important to know about the test pyramid and test confidence
  • JavaScript unit test Frameworks: Jasmine, Mocha, AVA, Tape and Jest
  • JavaScript Unit Testing Frameworks in 2020: A Comparison

Beyond that, for additional testing tips, here are some community best practices:

  • javascript-testing-best-practices
  • ui-testing-best-practices

Since this is just a unit test for the Node environment toolkit package, we decided to use Jest for unit testing after comparing various testing frameworks:

  • The built-in assertion library can be implemented out of the box (fromitexpect, Jest keeps the entire kit in one place)
  • Jest can reliably run tests in parallel, and in order to speed up the testing process, Jest prioritizes previously failed test cases
  • Built-in coverage report, no additional configuration required
  • Excellent error message

Tips: There are many front-end testing frameworks, and E2E testing can be more complex than simple unit testing (both in terms of support for the testing framework and design of test cases). I have used the Karma test management tool for browser environment testing with Mocha, PhantomJS and Nightwatch (all of which are superficial), and I am most impressed with the TestCafe test framework (complex OFFICIAL API documentation). In addition, if you are interested, you can also learn about the Cypress testing framework.

Jest configuration

The unit test of this project mainly adopts Jest testing framework. Jest supports TypeScript in conjunction with Babel. See jest-using TypeScript, But there are some limitations to using Babel (see Babel 7 or TypeScript for details). Since this project did not use Babel for translation and wanted perfect support for type checking, TS-JEST was used for unit testing. Follow the official tutorial for dependency installation and project initialization:

npm install --save-dev jest typescript ts-jest @types/jest
npx ts-jest config:init
Copy the code

Jest: Jest: Jest: Jest: Jest: Jest: Jest

module.exports = {
  preset: "ts-jest".testEnvironment: "node".// Output the directory of the overwrite information file
  coverageDirectory: "./coverage/".// Overwrite the information to ignore file mode
  testPathIgnorePatterns: ["<rootDir>/node_modules/"].// If the test coverage does not reach 100%, the test fails
  // This can be used to prevent code builds and commits
  coverageThreshold: {
    global: {
      branches: 100.functions: 100.lines: 100.statements: 100,}},/ / path mapping configuration, the concrete are available at https://kulshekhar.github.io/ts-jest/user/config/#paths-mapping
  / / need to cooperate with the TypeScript path map, specific to view: https://www.tslang.cn/docs/handbook/module-resolution.html
  moduleNameMapper: {
    "^ @ / (. *) $": "<rootDir>/src/$1",}};Copy the code

Note that the paths in tsconfig.json also need to be configured, and that you include your test code in the TypeScript compilation directory. After configuration, configure the test command in package.json:

"scripts": {
  "lint": "eslint src --max-warnings 0"."test": "jest --bail --coverage"."build": "npm run lint && npm run jest && rimraf dist types && gulp",}Copy the code

Note these configuration information in Jest (see Jest CLI Options for more configuration information) :

  • bailThe configuration function of “is relatively similar to that in ESLintmax-warnings, is set totrueIt means to stop running the rest of the test cases once errors are found in the unit test cases, thus preventing the situation of running too many use cases and having to wait for them all to run out.
  • coverageIt is generated in the current root directorycoverageA test coverage report for your code, which can also be uploadedcoverallsDisplay the Badges on the Github project.

Tips: FindRelatedTests in Jest CLI Options can be used in conjunction with pre-commit hooks to run a minimal number of unit test cases, with Lint-Staged to perform a similar function to ESLint, For more details, see Lint-prevanced-use environment Variables with Linting Commands.

Create the greet.spec.ts file in the test directory of the current root directory and design the following test code:

import greet from "@/greet";

describe("src/greet.ts".() = > {
  it("name param test".() = > {
    expect(greet("world")).toBe("Hello from world 1");
  });
});
Copy the code

Warm tip: test files have two kinds of placing style, one is to create a test folder, and then all the test code in the test directory for management, another is in each source files at the same level of the directory to create a __test__ directory, the nearest test. Most projects will probably prefer the first directory structure (check out any open source project on Github; ts-Test uses the second). In addition, it is important to note that Jest can configure testMatch or testRegex to enable projects to identify specific format files to run as test files (this project uses the default configuration to identify.spec files for unit tests).

Jest ensures build

Unit testing is done separately by executing the NPM run test command, which demonstrates unit testing while executing the build command (ensuring that all unit test cases pass prior to the build). If the test fails, then the build should be prevented from continuing, such as performing a failed build behavior:

PS C:\Code\Git\algorithms> npm run build

> algorithms-utils@1.0. 0 build C:\Code\Git\algorithms
> npm run lint-strict && npm run jest && rimraf dist types && gulp


> algorithms-utils@1.0. 0 lint-strict C:\Code\Git\algorithms
> eslint src --max-warnings 0


> algorithms-utils@1.0. 0Jest C:\Code\Git\algorithms > jest --coverage PASS dist/test/greet.spec.js FAIL test/greet.spec.ts ● SRC /greet.ts  param test expect(received).toBe(expected)// Object.is equality

    Expected: "Hello from world 1"
    Received: "Hello from world"

      3 | describe("src/greet.ts".() = > {
      4 |   it("name param test".() = >{>5 |     expect(greet("world")).toBe("Hello from world 1");
        |                            ^
      6|});7|});8 |

      at Object.<anonymous> (test/greet.spec.ts:5:28)

----------|---------|----------|---------|---------|-------------------
| File       | % Stmts   | % Branch   | % Funcs   | % Lines   | Uncovered Line #s   |
| ---------- | --------- | ---------- | --------- | --------- | ------------------- |
| All files  | 100       | 100        | 100       | 100       |
| greet.ts   | 100       | 100        | 100       | 100       |
| ---------- | --------- | ---------- | --------- | --------- | ------------------- |
Test Suites: 1 failed, 1 passed, 2 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   0 total
Time:        3.45 s
Ran all test suites.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! algorithms-utils@1.0. 0 jest: `jest --coverage`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the algorithms-utils@1.0. 0 jest script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in: npm ERR! C: \ Users \ \ AppData \ son implement Roaming \ NPM - cache \ _logs \2020-07-12T13_42_11_628Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! algorithms-utils@1.0. 0 build: `npm run lint-strict && npm run jest && rimraf dist types && gulp`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the algorithms-utils@1.0. 0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in: npm ERR! C: \ Users \ \ AppData \ son implement Roaming \ NPM - cache \ _logs \2020-07-12T13_42_11_673Z-debug.log
Copy the code

Note that since the script is executed in parallel (&&), ESLint validation is performed before the build command is executed. If ESLint fails, the build exits, otherwise Jest unit tests continue. If the unit tests fail, the build exits, and the source build only happens if both pass.

Jest ensures that code is uploaded

In addition to preventing irresponsible code builds, you also need to prevent irresponsible code commits. Lint-passage prevents remote commit of code that does not pass unit tests:

"scripts": {
  "lint": "eslint src --max-warnings 0"."test": "jest --bail --coverage",},"lint-staged": {
  "*.ts": [
    "npm run lint"."npm run test"]}Copy the code

At this point, if the unit test is wrong, the code will be stopped:

husky > pre-commit (node v1213.1.)
[STARTED] Preparing...
[SUCCESS] Preparing...
[STARTED] Running tasks...
[STARTED] Running tasks for *.ts
[STARTED] npm run lint
[SUCCESS] npm run lint
[STARTED] npm run jest
[FAILED] npm run jest [FAILED]
[FAILED] npm run jest [FAILED]
[SUCCESS] Running tasks...
[STARTED] Applying modifications...
[SKIPPED] Skipped because of errors from tasks.
[STARTED] Reverting to original state because of errors...
[SUCCESS] Reverting to original state because oferrors... [STARTED] Cleaning up... [SUCCESS] Cleaning up... * NPM run jest: FAIL test/greet.spec. Ts SRC /greet.ts × name param test (4Ms) ● SRC /greet. Ts// Object.is equality

    Expected: "Hello from world 1"
    Received: "Hello from world"

      3 | describe("src/greet.ts".() = > {
      4 |   it("name param test".() = >{>5 |     expect(greet("world")).toBe("Hello from world 1");
        |                            ^
      6|});7|});8 |

      at Object.<anonymous> (test/greet.spec.ts:5:28)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        1.339 s, estimated 3 s
Ran all test suites related to files matching /C:\\Code\\Git\\algorithms\\src\\index.ts|C:\\Code\\Git\\algorithms\\test\\greet.spec.ts/i.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! algorithms-utils@1.0. 0 jest: `jest --bail --findRelatedTests --coverage "C:/Code/Git/algorithms/src/index.ts" "C:/Code/Git/algorithms/test/greet.spec.ts"`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the algorithms-utils@1.0. 0 jest script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in: npm ERR! C: \ Users \ \ AppData \ son implement Roaming \ NPM - cache \ _logs \2020-07-12T14_33_51_183Z-debug.log

> algorithms-utils@1.0. 0 jest C:\Code\Git\algorithms
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the algorithms-utils@1.0. 0 jest script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in: npm ERR! C: \ Users \ \ AppData \ son implement Roaming \ NPM - cache \ _logs \2020-07-12T14_33_51_183Z-debug.log

> algorithms-utils@1.0. 0 jest C:\Code\Git\algorithms
> jest --bail --findRelatedTests --coverage "C:/Code/Git/algorithms/src/index.ts" "C:/Code/Git/algorithms/test/greet.spec.ts"

----------|---------|----------|---------|---------|-------------------
| File       | % Stmts   | % Branch   | % Funcs   | % Lines   | Uncovered Line #s   |
| ---------- | --------- | ---------- | --------- | --------- | ------------------- |
| All files  | 0         | 0          | 0         | 0         |
| ---------- | --------- | ---------- | --------- | --------- | ------------------- |
husky > pre-commit hook failed (add --no-verify to bypass)
git exited with error code 1
Copy the code

Tip: To learn more about the ecology of Jest, check out Awesome – Jest.

Jest support for ESLint

Under the SRC directory of the source code by configuring @ typescript – eslint/eslint – the plugin can be recommended eslint validation rules, in order to make the test directory of test code can be adaptable to the rules of the Jest recommend eslint check, This can be supported by configuring eslint-plugin-jest (the ts-jest project uses this plugin for ESLint validation, see the ts-jest/.eslintrc.js configuration file), where the recommended rules are still used:

module.exports = {
  root: true.parser: "@typescript-eslint/parser".plugins: ["@typescript-eslint"].extends: [
    "eslint:recommended"."plugin:@typescript-eslint/recommended".// Added recommended ESLint validation rules
    // For all rule sets to view: https://github.com/jest-community/eslint-plugin-jest#rules (recommended)
    "plugin:jest/recommended",]};Copy the code

To verify that the recommended rule is valid, you can find a no-identical title rule here:

import greet from "@/greet";
describe("src/greet.ts".() = > {
  it("name param test".() = > {
    expect(greet("world")).toBe("Hello from world 1");
  });
});

// A duplicate title is entered here
describe("src/greet.ts".() = > {
  it("name param test".() = > {
    expect(greet("world")).toBe("Hello from world 1");
  });
});
Copy the code

Note how to modify the ESLint validation range in Package. json:

"scripts": {
  // ESLint checks the SRC and test directories
  "lint": "eslint src test --max-warnings 0",},Copy the code

NPM Run Lint for format validation of unit tests:

PS C:\Code\Git\algorithms> npm run lint

> algorithms-utils@1.0. 0 lint C:\Code\Git\algorithms
> eslint src test --max-warnings 0


C:\Code\Git\algorithms\test\greet.spec.ts
  9:10  error  Describe block title is used multiple times inThe same describe block jest/no-identical title *1 problem (1 error, 0 warnings)

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! algorithms-utils@1.0. 0 lint: `eslint src test --max-warnings 0`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the algorithms-utils@1.0. 0 lint script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in: npm ERR! C: \ Users \ \ AppData \ son implement Roaming \ NPM - cache \ _logs \2020-07-13T02_25_12_043Z-debug.log
Copy the code

ESLint throws an error message. Note that using this ESLint validation also generates an error message in VS Code in real time (a red wavy line under the Code, a Tooltip showing the rule for the error, and a red file name in the current project directory). Subsequent Git commits and builds will fail!

Tip: If you want Jest to test code that requires formatting, check out the eslint-plugin-jest-formatting plugin.

Npm Script Hook

When you look at a front-end open source project, the first thing you’ll probably look for is the package.json fields like main, bin, and files. In addition, if you want to learn more about the structure of the project, You might also view the scripts field information to understand the development, build, test, and installation processes of your project. NPM’s scripting capabilities are so powerful that you can take advantage of any process tools you need to script your project. This article will not go into much of the functionality of the NPM script, but will show you the hook functionality that is used.

Some of the script commands currently used in this project are as follows (the script is relatively few and well-defined for now) :

"lint": "eslint src test --max-warnings 0"."test": "jest --bail --coverage"."build": "npm run lint && npm run prettier && npm run test && rimraf dist types && gulp"."changelog": "rimraf CHANGELOG.md && conventional-changelog -p angular -i CHANGELOG.md -s"
Copy the code

If you look at the build script command, you will see that it contains a large number of secondary execution scripts, but the only scripts that are really relevant to build are Rimraf dist Types && gulp. NPM’s script hooks, pre and POST, are used to separate the functions of the script, which makes the semantics of the script more clear (although the increasing number of scripts may easily increase the cognitive burden of the developer). In addition to specifying some special script hooks (such as prepublish, postpublish, preinstall, postinstall, etc.), NPM can also add pre and post hooks to any script. Here, you can simplify concurrent script execution with custom hooks:

"lint": "eslint src test --max-warnings 0"."test": "jest --bail --coverage"."prebuild": "npm run lint && npm run prettier && npm run test"."build": "rimraf dist types && gulp"."changelog": "rimraf CHANGELOG.md && conventional-changelog -p angular -i CHANGELOG.md -s"
Copy the code

If you run the NPM run build command, you actually run the following command:

npm run prebuild && npm run build
Copy the code

NPM Scripts hook will be used for the design of the script if there are many secondary executions.

Tips: You might wonder where you need a hook like preinstall or preuninstall, such as looking at husky-package.json, Husky had some side effects when it was installed because the Git Hook script had to be inserted (at this point, of course, you can trigger the Git Hook script insertion logic via preinstall). If you don’t want to use Husky, you’ll need to clean up the embedded scripts after uninstalling so that you don’t interfere with the original Git Hook functionality. If you want to learn more about NPM scripts, check out nPm-Scripts or the NPM Scripts Usage Guide.

Vuepress

Vuepress background

A common component library or tool library requires a presentation (to provide a good development experience). A common tool library can use tsDoc, JSDOC, or ESDOC for automatic generation of API documentation, but it often needs to comply with some annotation specification, which can be a development burden to some extent, or it can be given to a VS Code plug-in for one-click generation. For example, Document This For Jsdoc or TSDoc Comment.

Element UI of Component library uses Vue-Markdown-loader (Convert Markdown file to Vue Component using Markdown-it) for Component Demo design. However, the configuration is relatively complex. An easier way is to design with Vuepress, which is very powerful, but you need to be familiar with Vue because you can use the Vue syntax in Markdown. Of course, if it’s a Demo of the React component library, you can use Dumi to generate a Demo of the component. You can also learn more about React markdown, react-static, etc.

Since Vuepress was used to design the Vue component library Demo, it is still used to design the API documentation for the tool library package (you can also use the TSDoc tool if you want to generate the API documentation automatically). The main features of the Vuepress design document are as follows:

  • You can use Vue directly from Markdown (you can also customize the Vue document view component)
  • Many Markdown extensions are built in
  • You can use Webpack to build custom configurations
  • The default topic supports search capabilities
  • The Vuepress plug-in can be installed (any subsequent typesetting that needs to be supported for Latex can be generated using the existing plug-in capabilities)
  • Default response

Vuepress configuration

Follow the official Quick Start documentation to install the dependency and set the NPM scripts:

"scripts": {
  "docs:dev": "vuepress dev docs"."docs:build": "vuepress build docs"
}
Copy the code

According to the Vuepress official website convention is better than the principle of configuration, the directory structure of the demo document is designed. The official document may be difficult to understand at once, so you can design the simplest directory first:

.├ ── docs │ ├─.vuepress │ ├─ ├─ ch.pdf # ├─ ch.pdfCopy the code

Design the home page in docs/ readme.md according to the default theme/home page:

---
home: true
# heroImage: /hero.png
heroText: algorithms-utils
tagline: algorithms and TypeScript implementationsactionText: Start learningactionLink: /guide/Features: - title: Simplification theorydetails: Simplify the content of "Introduction to Algorithms" to help yourself learn the theoretical knowledge of algorithms more easily. - title: exercisesdetails: Answer the exercises of "Introduction to algorithm" to help yourself better practice the theoretical knowledge of algorithm. -title: Select the topicdetails: Collect common interview questions to improve my algorithm programming ability and interview pass rate.footer: MIT Licensed | Copyright © 2020-- - the present child implementCopy the code

Configure the docs/.vuepress/config.js file as follows:

const packageJson = require(".. /.. /package.json");

module.exports = {
  // Configure the site title
  title: packageJson.name,
  // Configure the website description
  description: packageJson.description,
  // Configure the basic path
  base: "/algorithms/".// Configure the basic port
  port: "8080"};Copy the code

NPM run docs:dev

PS C:\Code\Git\algorithms> npm run docs:dev

> algorithms-utils@1.0. 0 docs:dev C:\Code\Git\algorithms
> vuepress dev docs

wait Extracting site metadata...
tip Apply theme @vuepress/theme-default. tip Apply plugin container (i.e."vuepress-plugin-container")... tip Apply plugin @vuepress/register-components (i.e."@vuepress/plugin-register-components")... tip Apply plugin @vuepress/active-header-links (i.e."@vuepress/plugin-active-header-links")... tip Apply plugin @vuepress/search (i.e."@vuepress/plugin-search")... tip Apply plugin @vuepress/nprogress (i.e."@vuepress/plugin-nprogress")... Tick the Client Compiled successfullyin 5.31s I "WDS" : Project is running at HTTP:/ / 0.0.0.0:8080 /I "WDS" : Webpack output is servedfrom/ index-utils/I "WDS" : Content notfrom webpack is served fromC:\Code\Git\algorithms\docs\.vuepress\public I "WDS" : 404s will fallback to /index.html success [23:13:14] Build 10b15a finished in 5311 ms!
> VuePress dev server listening at http://localhost:8080/algorithms-utils/
Copy the code

The effect is as follows:

Of course, in addition to the above design of the home page, this project will also design the navigation bar, sidebar, using plug-ins, using components and so on. The focus here is on the Webpack build configuration.

To use TypeScript code from the SRC directory in the Markdown document, the.vuepress/config.js file is configured:

const packageJson = require(".. /.. /package.json");
const sidebar = require("./config/sidebar.js");
const nav = require("./config/nav.js");
const path = require("path");

module.exports = {
  title: packageJson.name,
  description: packageJson.description,
  base: "/algorithms/".port: "8080".themeConfig: {
    nav,
    sidebar,
  },

  plugins: [
    "vuepress-plugin-cat"["mathjax",
      {
        target: "svg".macros: {
          "*": "\\times",}},],// Added support for TypeScript syntax to the Markdown document
    [
      "vuepress-plugin-typescript",
      {
        tsLoaderOptions: {
          // All configuration items of ts-Loader}},]].chainWebpack: (config) = > {
    config.resolve.alias.set("image", path.resolve(__dirname, "public"));

    // Simulate the introduction of library packages in the documentation
    // For example, after releasing the index-utils library package,
    // Import greet from 'battery-utils /greet.ts' is equivalent in the Vuepress presentation
    // import greet from '~/src/greet.ts',
    // Where ~ refers to the project root directory only
    config.resolve.alias.set(
      "algorithms-utils",
      path.resolve(__dirname, ".. /.. /src")); }};Copy the code

Tips: The Webpack configuration here uses the Webpack-chain operation, if you want to use the Webpack object configuration you can see Vuepress – Build process – configureWebPack.

At this point, you can design the TypeScript introduction demo in Vuepress’s Markdown documentation:

# Test vuepress ::: danger Test Vuepress is introduced to greet. : : :<template>
  <collapse title="Look at the answers.">{{msg}}</collapse>
</template>

<template>
  <div>{{msg}}</div>
</template>

<script lang="ts">
  import greet from 'algorithms-utils/greet'
  const msg = greet('ziyi')
  export default {
    data() {
      return {
         msg
      }
    },
  }
</script>

Copy the code

Start Vuepress to view the demo:

You can see that the SRC /greet.ts code introduced in Markdown is working, and that the NPM run docs:build can generate static resources for the presentation for deployment and access.

Note: More Vuepress configuration information for this project can be found in the Commit information. In addition, if you want to know more about the Vuepress ecology, such as what interesting plug-ins or topics there are, check out the Awesome Vuepress or Vuepress community.

Documentation tools and specifications

Usually when writing documents, many students do not pay attention to the cleanliness of documents. In fact, writing documents and writing code need some format specifications. Markdownlint is a Markdown format validation tool similar to ESLint that allows us to better standardize the documents we write. Markdown format verification does not require a strong constraint like ESLint or Prettier. It can simply be prompted and Save Auto Fix.

By installing the Vs Code plugin MarkdownLint and configuring it to Save Auto Fix (the plugin explicitly lists which rules can be fixed). After the installation is complete, view the test file just performed:

You’ll see that the plugin is in effect, but the ability to insert HTML into Markdown is a must (Vuepress supports the ability to use Vue in Markdown), so the corresponding rules can be masked through the.markdownlintrc file.

Tip: If you want Markdown validation before your code is submitted or before your document is built, try its command line interface markdownLint-cli. In addition, if you have no idea about the design of the document or do not know how to write a good technical document, you can check out the technical article writing skills to share, will certainly let you learn.

Github Actions

CI/CD background

Premise note: Individuals may be relatively unfamiliar with CI/CD, having simply played Travis, Gitlab CI/CD, and Jenkins.

The background of CI/CD is not too much here, interested students can see some good articles:

  • Introduction to CI/CD with GitLab
  • GitHub Actions Introduction tutorial
  • Github Actions official documentation
  • What DID I Do when I had a Server?

In the Introduction to CI/CD with GitLab (Chinese version), you can clearly understand the responsibilities and functions of CI and CD:

The following figure provides a clearer picture of the functions available in Gitlab at each stage:

Because this project relies on Github, Gitlab’s default integration capabilities are not available. Previous Github projects used Travis for CI/CD integration, but now with Github Actions more convenient, Therefore, we decided to use Github Actions for CI/CD integration (please Google if you want to know more about these CI/CD differences). The benefits of Github Actions are:

  • Reusable Actions (previously you had to write complex scripts, but now you can reuse scripts written by others, which can be simply understood as CI script plugins)
  • Support for more Webhooks, which are certainly unique to the Github ecosystem

Of course, there are some limitations, which are related to execution time and number of times. Note that Jenkins and others support local connection runs, Github Actions also support connecting to a local machine to run workflows, so some restrictions may not be limited to local running.

Tips: The CI/CD functions used in this project are relatively simple. For more general Actions, see official Actions and Awesome Actions. Jenkins is currently being used for automated build optimization of the front end, and a simple tutorial article is likely to follow (although it will vary from the usual usage).

Making Actions configuration

The configuration of this project may include the following three aspects:

  • Automatically update static resource processes
  • Publish library package process
  • Submit the Pull Request process

The process of automatically updating static resources is divided into the following steps (the following steps are performed on the Github server, which you can understand as the new service environment) :

  • Pull the current Github repository code and switch to the appropriate branch
  • Install the Node and Npm environments
  • Install project dependencies
  • Static resources for building library packages and presentation documents
  • Publish static resources for the presentation

Find the Actions you need by looking at official Actions and awesome Actions:

  • Checkout: pull repository code from Github to the Github server$GITHUB_WORKSPACEdirectory
  • Cache: NPM cache
  • Setup-node: Installs the Node and Npm environments
  • Actions-gh-pages: Publish static resources on Github

Tip: There are many actions available, but this is just a simple process to set up.

Add mian. Yml configuration file under.github/workflows:

The following are simple translations of official documents
The current yml (.yaml) file is a process that is continuously integrated and runs once. It must be placed in your project's.github/ Workflow directory
# if it is not clear. Yml file format syntax, you can look at https://www.codeproject.com/Articles/1214409/Learn-YAML-in-five-minutes
# Formatting problems are inevitable when writing for the first time. You can use the VS Code plugin for formatting detection. https://marketplace.visualstudio.com/items?itemName=OmarTawfik.github-actions-vscode

# specific each configuration properties can view the HTTPS: / / docs.github.com/en/actions/reference/workflow-syntax-for-github-actions

The execution of # Workflow is still subject to some limitations, for example
# - Maximum 6 hours per job (local machine is not limited)
Each workflow executes for a maximum of 72 hours
# - The number of concurrent jobs is limited
# - more see HTTPS: / / docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#usage-limits

# Name: Specifies the name of the current workflow
name: Algorithms

# on: Specifies the event triggered by workflow
#
# Event has the following types
# - webhook
# - scheduled
# - manual
on:
  # push: a Webhook event that triggers workflow when code is submitted. It can also be a list of triggers, such as [push, pull_request]

  Most of the events triggered by workflows are based on Webhook configuration. Here are some common Webhooks:
  # -delete: Emitted when a branch or tag is deleted
  # -fork/watch: Triggered when someone forks/watches a project (what's the use of sending email notifications?)
  Pull_request: triggered when PR is submitted
  # -page_build: Triggered when Github page-enabled branch code is submitted
  # -push: Triggered when code is committed to a particular branch
  # -registry_package: Triggered when publishing or following a new package
  # more webhook can view the HTTPS: / / docs.github.com/en/actions/reference/events-that-trigger-workflows
  One of the main features of Git Actions is a series of Webhooks provided by Gihub
  push:
    # branches: Specifies the specific branches triggered by push. Here you can specify multiple branches in a list
    branches:
      - feat/framework
    #
    The designation of # branches can be a wildcard type such that the following configuration matches refs/ Heads/RELEASES /10
    # - 'releases/**'
    #
    # Branches can also be used in reverse matching, e.g. the following does not match refs/heads/ RELEASES /10
    # - '! releases/**'
    #
    # branches-ignore: only works on the two webhooks [push, pull_request]. This is used to specify the branch that is not triggered by the current webhook
    # can not be used with branches in the same Webhook
    #
    # tags: only for [push, pull_request] two webhooks. This is used to specify the tag triggered by the current webhook
    #
    # tags:
    # - v1 # Push events to v1 tag
    * # Push events to V1.0, V1.1, and V1.9 tags
    #
    # tags-ignore: Similar to branches-ignore
    #
    # paths, paths - ignore...
    #
    More information about specific filtering modes is available https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
    #
    For example, if the Issues are open, open, closed, and so on, the case can also be opened
    # more webhook types can view the HTTPS: / / docs.github.com/en/actions/reference/events-that-trigger-workflows#webhook-events
    #
    # on:
    # issues:
    # types: [opened, edited, closed]

  In addition, if you have different Webhook triggers for each branch, you can configure multiple Webhooks in the following form
  #
  # push:
  # branches:
  # - master
  # pull_request:
  # branches:
  # - dev
  #
  In addition to the webhook events mentioned above, there are scheduled events and manual events
  # Scheduled Event: Used for scheduled builds, such that the minimum time interval is 5 minutes per build
  # concrete can view the HTTPS: / / docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events


      
       . Env, jobs.
       
        .env.
       
# defaults/defaults.run: All jobs are valid. Each job can be configured independently through jobs.
      
# deafults
# defaults.run

# Jobs: A workflow consists of one or more jobs
jobs:
  My_first_job # job ID # job ID # job ID # job ID # job ID # job ID
  build_and_deploy:
    # name: The name of the job displayed on Github
    name: Build And Deploy
    #
    # needs: the current job build must be executed after job1 and job2 have been executed successfully
    # needs: [job1, job2]
    #
    # runs-on: specifies the environment configuration for a job to run, including:
    # - windows-latest
    # - windows-2019
    # - ubuntu 20.04
    # - ubuntu-latest
    # - ubuntu 18.04
    # - ubuntu 16.04
    # - macos-latest
    # - macos 10.15
    # -Hosted hosted (local machine) / / docs.github.com/en/actions/hosting-your-own-runners/using-self-hosted-runners-in-a-workflow)
    runs-on: ubuntu-latest
    #
    Outputs: outputs information
    #
    # env: Used to set environment variables
    #
    # defaults: Default Settings for all current steps
    #
    # defaults.run

    # if: The current job is executed if the condition is met

    Step: A job consists of multiple steps. Step can be used
    Execute a list of tasks
    # - Execute command
    # - Execute action
    # - Implement a public repository
    # - Action in Docker Registry
    steps:
      #
      # id: Similar to job ID
      #
      # if: Similar to job if
      #
      # name: Name of the current step
      - name: Checkout
        #
        # uses: Uses to execute an action
        #
        # action: Unit code that can be reused
        For security and stability of workflow it is recommended to specify a release version or a COMMIT SHA for the action
        # - Use the major version of the specified action, which allows you to receive fixs and security patches while maintaining compatibility
        # - Use of the Master version is not recommended as there is a high chance that a new major version of the Master version will be released and break the compatibility of the Action
        # -action may be a JavaScript file or a Docker container. If it is a Docker container, then runs must specify the Linux environment
        #
        # Specify fixed COMMIT SHA
        # uses: actions/setup-node@74bc508
        # Specify a major release
        # uses: actions/setup-node@v1
        Specifies a minor release version
        # USES: actions/[email protected]
        # Specify a branch
        # uses: actions/setup-node@master
        # Specify a specific branch, ref, or SHA of a Github repository subdirectory
        # uses: actions/aws/ec2@master
        # Specifies the workFlows directory address where the current repository resides
        # uses: ./.github/actions/my-action
        Specifies the address of the Docker image published on Dock Hub
        # uses: docker: //alpine: 3.8
        # A Docker image in a public registry
        # uses: docker: //gcr.io/cloud-builders/gradle

        The # checkout action is primarily used to pull the source code to the Github repository (note that workflow runs on the server, so you need to pull the repository source code to the current Github repository).
        # Its features include but are not limited to
        # - Fetch all history for all tags and branches
        # - Checkout a different branch
        # - Checkout HEAD^
        # - Checkout multiple repos (side by side)
        # - Checkout multiple repos (nested)
        # - Checkout multiple repos (private)
        # - Checkout pull request HEAD commit instead of merge commit
        # - Checkout pull request on closed event
        # - Push a commit using the built-in token

        # checkout action: https: //github.com/actions/checkout
        uses: actions/checkout@v2
        # with: The input parameter provided by the action
        with:
          Specifies the branch, tag, or SHA of checkout
          # more checkout action configuration to view the HTTPS: / / github.com/actions/checkout#usage
          ref: feat/ci
        # args: CMD directive parameter for Docker containers
        # entryPoint: Both the Docker container action (which overwrites the EntryPoint of the Dockerfile) and JavaScript action can be used
      #
      # run: Execute the command line program using the default non-login shell of the current operating system
      # Run a single script
      # run: npm install
      # Run multiple scripts
      # run: |
      # npm ci
      # npm run build
      #
      # working-directory: specifies the directory where the current script is run
      # working-directory: ./temp
      #
      # shell: You can specify a shell type for execution, such as bash, PWSH, Python, sh, CMD, powershell
      # shell: bash
      #
      # env: In addition to setting workflow and job env, you can set step env as well.
      #
      # comtinue-on-error: If the current step fails by default, the current job will be prevented from continuing to execute. If the current step fails, the current job will be skipped

      - name: Cache
        # cache action: https://github.com/actions/cache
        # Cache is used to cache NPM and increase build speed
        uses: actions/cache@v2
        # NPM cache path are available at https://docs.npmjs.com/cli/cache#cache
        # since runs-on is ubuntu-latest, configure ~/.npm
        with:
          path: ~/.npm
          key: The ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: | ${{ runner.os }}-node-      # github-script action: https://github.com/actions/github-script
      Call the Github API or reference the Workflow context using Script syntax in your Workflow

      # setup-node action: https://github.com/actions/setup-node
      # Configure the Node execution environment (the server currently being built does not have a Node environment by default, you can install Node using Action)
      NPM is bundled with Node. If you want to know why NPM is bundled, Google interesting Story
      Use this action to execute the NPM script on the server
      You can also try v2-beta here
      - name: Set Node
        uses: actions/setup-node@v1
        with:
          # can also be flexibly configured using strategy.matrix.node
          # This is a local build using version 12 of Node, so this is a fixed version
          node-version: "12"

      - run: npm install
      - run: npm run build
      - run: npm run docs:build

      - name: Deploy
        # used to publish static site resources
        # actions-gh-pages action: https://github.com/peaceiris/actions-gh-pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          # GTIHUB_TOKEN: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token
          # Github automatically generates gihubT_tokens in workflows to authenticate workflow runs
          github_token: The ${{ secrets.GITHUB_TOKEN }}
          # Static resource directory Settings
          publish_dir: ./docs/.vuepress/dist
          The default publishing branch is gh-pages. You can specify a specific publishing branch
          publish_branch: gh-pages1 # default: gh-pages
          full_commit_message: The ${{ github.event.head_commit.message }}
    #
    # timeout-minutes: specifies the maximum time for a job to be executed. The default is 6h
    #
    # strategy.matrix: for example, specify the node version list of the current job, the operating system type list, etc
    # strategy.fail-fast
    # strategy.max-parallel
    # continue-on-error: Workflow stops execution once the current job fails. Set this parameter to true to skip the current job execution
    Container: Docker container configuration, including image, env, ports, volumes, options, and so on
    #
    The Docker container Action or service Action must be run in Linux
Copy the code

Note: This section does not describe the specific configuration process. For more information, see the link posted in the configuration file.

After you upload the CI profile, Github will automatically build it as follows:

You can view information about each build while it is being built or after the build is complete. If the first build fails, you can use the build information to find out why the first build failed and modify the build configuration to try to build again. In addition, Github notifies each build failure via email:

If the build is successful, the Github service will go through a series of processes and automatically update the static resource site every time you push new code.

conclusion

After reading this document, I hope you will develop the following habits if you want to use some of these tools:

  • Read through the tool documentation to understand the differences between different tools for the same function

Read through the official Github README documentation for the tool, as well as the official site documentation, to learn about the core philosophy of the tool’s design, its core functionality, and what core issues it addresses. There are many tools on the front end, and the same function can be achieved by many different tools. If you want to use the appropriate tools on your project, you need to know the differences. Read the official documents in their entirety to help you understand the core features and differences.

  • After researching the differences between the tools, choose the tools you think are appropriate to practice

You will become more and more familiar with the use of the tool as you practice. At this point, if you run into some problems or want to implement some functionality, it will be relatively easy to read through the document. Of course, if you encounter some error messages that cannot be resolved, the first time you should search for the Github Issues corresponding to the current tool. In addition, you can also look at the source code of the error stack trace tool, which may make it clearer why the error message occurred.

  • After completing the above two steps, you should have summarized the techniques of using the tool. At this point, reading through the tool documentation may yield different results

Link to the document

  • Use NPM to publish and use CLI tools
  • Top 10 JavaScript errors from 1000+ projects (and how to avoid them)
  • Front-end construction: Selection reference of 13 popular tools in 3 categories
  • Introduction to the Cz toolset
  • ES Modules: A Cartoon Deep-Dive
  • JavaScript program testing
  • New to front-end testing? Start from the top of the pyramid!
  • JavaScript & Node.js Testing Best Practices
  • JavaScript Unit Testing Frameworks: Jasmine, Mocha, AVA, Tape, and Jest
  • JavaScript unit testing frameworks in 2020: A comparison
  • javascript-testing-best-practices
  • ui-testing-best-practices
  • NPM Scripts Usage Guide
  • Technical article writing skills to share
  • Introduction to CI/CD with GitLab
  • GitHub Actions Introduction tutorial
  • What do I do when I have a server