初始化
mkdir <projectName>
cd <projectName>
touch index.ts
npm init -y
git init
touch .gitignore
Typescript
# 安装typescript
npm i typescript -D --save
# 初始化typescript配置,生成tsconfig.json
npx tsc -init
tsconfig.json
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Language and Environment */
"target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": [
"DOM",
"ES2017"
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
/* Modules */
"module": "ESNext" /* Specify what module code is generated. */,
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
"baseUrl": "./" /* Specify the base directory to resolve non-relative module names. */,
/* Emit */
"declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
"sourceMap": true /* Create source map files for emitted JavaScript files. */,
"declarationDir": "./types" /* Specify the output directory for generated declaration files. */,
/* Interop Constraints */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
"noUnusedLocals": true /* Enable error reporting when a local variables aren't read. */,
"noUnusedParameters": true /* Raise an error when a function parameter isn't read */,
/* Completeness */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Babel
# babel解析核心
npm i @babel/core -D -S
# babel运行时依赖 babel预设置
npm i @babel/plugin-transform-runtime @babel/preset-env -D -S
touch .babelrc.js
.babelrc.js
module.exports = {
presets: [
[
"@babel/env",
{
targets: {
browsers: ["ie >= 11"],
},
useBuiltIns: "usage",
corejs: 3,
modules: "auto",
loose: true,
},
],
],
};
ESLint
# eslint ts解析器 ts规则插件
npm i eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin -D -S
touch .eslintrc.js
touch .eslintignore
.eslintrc.js
module.exports = {
// 规则继承
extends: ["plugin:@typescript-eslint/recommended"],
// 解析器
parser: "@typescript-eslint/parser",
// ts插件
plugins: ["@typescript-eslint"],
// 规则定制
rules: {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-expressions": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
vars: "all", //全部声明包括全局
args: "all", //一次声明全位置
ignoreRestSiblings: true, //忽略rest
argsIgnorePattern: "^_", //通过lint正则
varsIgnorePattern: "^_", //通过lint正则
},
],
},
};
.eslintignore
/es
/lib
/node_modules
Prettier
格式化工具,配合eslint
npm i prettier eslint-config-prettier eslint-plugin-prettier --save-dev
touch .prettierrc
.prettierrc
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 80,
"overrides": [
{
"files": ".prettierrc",
"options": { "parser": "json" }
}
]
}
修改.eslintrc.js
module.exports = {
extends: [
'plugin:@typescript-eslint/recommended',
// 关闭和eslint冲突,配置prettier插件,相关规则预设
'plugin:prettier/recommended',
],
...
};
lint-staged/husky
#前置安装husky和lint-staged钩子
npx mrm@2 lint-staged
如果全局环境有安装nvm之类的nodejs管理工具的话,需要修改${project}/.husky/pre-commit文件,以保证husky脚本正确执行
#项目根目录
cd ${project}/.husky
pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
export NVM_DIR="$HOME/.nvm/nvm.sh"
. "$(dirname $NVM_DIR)/nvm.sh"
export NVM_DIR="$HOME/.nvm"
a=$(nvm ls | grep 'node')
b=${a#*(-> }
v=${b%%[)| ]*}
export PATH="$NVM_DIR/versions/node/$v/bin:$PATH"
npx lint-staged
Rollup
# 安装rollup 路径解析插件
npm i rollup @rollup/plugin-node-resolve -D --save
# 安装typescript插件
npm i rollup-plugin-typescript2 -D --save
# 安装babel插件
npm i @rollup/plugin-babel -D --save
# 安装rimraf插件清理产物
npm i rimraf -D --save
# 串行运行方案
npm i npm-run-all -D --save
# 新建rollup配置文件
touch rollup.config.js
rollup.config.js
import nodeResolve from '@rollup/plugin-node-resolve';
import babel from '@rollup/plugin-babel';
import typescript from 'rollup-plugin-typescript2';
import pkg from './package.json';
const babelRuntimeVersion = pkg.peerDependencies['@babel/runtime'].replace(
/^[^0-9]*/,
'',
);
const extensions = ['.ts'];
const noDeclarationFiles = { compilerOptions: { declaration: false } };
// 生成external配置
const makeExternalPredicate = (externalArr) => {
if (externalArr.length === 0) {
return () => false;
}
const pattern = new RegExp(`^(${externalArr.join('|')})($|/)`);
return (id) => pattern.test(id);
};
export default [
//Commonjs
{
input: 'src/index.ts',
output: {
file: 'lib/index.js',
format: 'cjs',
indent: false,
},
external: makeExternalPredicate([
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.peerDependencies || {}),
]),
plugins: [
nodeResolve({ extensions }),
typescript({
useTsconfigDeclarationDir: true,
}),
babel({
extensions,
plugins: [
['@babel/plugin-transform-runtime', { version: babelRuntimeVersion }],
],
babelHelpers: 'runtime',
}),
],
},
// ES
{
// 入口文件
input: 'src/index.ts',
// 输出文件 es 无缩进
output: { file: 'es/index.js', format: 'es', indent: false },
// 外部扩展,不打包
external: makeExternalPredicate([
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.peerDependencies || {}),
]),
// 插件
// 一些插件重复功能
// ts路径解析(nodeResolve(extensions)/typescript/babel(extensions))
// ts转js typescript/babel
plugins: [
// rollup路径解析
nodeResolve({
extensions,
}),
typescript({ tsconfigOverride: noDeclarationFiles }),
babel({
// 转译目标文件
extensions,
plugins: [
[
'@babel/plugin-transform-runtime',
{ version: babelRuntimeVersion, useESModules: true },
],
],
//babelHelpers
//runtime:使用Rollup构建库时常用,它必须与@babel/plugin-transform-runtime结合使用,你还应该指定@babel/runtime作为你的包的依赖。目标是es/cjs时,应该配置@babel/runtime为扩展依赖,也可以按需指定依赖如:@babel/runtime/helpers/get,Rollup将只排除完全匹配字符串的模块。
//bundled:helpers打包进产物中
//external:与@babel/plugin-external-helpers结合使用。从全局babelHelpers对象中引用helpers
//inline:babel默认配置,每个独立文件中插入helpers,会导致严重的代码重复
babelHelpers: 'runtime',
}),
],
},
];
package.json
{
"name": "utils",
"version": "1.0.0",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
"types": "types/index.d.ts",
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"clean": "rimraf lib dist es types",
"build": "rollup -c",
"lint": "eslint --ext .js,.jsx src/",
"start": "npm-run-all -s clean build",
"prepare": "husky install"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.16.0",
"@babel/plugin-transform-runtime": "^7.16.4",
"@babel/preset-env": "^7.16.4",
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-node-resolve": "^13.0.6",
"@rollup/plugin-replace": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^5.5.0",
"@typescript-eslint/parser": "^5.5.0",
"eslint": "^8.3.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"husky": "^7.0.4",
"lint-staged": "^12.1.2",
"npm-run-all": "^4.1.5",
"prettier": "^2.5.0",
"rimraf": "^3.0.2",
"rollup": "^2.60.1",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.31.1",
"typescript": "^4.5.2"
},
"peerDependencies": {
"@babel/runtime": "^7.16.3"
},
"dependencies": {},
"lint-staged": {
"*.{js,jsx}": "eslint --cache --fix"
}
}