There are a number of CLI tools available for quickly initializing a build project. For example, TSDX and create-React-app are a bit bloated for some small personal projects. If you put aside these CLI tools and manually build a small and beautiful NPM package development environment from 0 to 1, what do you need to do? Might as well try it together!

First, our project expectations:

  1. Implement a Javascript tool library
  2. Support the Typescript
  3. Team collaboration Commit Message format constraints
  4. Prettier code formatting, ESlint verification
  5. Automatically upgrade the version and build before sending the package

The package build tool uses Rollup.

First, build the basic file structure

The first step is to design and build the file structure of the project and initialize a package.json file that describes the functionality of the current project.

mkdir dyboy-npm-ts-template
cd dyboy-npm-ts-template
touch index.ts
npm init -y
Copy the code

Initialize the Typescript environment

As you can see, our entry file./index.ts is Typescript. The most important thing is that we need to package it to users to support code hints in TS environment, which will help improve development efficiency

yarn add typescript -D
Copy the code

It then initializes to quickly generate a tsconfig.json file that belongs to the Typescript configuration file

tsc --init
Copy the code

The default tsconfig.json configuration needs to be modified to enable us to compile into ES modules.

After simple modification, the tsconfig.json configuration and directory structure are as follows:

When configured, Typescript prints the index.d.ts type declaration file to the./dist directory during compilation

You also need to modify/add the package.json file.

- "main": "index.js",
+ "main": "./dist/index.cjs.js",
+ "module": "./dist/index.esm.js",
+ "types": "./dist/index.d.ts",
+ "files": [
+ "dist"
+],
Copy the code

The files field is used to specify which files and folders NPM will publish when the package is distributed.

Note: the folder name in the files field is written directly into the name. Do not include the./ character, otherwise the packaged product will not contain the folder.

At this point, you’re ready to write Typescript files smoothly

Index. ts file contents:

const func = () = > {
    // TODO: coding...
};

export { func };
Copy the code

The mouse-over function func also has a type hint indicating that the Typescript development environment is OK

Git initialization

The code exists locally, but for better code versioning/backup, Git tools will be used and associated with remote repositories.

First initialize git for your project

git init
Copy the code

Create a new.gitignore file to ignore files or folders that do not need to be stored in Git versions and add the following write rules:

node_modules/
dist/
.DS_Store
.yarn-error.log
Copy the code

Initialize the Rollup packaging environment

Since we were publishing NPM packages, we needed a small and elegant build tool, and Rollup was the natural choice. Rollup supports Tree Shaking well, making packaged packages smaller.

4.1 Installation Dependencies:

yarn add rollup -D
yarn add @rollup/plugin-typescript -D
yarn add @rollup/plugin-node-resolve -D
yarn add @rollup/plugin-commonjs -D
Copy the code

Rollup is installed, along with plugins that support TS, processing paths, and CommonJS

4.2 configuration rollup. Config. Js

The initial configuration is as follows:

import resolve from '@rollup/plugin-node-resolve';
import typescript from '@rollup/plugin-typescript';
import commonjs from '@rollup/plugin-commonjs';

export default[{input: './src/index.ts'.output: {
      dir: 'dist'.format: 'cjs'.entryFileNames: '[name].cjs.js',},plugins: [resolve(), commonjs(), typescript()],
  }, {
    input: './src/index.ts'.output: {
      dir: 'dist'.format: 'esm'.entryFileNames: '[name].esm.js',},plugins: [resolve(), commonjs(), typescript()],
  }
];
Copy the code

It is possible to generate files supporting both CommonJS and ESModule, and in the previous tsconfig.json configuration an index.d.ts file was also generated to indicate type declarations.

4.3 modify the scripts

When you get to package.json, to use the shortcut instructions and call rollup as a preview for development, you need to configure the scripts field as follows:

"scripts": {
+ "dev": "rollup -w -c",
+ "build": "rollup -c"
- "test": "echo \"Error: run tests from root\" && exit 1"
},
Copy the code

This way, we can compile in real time at development time with Yarn Dev.

To package the yarn, run the yarn build command

ESlint configuration

On the other hand, if it’s an open source product, when someone mentions MR, we want his code style to match some of our expectations, so we’ll introduce ESlint into the project.

Install the ESLint development environment dependencies first

yarn add eslint -D
Copy the code

You can then initialize a configuration file using the newly installed ESLint:

./node_modules/.bin/eslint --init
Copy the code

This gives you an.eslintrc.json configuration file in the root directory of your project,

You can then modify some rules of ESlint according to your needs. The rules configured by the author are as follows:

{
  "env": {
    "browser": true."commonjs": true."es2021": true
  },
  "extends": ["eslint:recommended"."plugin:@typescript-eslint/recommended"]."parser": "@typescript-eslint/parser"."parserOptions": {
    "ecmaVersion": 8
  },
  "plugins": ["@typescript-eslint"]."rules": {
    "@typescript-eslint/no-unused-vars":  [
      "error",
      {
        "varsIgnorePattern": "^ _"}]."no-unused-vars": "off"."no-console": "warn"."space-before-function-paren": "warn"."semi": "warn"."quotes": ["warn"."single"]}}Copy the code

Prettier code automatically formatting

Prettier can be used to automatically unify team code because front-end development projects involve code formatting such as whitespace after parentheses and CSS formatting.

Install the prettier

yarn add prettier -D
Copy the code

Next, create a.prettierrc.json configuration file that reads as follows:

{
  "printWidth": 100.// Single line length
  "tabWidth": 2.// Indent length
  "useTabs": false.// Use Spaces instead of TAB indentation
  "semi": true.// Use a semicolon at the end of a sentence
  "singleQuote": true.// Use single quotes
  "bracketSpacing": true.// Add Spaces before and after the object -eg: {foo: bar}
  "arrowParens": "avoid" // Use parentheses around the arguments of the single-argument arrow function -eg: (x) => x
}
Copy the code

For more rules, see Configuration File

Developers can use the Shift + Commond + F shortcut to format the current file.

Husky Git commit constraint

Of course, in addition to manual formatting, what if the developer commits the code to a remote location without formatting. For this purpose, introduce Husky as a Git commit to do an automatic formatting of the files in the staging area and verify compliance with Eslint rules.

At the same time, you also need to standardize your Git commit message. You can introduce the CommitLint tool to verify that the submitted message format complies with the specification

For specific specifications, refer to: Conventional Commits

First install the development environment dependencies:

Yarn add [email protected] - D yarn add lint - staged - D yarn add @ commitlint yarn add @ commitlint/config/cli - D - but - DCopy the code

Then add the following to the package.json file:

"husky": {
  "hooks": {
    "pre-commit": "lint-staged"."commit-msg": "commitlint -E HUSKY_GIT_PARAMS"}},"commitlint": {
  "extends": [
    "@commitlint/config-conventional"]},"lint-staged": {
  "*.{ts,js}": [
    "node --max_old_space_size=8192 ./node_modules/.bin/prettier -w"."node --max_old_space_size=8192 ./node_modules/.bin/eslint --fix --color"."git add"]},Copy the code

Once configured, at Git commit, a developer will call lint-staged commands in fields where Prettier is formatted, ESlint validates and fixes, and the modified file will be stored in staging.

The next step is to verify that the COMMIT message complies with the specification before the commit succeeds.

Upgrade the version and build it before pre-delivery

To quickly send packages, you can add shortcut commands in the scripts field of the package.json file to normalize package sending.

Add the following command to prompt the upgrade package version before the package is sent (NPM publish), and then build to build the product

"prepublish": "yarn version && yarn build"
Copy the code

Several lifecycle hooks for NPM publish:

  1. Prepublish: Run BEFORE the package is published (Also Run on local NPM install without any arguments).
  2. Prepare: Run both BEFORE the package is packed and published, and on local npm install without any arguments. This is run AFTER prepublish, but BEFORE prepublishOnly.
  3. PrepublishOnly: Run BEFORE the package is prepared and packed, ONLY on NPM publish.
  4. Publish: Run AFTER the package is published.
  5. Postpublish: Run AFTER the package is published.

Complete initialization

Json -> license: MIT protocol: MIT protocol

The final act of initialization is to store the current changes to Git records and associate remote repositories.

Create Git repository – Github Docs

We then staged and committed the local code

git add -A
git commit -m "feat: init"
Copy the code

Associate the remote repository and commit local code to the remote repository:

git remote add origin "https://xxxx.com/xx/xx.git"
git push -u origin master
Copy the code

We can use the current repository as a template repository for developing typescript-enabled NPM packages. We can create new NPM packages by cloning the current template and changing the configuration as needed, adding rollup plug-ins, and so on.

conclusion

I’ve sorted out the things you need to do to initialize a project, including packaging build, development, Git, and package, and I’ve done the initialization of the project happily from zero to one, so I can develop it more happily.

TODO: Since the initial environment of the project is the same and can be given the concept of a template, is it possible to write a development scaffolding (CLI) for your own team to initialize the project?