Hello. Recently, I came across the task of setting up the turnover of private npm packages. Everything sounded very interesting and promising until it turned out that there was not much to do there. It would all be over, but the second task arose - to write a demo repository for the npm package, which could be taken, cloned and quickly created on its base something useful and in the same style.
The result was a project with customized formatting, code type, tests for each pool, code coverage limits, code coverage report and automatic documentation. Plus convenient publication in npm. Details about the setting - under the cut.
At first, I figured that we already have:
Then he figured out his Wishlist - since there is time and desire, why not go for a walk. What do I want more:
As a result, the requirements were formed in the following:
It seems to be good, you need to try.
Create (clone) the repository, initialize package.json, set locally TypeScript. In general, all dependencies are set locally, since everything will go to the server. Do not forget to fix version dependencies .
git init npm init npm i -D typescript ./node_modules/.bin/tsc --init
Immediately on the spot you need to correct tsconfig.json for yourself - set the target, libs, include / exclude, outDir and other options.
To preserve the uniformity of formatting, I took two tools. The first is the .editorconfig file. It is understood by all major IDEs (WebStorm, VSCode, Visual Studio, etc.), does not require installation of anything extra and works with a large number of file types - js, ts, md, and so on.
#root = true [*] indent_style = space end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true max_line_length = 100 indent_size = 4 [*.md] trim_trailing_whitespace = false
Now auto-formatting will behave more or less the same for me and for my colleagues.
The second tool is the prettier . This is an npm package that checks, and if possible, automatically adjusts your text formatting. Install it locally and add the first command to package.json
npm i -D prettier
package.json
"prettier": "prettier --config .prettierrc.json --write src/**/*.ts"
The prettier has no init command, so you need to configure it manually. Create a .prettierrc.json at the root of the project with roughly such controversial content (if anything, the post is not at all about which quotes are better, but you can try)
.prettierrc.json
{ "tabWidth": 4, "useTabs": false, "semi": true, "singleQuote": true, "trailingComma": "es5", "arrowParens": "always" }
Now create the src folder, create index.ts with some conditional content in it, and try running prettier. If he doesn’t like your formatting, he will fix it automatically. Very comfortably. If you do not want to remember this only during a commit / push, you can configure it to autostart or install an extension for the studio.
With the style of the code is also not difficult. For JavaScript there is eslint , for TypeScript there is tslint . Put tslint and create tsconfig.js to store settings
npm i -D tslint ./node_modules/.bin/tslint --init
package.json
"lint": "tslint -c tslint.json 'src/**/*.ts' 'tests/**/*.spec.ts'"
You can write your own rules, or you can use already existing rules using the extend parameter. Here , for example, a config from airbnb.
module.exports = { extends: "./tslint-base.json", rules: { "no-excessive-commenting": [true, {maxComments: Math.random() * 10}] } };
Isn't it beautiful?
There is an important point - tslint and prettier intersect along the functional (for example, in the length of a string or "hanging" commas). So, if you use both - you will need to monitor compliance or abandon something.
And yet, for those who want to check not all files, but only staged - there is a lint-staged package
What do we need from the tests first? First, that they run automatically, secondly, the control of coverage, thirdly, some kind of report, preferably in the lcov format (if that - lcov is well understood by different analyzers - from SonarQube to CodeCov). Automation, we will do a bit later, while we set up the tests themselves.
We put karma , jasmine and all the corresponding kit
npm i -D karma karma-jasmine jasmine karma-typescript karma-chrome-launcher @types/jasmine ./node_modules/.bin/karma init
We modify karma.conf.js a bit and immediately set up the coated operation.
karmaTypescriptConfig : { include: ["./src/**/*.ts", "./tests/**/*.spec.ts"], tsconfig: "./tsconfig.json", reports: { "html": "coverage", "lcovonly": { directory: './coverage', filename: '../lcov.dat' } }, coverageOptions: { threshold: { global: { statements: 60, branches: 60, functions: 60, lines: 60, excludes: [] }, file: { statements: 60, branches: 60, functions: 60, lines: 60, excludes: [], overrides: {} } } }, }
And, of course, do not forget to add a new command in package.json
package.json
"test": "karma start"
If you use or plan to use CI, then it is better to put HeadlessChrome :
npm i -D puppeteer
And preconfigure Karma (Chrome fix on ChromeHeadless) plus something else. Edits can be viewed in the demo repository .
Run the tests, check that everything works. At the same time, check the coverage report (it is in the coverage folder) and remove it from version control, it is not needed in the repository.
Report:
Commits can also be unified (and at the same time bring someone to a white-hot, if you overdo it, so it's better without fanaticism). For this, I took commitizen . It works in the form of a dialogue, supports the conventional-changelog format (you can create a changelog from its commits) and there is a VsCode plugin for it
npm i -D commitizen npm i -D cz-conventional-changelog
cz-conventional-changelog is an adapter that is responsible for the questions, and as a result, for the format of your commits
Add a new command to the scripts section
"commit":"git-cz"
And the new section package.json - config for commitizen
"config": { "commitizen": { "path": "./node_modules/cz-conventional-changelog" } }
The dialogue with commitizen looks like this:
Now to the documentation. We will have two kinds of documentation - from the code and from the commits. For documentation from the code I took typedoc (analog esdoc but for TypeScript). It is very easy to install and work. The main thing do not forget to remove the results of his labors from the control of versions.
npm i typedoc -D
and update package.json
package.json
"doc": "typedoc --out docs/src/ --readme ./README.md"
The --readme flag will force the readme to be included in the main documentation page, which is convenient.
The second type of documentation is the changelog, and the conventional-changelog-cli package will help us.
npm i -D conventional-changelog-cli
package.json
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s"
From angular there is only formatting and nothing else. Now, in order to update the changelog, just run npm run changelog. The main thing is to carefully write commits. Well, we always write perfect commits, so this should not be a problem.
Since our package should work for JavaScript, we need to turn TypeScript into JavaScript. In addition, it would be nice to make a minified bundle, just in case. To do this, we need uglifyjs and tweak package.json a bit
npm i -D uglifyjs
package.json
"clean":"rmdir dist /S /Q", "build": "tsc --p ./ --sourceMap false", "bundle": "uglifyjs ./dist/*.js --compress --mangle --output ./dist/index.min.js"
By the way, if you want to control the size of your project, there are two more interesting packages.
They can also be integrated into the process of kommit / push / public list in order to keep in the acceptable dimensions of the bundle. Very, very helpful.
Well, we have already done the basic steps, now everything needs to be automated, otherwise it will be frankly inconvenient to work.
For this we need another package - husky . It rewrites the git hooks and calls the associated commands from package.json. For example, when you make a commit, precommit, push - prepush, and so on will work. If the script returns an error, the commit will crash.
npm i -D husky
package.json
"precommit":"npm run prettier", "prepush": "call npm run lint && call npm run test"
There is an important nuance, the use of call syntax is not cross-platform and will not take off on unix systems. So if you want to do everything in an honest way, you will also have to install the npm-run-all package, it does the same thing but cross-platform.
Well, we have come to the publication of our (albeit empty) package. Let's think what we want from publishing?
Hands do it all - sad. Either you forget something, or you need to write a checklist. It is also necessary to automate. You can put another package - unleash . And you can use the native hooks of the npm itself - preversion, version, postversion, for example like this:
"preversion": "npm run test", "version": "call npm run clean && call npm run build && npm run bundle && call npm run doc && call npm run changelog && git add . && git commit -m 'changelogupdate' --no-verify", "postversion": "git add . && git push && git push --tags",
It remains to specify for package.json what to include in the package, entry point and path to our types (do not forget to specify the --declaration flag in tsconfig.json to get d.ts files)
package.json
"main": "./dist/index.min.js", "types": "./dist/index.d.ts", "files": [ "dist/", "src/", "tests/" ]
Well, that seems to be all. Now enough to execute
npm version ... npm publish
And everything else will be done automatically.
As a bonus, there is a demo repository that all supports + CI with travis-ci. Let me remind you that HeadlessChrome is set up there, so if this is important to you, I advise you to look in there.
Many thanks to Alexey Volkov for his report on JsFest, which became the basis of this article.
Thanks max7z , indestructible , justboris for clarifying that the paths to local dependencies can be omitted.
Source: https://habr.com/ru/post/417429/
All Articles