前言
之前做过一个从零初始化一个todo前端项目的系列,此篇文章目的是做一期npm包的创建发布,初始化一个npm包的脚手架,然后梳理一下npm包的发布流程。
npm is the package manager for javascript. npm是js的包管理器,更多的用于nodejs端。
项目github地址:shengshunyan-utils
包npm地址:@shengshunyan/utils
初始化脚手架
创建项目
创建一个github仓库,初始化LICENSE和README文件,然后clone到本地
bash1
git clone https://github.com/shengshunyan/shengshunyan-utils.git
初始化package.json文件
bash1
npm init
创建src文件夹,添加模块功能代码,这里添加js的排序算法代码作为示例模块代码 (具体代码查看github仓库)
bash1
2
3
4touch src/index.ts
touch src/sort/index.ts
touch src/sort/bubble.ts
touch src/sort/selection.ts
配置打包
本文选择rollup作为打包工具,首先全局安装一下rollup
bash1
npm install rollup -g
根目录新建rollup.config.js文件,作为打包配置
javascript1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import babel from 'rollup-plugin-babel';
import { terser } from 'rollup-plugin-terser';
import { eslint } from 'rollup-plugin-eslint';
import typescript from 'rollup-plugin-typescript2';
const isPro = process.env.NODE_ENV === 'production'
export default {
input: 'src/index.ts',
output: [
{
file: 'lib/index.js',
format: 'cjs',
},
{
file: 'es/index.js',
format: 'esm',
},
{
file: 'umd/index.js',
format: 'umd',
// script标签的形式引入时,全局变量的模块名
name: 'utils',
},
],
plugins: [
resolve(), // 这样 Rollup 能找到 `ms`
commonjs(), // 这样 Rollup 能转换 `ms` 为一个ES模块
eslint({
throwOnError: true,
throwOnWarning: true,
include: ['src/**'],
exclude: 'node_modules/**',
}),
typescript(),
babel({
runtimeHelpers: true, // 使plugin-transform-runtime生效
exclude: 'node_modules/**', // 防止打包node_modules下的文件
}),
isPro && terser()
]
};修改package.json文件
a. 指定各种模块格式打包产物的入口文件
json1
2
3
4
5{
"main": "lib/index.js",
"module": "es/index.js",
"browser": "umd/index.js",
}b. 配置运行脚本
json1
2
3
4"scripts": {
"dev": "rollup -c -w",
"build": "NODE_ENV=production rollup -c"
}
完善配置文件
添加eslint配置文件
a. .eslintrc.js
javascript1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29module.exports = {
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": ['plugin:@typescript-eslint/recommended'],
"parser": '@typescript-eslint/parser',
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly",
"ENV": true
},
"parserOptions": {
"ecmaVersion": 11,
"sourceType": "module"
},
"rules": {
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
'linebreak-style': 'off',
}
};b. .eslintignore
plaintext1
2
3
4/example/
/es/
/lib/
/umd/添加babel配置文件
.babelrc
json1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"chrome": "49",
"firefox": "65",
"safari": "12",
"node": "current"
},
"modules": false,
"useBuiltIns": "usage",
"corejs": "3"
}
]
],
"plugins": [
"@babel/plugin-transform-runtime"
],
"ignore": [
"node_modules/**"
]
}添加typescript配置文件
tsconfig.json
json1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31{
"compilerOptions": {
"baseUrl": ".",
"outDir": "./lib", // 输出目录
"sourceMap": false, // 是否生成sourceMap
"target": "esnext", // 编译目标
"module": "esnext", // 模块类型
"moduleResolution": "node",
"allowJs": false, // 是否编辑js文件
"strict": true, // 严格模式
"noUnusedLocals": true, // 未使用变量报错
"experimentalDecorators": true, // 启动装饰器
"resolveJsonModule": true, // 加载json
"esModuleInterop": true,
"removeComments": false, // 删除注释
"declaration": true, // 生成定义文件
"declarationMap": false, // 生成定义sourceMap
"declarationDir": "./lib/types", // 定义文件输出目录
"lib": [
"esnext",
"dom"
], // 导入库类型定义
"types": [
"node",
"jest",
] // 导入指定类型包
},
"include": [
"src/*" // 导入目录
]
}添加git和npm配置文件
a. .gitignore
plaintext1
2node_modules/
package-lock.jsonb. .npmignore (可以在npm发布的时候不提交相关内容)
plaintext1
2
3
4
5
6
7
8__test__/
example/
src/
.babelrc
.eslintignore
.eslintrc.js
rollup.config.js
tsconfig.json
添加单元测试
安装相关依赖:
- jest是测试库;
- @types/jest是jest对typescript的类型支持;
- babel-jest转换测试代码中高级语法;
ts-jest转换测试代码中typescript语法;
bash1
npm install --save-dev jest @types/jest babel-jest ts-jest
package.json文件中添加jest测试配置,使能够运行ts语法的测试代码;并在 “scripts” 配置中添加测试的命令:“test”: “jest”
json1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18{
"jest": {
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"testMatch": [
"<rootDir>/__test__/**/?(*.)(spec|test).ts?(x)"
]
},
"scripts": {
"test": "jest"
}
}添加测试代码
/__test__/sort/bubble.test.ts
typescript1
2
3
4
5import bubbleSort from '../../src/sort/bubble'
test('冒泡排序:正确排序数组 [1, 3, 2, 2, 2]', () => {
expect(bubbleSort([1, 3, 2, 2, 2]).toString()).toEqual([1, 2, 2, 2, 3].toString());
});运行测试命令
bash1
npm run test
结果:
bash1
2
3
4
5
6
7
8
9
10
11
12
13
14
15$ npm test
> @shengshunyan/utils@1.0.2 test
> jest
ts-jest[config] (WARN) There is a mismatch between your NodeJs version v12.18.2 and your TypeScript target ESNext. This might lead to some unexpected errors when running tests with `ts-jest`. To fix this, you can check https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping
ts-jest[config] (WARN) There is a mismatch between your NodeJs version v12.18.2 and your TypeScript target ESNext. This might lead to some unexpected errors when running tests with `ts-jest`. To fix this, you can check https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping
PASS __test__/sort/selection.test.ts
PASS __test__/sort/bubble.test.ts
Test Suites: 2 passed, 2 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 3.022 s
Ran all test suites.
添加库使用示例
根目录创建 /example 文件夹,里面放置库的使用示例
以script标签引入为例
/example/01 script/index.html
1 |
|
更新 README.md 文件
一般npm包README需要包含以下几项:
- Introduction
- Installation
- Usage
- Testing
- License
- Keywords
发布流程
先去npm 注册个账号,然后在命令行使用
bash1
npm adduser # 根据提示输入用户名密码即可
发布包 (注意:使用npm的源不要使用其他如:taobao)
bash1
2# 如果你的库名是 @name/subname,且按公开库发布,在运行 npm 发布命令时要加参数:npm publis --access public
npm publish