如何优化组件库的package.json

开发一个组件库,最后一步是将组件库发布到 npm 上。这样,全世界的开发者就可以直接安装使用。如何让其他开发者在使用我们的组件库时能够安装更快、体验更好呢?这里,除了优化组件库本身的代码外,还可以通过优化组件库的 package.json 来实现。

开发环境

  • create-react-app
  • react 16.8.0+
  • typescript 4.5.5
  • jest
  • testing-library
  • sCSS
  • storybook
  • eslint
  • husky
  • ……

优化前的 package.json

内容有点长,和我们平时使用的基本一致,可以简单看一下就行。主要用于前后对比。

{
  "name""vikingship",
  "version""0.1.0",
  "private"true,
  "scripts": {
    "start""react-scripts start",
    "build""npm run build-ts && npm run build-css",
    "test""react-scripts test",
    "eject""react-scripts eject",
    "build-ts""tsc -p tsconfig.build.json",
    "build-css""node-sass ./src/styles/index.scss ./dist/index.css",
    "lint""eslint -c .eslintrc.js --ext .js,.jsx,.ts,.tsx",
    "lint:fix""npm run lint -- --fix",
    "storybook""start-storybook -p 6006 -s public",
    "build-storybook""build-storybook -s public"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "dependencies": {
    "@fortawesome/fontawesome-svg-core""^1.3.0",
    "@fortawesome/free-solid-svg-icons""^6.0.0",
    "@fortawesome/react-fontawesome""^0.1.17",
    "@testing-library/jest-dom""^5.16.2",
    "@testing-library/react""^12.1.2",
    "@testing-library/user-event""^13.5.0",
    "@types/classnames""^2.3.1",
    "@types/jest""^27.4.0",
    "@types/node""^16.11.22",
    "@types/react""^17.0.39",
    "@types/react-dom""^17.0.11",
    "@types/react-transition-group""^4.4.4",
    "@types/storybook__addon-info""^5.2.4",
    "axios""^0.26.0",
    "classnames""^2.3.1",
    "node-sass""^7.0.1",
    "react""^17.0.2",
    "react-dom""^17.0.2",
    "react-scripts""5.0.0",
    "react-transition-group""^4.4.2",
    "typescript""^4.5.5",
    "web-vitals""^2.1.4"
  },
  "devDependencies": {
    "@storybook/addon-actions""^6.4.19",
    "@storybook/addon-docs""^6.4.19",
    "@storybook/addon-essentials""^6.4.19",
    "@storybook/addon-info""^5.3.21",
    "@storybook/addon-interactions""^6.4.19",
    "@storybook/addon-links""^6.4.19",
    "@storybook/builder-webpack5""^6.4.19",
    "@storybook/manager-webpack5""^6.4.19",
    "@storybook/node-logger""^6.4.19",
    "@storybook/preset-create-react-app""^4.0.1",
    "@storybook/preset-scss""^1.0.3",
    "@storybook/react""^6.4.19",
    "@storybook/testing-library""^0.0.9",
    "css-loader""^6.6.0",
    "react-docgen""^5.4.0",
    "sass""^1.49.9",
    "sass-loader""^12.6.0",
    "style-loader""^3.3.1",
    "webpack""^5.69.1"
  },
  "eslintConfig": {
    "overrides": [
      {
        "files": [
          "**/*.stories.*"
        ],
        "rules": {
          "import/no-anonymous-default-export""off"
        }
      }
    ]
  }
}

优化步骤

移除之前 build 生成的文件夹

初始化 package.json 中的 build,每个在执行 npm run build 时,都会在 dist 文件夹下重新生成构建好的文件内容。但这有一个问题,如果我组件库中的一个组件已经删除了,但是之前构建在 dist 目录下的对应的组件文件依然存在。所以,我们需要在 build 之前,删除掉之前的 dist 文件夹。

由于不同的系统,删除文件夹的命令不一致,所以这里借助一个叫 rimraf 的工具来进行。

执行命名

npm install rimraf --save-dev

安装好 rimraf 后,修改 build 命令如下所示:

"script": {
...
- "build": "npm run build-ts && npm run build-css",
+ "clean": "rimraf ./dist",
+ "build": "npm run clean && npm run build-ts && npm run build-css",
...
},
"devDependencies": {
...
+ "rimraf": "^3.0.2",
...
}

添加基本信息

因为组件库需要提供给其他开发者使用,所以需要设置项目private: false,指定组件库不是私有的,是公开的。需要的其它信息还包括:

  • description 组件的描述
  • author 作者
  • main 入口文件
  • module 导出的模块文件
  • types 对应的 ts 定义文件
  • license 遵循的开源协议
  • keywords 关键字,方便其他人搜索使用
  • homepage / repository 项目对应的 Git 仓库地址
  • files 指定哪些文件 / 文件夹需要上传到 npm
{
...
- "private": true,
+ "private": false,
+ "description": "这里是包的描述内容",
+ "author": "作者名字",
+ "main": "dist/index.js",
+ "module": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "license": "MIT",
+ "keywords": [
+   "component",
+   "UI",
+   "React"
+ ],
+  "homepage": "https://github.com/xiangming25/vikingship.git",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/xiangming25/vikingship.git"
+  },
+  "files": [
+    "dist"
+  ],
...
}

发布之前执行构建命令

"script": {
    ...
+    "prepublish": "npm run build"
    ...
}

精简 package.json 依赖

初始化项目时,有许多的包都是放在 dependencies 下面的,这样在 npm install 时,都会进行下载安装。但像 @types/* 下面的定义文件、将 scss 处理为 cssnode-sass、开发时需要启动服务的 react-scripts、以及帮助我们提高代码质量和效率的 typescript 等。这些都只是我们在开发过程中需要用到,在发布后的组件库中完全不需要用到它们,所以这里对依赖项的位置进行调整,将只在开发环境中用到的组件放在 devDependencies 中。

{
...
"dependencies": {
    ...
-    "@types/classnames": "^2.3.1",
-    "@types/jest": "^27.4.0",
-    "@types/node": "^16.11.22",
-    "@types/react": "^17.0.39",
-    "@types/react-dom": "^17.0.11",
-    "@types/react-transition-group": "^4.4.4",
-    "@types/storybook__addon-info": "^5.2.4",
-    "node-sass": "^7.0.1",
-    "react-scripts": "5.0.0",
-    "typescript": "^4.5.5",
    ...
},
"devDependencies": {
    ...
+    "@types/classnames": "^2.3.1",
+    "@types/jest": "^27.4.0",
+    "@types/node": "^16.11.22",
+    "@types/react": "^17.0.39",
+    "@types/react-dom": "^17.0.11",
+    "@types/react-transition-group": "^4.4.4",
+    "@types/storybook__addon-info": "^5.2.4",
+    "node-sass": "^7.0.1",
+    "react-scripts": "5.0.0",
+    "typescript": "^4.5.5",
    ...
},
...
}

优化 react & react-dom

组件库的 react 版本可能不能与其他开发者使用的 react 版本完全一致,如果不一致,就又会下载安装一次,并且还会出现一些奇怪的问题。所以我们可以将 react 以及 react-dom 放在 peerDependencies 中。这样就可以告诉用户,我们需要的最低版本是多少,只要开发者的实际项目满足最低版本要求就行。

{
    ...
    "dependencies": {
-        "react": "^17.0.2",
-        "react-dom": "^17.0.2",
    }
    ...
+     "peerDependencies": {
+        "react": ">=16.8.0",
+        "react-dom": ">=16.8.0",
+      }
    ...
    "devDependencies": {
    ...
+        "react": "^17.0.2",
+        "react-dom": "^17.0.2",
    ...
    }
  },
}

注意为什么又将 react 以及 react-dom 放在了 devDependencies 下面。这是因为放在 peerDependencies 下面可以满足使用组件的人能够正常运行,但是我们在开发调试时,就不能正常运行了。所以需要将 reactreact-dom 添加在 devDependencies 下面。

添加组件测试&风格检测

默认使用 react-scripts test 对代码进行测试,会在控制台中一直处于 watch 状态,控制台一直会卡在那里,不会有任何的返回值。查阅文档如果先设置环境变量为 CI=true,就不会一直处于 watch 状态,直接就会有测试结果的返回值。

问题又来了。在不同的系统设置环境变量的方式又是不一样,所以我们又需要借助 cross-env 工具来实现。

安装 cross-env

npm install cross-env -D

添加 test 命令

{
    ...
+    "test:nowatch": "cross-env CI=true react-scripts test",
-    "prepublish": "npm run build",
+    "prepublishOnly": "npm run test:nowatch && npm run lint && npm run build"
    ...
    "devDependencies": {
        ...
+        "cross-env": "^7.0.3",
        ...
    }
}

注意这里为什么将 prepublish 修改为 prepublishOnly。原因是因为 prepublishnpm install 时也会执行,这不是我们预期的效果。所以使得 prepublishOnly 来进行实现。

添加 husky

为了保证在开发过程中就对代码质量有所保证。我们在 git 提交时,就对组件进行测试以及对代码风格进行检查。这里我们使用到一个新的工具 husky

执行命令安装 husky

npm install husky -D

在项目中使用 husky

npm set-script prepare "husky install"
npm run prepare

添加钩子方法

npx husky add .husky/pre-commit "npm run test:nowatch && npm run lint"
git add .husky/pre-commit

husky 不同版本的设置方法可能不同,大家可以根据自己实际使用的版本进行配置。

{
...
+  "husky": {
+    "hooks": {
+      "pre-commit": "npm run test:nowatch && npm run lint"
+    }
+  },
    "devDependencies": {
        ...
+        "husky": "^7.0.4",
        ...
    }
...
}

husky 仓库的地址为:https://github.com/typicode/husky

最终的 package.json

{
  "name""vikingship",
  "version""0.1.0",
  "private"false,
  "description""这里是包的描述内容",
  "author""xiangming",
  "main""dist/index.js",
  "module""dist/index.js",
  "types""dist/index.d.ts",
  "license""MIT",
  "keywords": [
    "component",
    "UI",
    "React"
  ],
  "homepage""https://github.com/xiangming25/vikingship.git",
  "repository": {
    "type""git",
    "url""https://github.com/xiangming25/vikingship.git"
  },
  "files": [
    "dist"
  ],
  "scripts": {
    "start""react-scripts start",
    "clean""rimraf ./dist",
    "build""npm run build-ts && npm run build-css",
    "test""react-scripts test",
    "test:nowatch""cross-env CI=true react-scripts test",
    "eject""react-scripts eject",
    "build-ts""tsc -p tsconfig.build.json",
    "build-css""node-sass ./src/styles/index.scss ./dist/index.css",
    "lint""eslint -c .eslintrc.js --ext .js,.jsx,.ts,.tsx src --max-warnings 5",
    "lint:fix""npm run lint -- --fix",
    "storybook""start-storybook -p 6006 -s public",
    "build-storybook""build-storybook -s public",
    "prepublishOnly""npm run test:nowatch && npm run lint && npm run build",
    "prepare""husky install"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "dependencies": {
    "@fortawesome/fontawesome-svg-core""^1.3.0",
    "@fortawesome/free-solid-svg-icons""^6.0.0",
    "@fortawesome/react-fontawesome""^0.1.17",
    "@testing-library/jest-dom""^5.16.2",
    "@testing-library/react""^12.1.2",
    "@testing-library/user-event""^13.5.0",
    "axios""^0.26.0",
    "classnames""^2.3.1",
    "react-transition-group""^4.4.2",
    "web-vitals""^2.1.4"
  },
  "peerDependencies": {
    "react"">=16.8.0",
    "react-dom"">=16.8.0"
  },
  "devDependencies": {
    "@storybook/addon-actions""^6.4.19",
    "@storybook/addon-docs""^6.4.19",
    "@storybook/addon-essentials""^6.4.19",
    "@storybook/addon-info""^5.3.21",
    "@storybook/addon-interactions""^6.4.19",
    "@storybook/addon-links""^6.4.19",
    "@storybook/builder-webpack5""^6.4.19",
    "@storybook/manager-webpack5""^6.4.19",
    "@storybook/node-logger""^6.4.19",
    "@storybook/preset-create-react-app""^4.0.1",
    "@storybook/preset-scss""^1.0.3",
    "@storybook/react""^6.4.19",
    "@storybook/testing-library""^0.0.9",
    "@types/classnames""^2.3.1",
    "@types/jest""^27.4.0",
    "@types/node""^16.11.22",
    "@types/react""^17.0.39",
    "@types/react-dom""^17.0.11",
    "@types/react-transition-group""^4.4.4",
    "@types/storybook__addon-info""^5.2.4",
    "babel-eslint""^10.1.0",
    "cross-env""^7.0.3",
    "css-loader""^6.6.0",
    "husky""^7.0.4",
    "node-sass""^7.0.1",
    "react""^17.0.2",
    "react-docgen""^5.4.0",
    "react-dom""^17.0.2",
    "react-scripts""5.0.0",
    "rimraf""^3.0.2",
    "sass""^1.49.9",
    "sass-loader""^12.6.0",
    "style-loader""^3.3.1",
    "typescript""^4.5.5",
    "webpack""^5.69.1"
  },
  "eslintConfig": {
    "overrides": [
      {
        "files": [
          "**/*.stories.*"
        ],
        "rules": {
          "import/no-anonymous-default-export""off"
        }
      }
    ]
  }
}

总结

最近重新学习了一遍组件库的开发,对组件的开发又有了许多新的认识。很多需求都可以渐进式开发,并不是一来就能想得非常的全面,很多时候都是在做的过程中不断升级优化,然后越来越好。



原文始发于微信公众号(前端学习总结):如何优化组件库的package.json

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/83090.html

(0)

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!