前言
平时总会在项目中引用各种社区的 React 组件,也会在自己的项目中封装可重用的组件,但是一直不知道怎么把组件发布到 npm。正好最近项目对 Toast 的需求比较大,搜索后也没发现可用的轻量级组件,于是干脆自己撸一个发到 npm 练手。
准备
- 在编写一个社区组件之前,最重要的一点是要先构思好组件的 API,因为我们的组件是给别人用的,所以怎么用最方便,最优雅,都是需要提前考虑好的。我相信大家都遇到过搜到一个组件的文档后由于其冗长的篇幅和难用性而放弃使用的,因此这是最最重要的一点,与人方便与己方便。
- 其次,想好组件的名字,一个简单有辨识度的名字也是组件易用性的标准之一。
步骤
这篇文章只记录我在发布时觉得关键的步骤,完整的代码可以去我的 查看。
-
两个文件夹
src 下放组件对应的代码,通常是一个单入口的 index.js 还有其他子组件。 example 下放使用组件的示例代码,通常会是一个静态的网页,用于展示效果 -
webpack 编译
组件基于 es6 + jsx 语法,所以编译是在所难免的,由于我的项目最终需要编译部署到 github pages,所以我用了两套 webpack 配置,一套用于本地起 dev server,一套部署上线。下面只贴起本地服务的配置:
const path = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const webpack = require('webpack');module.exports = { mode: 'development', entry: './example/src/index.js', output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') }, devtool: 'cheap-module-source-map', devServer: { contentBase: './example', compress: true, clientLogLevel: 'none', hot: true, port: 3001 }, resolve: { extensions: ['.js', '.jsx'] }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, loader: 'babel-loader', options: { cacheDirectory: true } }, { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }, plugins: [ new HtmlWebpackPlugin({ inject: true, template: path.resolve(__dirname, 'example/index.html') }), new webpack.HotModuleReplacementPlugin() ], performance: false};复制代码
由于我的项目只有 css 和 js,没有图片等其他静态资源,所以只需要简单的两个 loader,其他的按需引用。
- eslint 代码校验 代码校验现在已经是前端工程化的标配了,不仅能及早的发现一些低级错误,也能规范自己的代码风格,显著提升开发体验。下面是我的 eslint 配置文件:
module.exports = { // 代码执行环境,如在浏览器端可以不提示 document, window 等全局对象未定义 env: { browser: true, es6: true, node: true }, plugins: ['react'], extends: ['eslint:recommended', 'plugin:react/recommended'], // 由于 react 用到了部分不在 es 标准中的语法,因此需要 babel 解析 parser: 'babel-eslint', parserOptions: { sourceType: 'module', ecmaFeatures: { jsx: true } }};复制代码
- babel 编译成待发布模块 代码写好了之后,测试也没问题,那么如何将写好的模块编译后发布呢?我搜了好多文章有直接用 webpack 打包的也有用 babel cli 编译的,然后翻了下社区流行组件的源码多是用 babel 直接编译的,所以就参考了一篇文章(参考见文末)开撸。
运行以下命令安装所需模块:
npm install --save-dev babel-cli babel-core babel-preset-env babel-preset-react-app复制代码
babel 配置文件:
{ "presets": ["env", "react-app"]}复制代码
最后,在 package.json
里加这么一段 npm script:
{ "scripts": { "compile": "NODE_ENV=production babel src --out-dir lib" }}复制代码
NODE_ENV=production
这段语句是 babel-preset-react-app
要求的,指明 node 的执行环境,方便内部进行优化处理;后面的 babel 命令则是把 src 文件夹下对应的代码编译后输出到同层的 lib 目录下。
npm run compile
就可以看到编译后的代码了,这些代码就是最终我们发布到 npm 上的组件。 - 使用
npm link
测试你的组件 当你的组件编译完成之后,在发布到 npm 上之前,还可以在本地的其他项目中对此组件进行测试。首先在package.json
里指定组件的入口文件:
{ "main": "lib/index.js"}复制代码
然后运行 npm link
,这样你的组件会被关联到本地的全局 node_modules 中去,然后在另一个项目里运行 npm link light-toast
( light-toast 替换为你的组件名),这样你就可以在本地的项目里 import 你的组件了。
-
Readme
组件是给自己和别人用的,那么一个简洁且易懂的 readme 是必不可少的,作为他人了解你代码的窗口,切记要写的通俗,一段冗长的说明文档会瞬间降低一个人使用此组件的兴趣。 -
发布
首先我们需要一个.npmignore
文件来指定哪些文件是不需要发布到 npm 上的,可根据自身需要修改。
examplesrc.babelrc.eslintrc.js.gitignore.prettierignorewebpack.config.jswebpack.config.prod.js复制代码
其次添加一个 LICENSE
文件,至于为啥需要这个了解下前段时间 react 因为协议闹出的不愉快就知道了,不过开源大部分都用 MIT 协议,直接找一份现成的拷过来就行了。
然后,修改下我们刚刚的 script:
{ "scripts": { "prepublishOnly": "NODE_ENV=production babel src --out-dir lib" }}复制代码
prepublishOnly
是 npm 提供的一个钩子,在执行 npm publish
之前执行,这里方便我们每次发布的时候自动编译代码。
最后,修改下 package.json
里的相关信息,比如组件的版本号,关键词,git 仓库等等,最重要的一点,把 react 和 react-dom 这两个依赖移到 peerDependencies
里去,这样不会导致依赖重复解析的问题。
现在,你终于可以发布你的第一个 react 组件了!等等,发布前你还需要先注册一个 npm 账号,运行 npm adduser
根据提示进行操作,然后运行 npm publish
,提示发布成功后你就可以在 npm 仓库里搜到你自己的组件啦~
- 用 Github Pages 托管 demo 如果你的项目是一个 UI 组件,那么最好你可以提供一个在线预览的地址,这样他人可以直观的看到运行效果,也会为你的项目加分不少。假设我们打包后静态 demo 的目录是在 dist 下面,里面包含一个
index.html
模板和一个index.js
入口,运行npm install --save-dev gh-pages
,这是一个可以将我们的代码推到 gh-pages 分支的包。然后在package.json
里添加以下脚本:
{ "scripts": { "deploy": "gh-pages -d dist" }}复制代码
运行 npm run deploy
就可以把 demo 发布到 Github Pages 上去了。
总结
本文是我自己第一次发布一个 React 组件的总结,其中也搜索了很多资料,希望能给大家一些帮助,让大家少走弯路,多多为开源社区做贡献。
顺便也厚脸皮的贴上我自己写的轻量级 Toast 组件的地址,求个 star ~ 如果你正在寻找一个小巧、不需要任何附加样式的 Toast 组件,那么这就是对的人。参考文章: