發佈 react 組件到 npm 上

我發佈了我的第一個 npm 組件,一個基於 react 的 3d 標籤雲組件。在這途中我也是遇到了很多的坑,花在完善整個發佈流程的時間遠多於寫這個組件本身的時間,所以我記錄下我覺得一個正常的 react 組件的發佈流程

最後記錄這篇文章花的時間比我完成整個組件的時間都多,最終希望能給新手帶來幫助

在整個發佈組件的過程我做了如下幾件事兒:

  1. 開發組件
  2. 編寫 Readme
  3. 推送到 github,並且把 demo 放到 github page 上
  4. 發佈組件到 npm 上

開發組件

創建項目文件夾並初始化 npm package ,確保你創建的組件名稱沒有在 npm 上被使用過, 這裏我們用 react-demo 作爲示例

mkdir react-demo
cd react-demo
npm init

npm init 是生成初始的 package.json 的命令,在 npm init 的時候,你可以根據你自己的需要進行填寫你的組件信息。或者直接使用 npm init -y 採用默認的,後面自己再去修改。

首先安裝 react 相關的包:

npm i react react-dom -D

採用 babel 編譯相關的依賴:

npm i @babel/cli @babel/core @babel/preset-env @babel/preset-react -D

採用 webpack 做構建,webpack-dev-server 作爲本地開發服務器,所以需要安裝如下依賴:

npm i webpack webpack-cli webpack-dev-server -D

我這裏爲了簡單演示,只安裝 babel-loader 用來編譯 jsx,其他 loader 安裝自己的需要自己安裝。

npm i babel-loader -D

另外再安裝一個 webpack 插件 html-webpack-plugin ,用來生成 html:

npm i html-webpack-plugin -D

然後再添加上常規的 startbuild 腳本,package.json 如下:

{
  "name": "react-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open development",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.2.3",
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "webpack": "^4.29.0",
    "webpack-cli": "^3.2.1",
    "webpack-dev-server": "^3.1.14"
  },
  "dependencies": {}
}

當然,你也可以直接把我這個 package.json 複製過去,然後 npm install 進行依賴的安裝,也可以一個一個的安裝。

一個最基本的組件只需要編譯 jsx,所以我這裏沒有安裝 css 以及處理其他的 loader,這篇文章的重點不是講 webpack 的,所以其他的自行解決,有 webpack 問題可以私聊我。

然後我們再創建如下的目錄結構:

├── example // 示例代碼,在自己測試的時候可以把測試文件放到 src 裏
│   └── src // 示例源代碼
│       ├── index.html // 示例 html
│       └── app.js // 添加到 react-dom 的文件
├── package.json 
├── src // 組件源代碼
│   └── index.js // 組件源代碼文件
├── .babelrc
├── .editorconfig // 不必須的,但是建議有
├── .gitignore // 如果要放到 github 上,這個是需要有的
└── webpack.config.js

下面我們再創建一個最簡單的組件,來進行演示:

/*** src/index.js ***/
import React from 'react';
const ReactDemo = () => (
 <h1>這是我的第一個 react npm 組件</h1>
);
export default ReactDemo;

接下來添加一個 demo

<!-- examples/src/index.html -->
<html>
<head>
    <title>My First React Component</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
    <div id="root"></div>
</body>
</html>
/*** examples/src/app.js ***/
import React from 'react'
import { render } from 'react-dom'
import ReactDemo from '../../src'

const App = () => <ReactDemo />
render(<App />, document.getElementById('root'))
注意 demo 中的 ReactDemo 是從 ../../src 中導入的

接下來配置非常簡單的 webpack, 在項目根路徑下創建 webpack.config.js 文件

const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const htmlWebpackPlugin = new HtmlWebpackPlugin({
    template: path.join(__dirname, "./example/src/index.html"),
    filename: "./index.html"
});

module.exports = {
    entry: path.join(__dirname, "./example/src/app.js"),
    output: {
        path: path.join(__dirname, "example/dist"),
        filename: "bundle.js"
    },
    module: {
        rules: [{
            test: /\.(js|jsx)$/,
            use: "babel-loader",
            exclude: /node_modules/
        }]
    },
    plugins: [htmlWebpackPlugin],
    resolve: {
        extensions: [".js", ".jsx"]
    },
    devServer: {
        port: 3001
    }
};

Webpack 的配置文件主要做了如下事情:

  • 使用 example/src/index.js 作爲項目入口,處理資源文件的依賴關係
  • 通過 babel-loader 來編譯處理 js 和 jsx 文件
  • 通過 html-webpack-plugin 自動注入編譯打包好的腳本文件
  • 爲 demo 啓動端口爲 3001 的服務

然後再配置一下 babel,咱們的 babel 主要做兩件事,將 jsx 編譯成 es5,然後再加一個通用的 env,所以 .babelrc 配置如下:

{
    "presets": ["@babel/preset-env", "@babel/preset-react"]
}

可以看到之前的 package.json ,我這裏 babel 安裝的是 7.x,那麼 babel-loader 就應該是 8.x 才行,然後 babel 7.x 相對於之前的配置是不同的,要用這個配置,版本一定要跟我的相同,不然配置可能會不一樣。

然後現在執行 npm start,然後再訪問 localhost:3001 就可以訪問到了。

編寫 README

編寫 README,如果你不知道該如何編寫,我給你提幾點建議,你可以選擇你覺得必要的點來寫:

  1. logo
  2. 官方主頁
  3. 介紹
  4. 安裝
  5. 快速開始
  6. 功能列表
  7. 截圖
  8. todoList
  9. 不足之處
  10. FAQ
  11. Change Log(更新日誌)

添加徽章

當你寫完 README 之後,我們將添加一些來自 shields.io 的時髦徽章,讓人們知道我們又酷又專業。

想添加什麼樣的徽章看自己喜歡吧,種類有很多。

可以點擊這裏看我之前寫的 3d 標籤雲的 README。

現在基本上可以發佈了,但是要是能提供一個在線的 demo 讓別人在用這個組件的時候可以看到效果就更好了。

在 GitHub Pages 上發佈一個在線 demo

發佈在線 demo 可以直接用 Github Pages 來幫助我們託管,通過 webpack 構建生產環境版本,然後發到 Github 上去即可。

首先去 Github 創建一個用來存放你組件代碼的倉庫。

然後把你的項目初始化成 git 項目:

git init

再添加遠程倉庫,將本地倉庫和遠程倉庫關聯起來。

git remote add origin [email protected]:crazylxr/react-demo.git

接下來我們可以安裝 gh-pages 來幫助我們發佈到 github pages:

npm i gh-pages -D

爲了方便記憶,後續能更快的發佈,這些命令我們可以寫成 npm-scriprt,所以我們增加兩個腳本:

{
  "name": "@taoweng/react-demo",
  "version": "1.0.0",
  "description": "react demo",
  "main": "lib/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open development",
    "build": "webpack --mode production",
    "deploy": "gh-pages -d examples/dist",
    "publish-demo": "npm run build && npm run deploy"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.2.3",
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "gh-pages": "^2.0.1",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "webpack": "^4.29.0",
    "webpack-cli": "^3.2.1",
    "webpack-dev-server": "^3.1.14"
  },
  "dependencies": {}
}

添加了 deploy 腳本和 publish-demo,以後需要發佈 demo 的時候只需要 npm run publish-demo 即可。

然後我們就可以 build 項目之後再將 expamples/dist 發佈到 gh-pages 分支:

npm run build
npm run deploy

或者直接

npm run publish-demo
注意:這裏只會將 expample/src 下的文件發佈到 ph-pages 分支,master 分支依然沒有到 github 上,如果你要把源碼放到 github 的 master 或者其他分支上,還是需要自己 push 的。

這個時候,我們可以通過 crazylxr.github.io/react-demo 訪問到我們寫的 demo。crazylxr 是 github 的 username,react-demo 是倉庫名,注意改成你自己的。

編譯源碼

我們現在的源碼是 jsx 的,所以我們需要通過 babeljsx 編譯爲正常瀏覽器能訪問的代碼。我們可以通過 babel-cli 來編譯我們代碼,直接編譯 src 目錄,到 lib 文件夾。更多命令見 babel-cli

npx babel src --out-dir lib

執行完這個命令,就把生成一個 lib 文件夾,然後裏面的 index.js 就是編譯過後的文件,是可以直接發佈到 npm 的文件。

然後將這個編譯命令寫到 script 裏,package.json 如下:

{
  "name": "@taoweng/react-demo",
  "version": "1.0.0",
  "description": "react demo",
  "main": "lib/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open development",
    "build": "webpack --mode production",
    "compile": "npx babel src --out-dir lib",
    "deploy": "gh-pages -d example/dist",
    "publish-demo": "npm run build && npm run deploy"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.2.3",
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "gh-pages": "^2.0.1",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "webpack": "^4.29.0",
    "webpack-cli": "^3.2.1",
    "webpack-dev-server": "^3.1.14"
  },
  "dependencies": {}
}

那麼以後要編譯 src 下面的代碼,只需要執行:

npm run compile

現在我們已經有編譯好的代碼了,接下來就可以發佈到 npm 供其他人使用了。

發佈 npm 包

在發佈以前我們是需要一些準備:

註冊 npm 賬戶:

在這裏](https://www.npmjs.com/) 註冊一個 npm 賬號。

登錄

在終端輸入:

npm adduser

也可以用:

npm login

然後你會得到一個讓你輸入usernamepasswordemail 的提示,把它們填在相應的位置。

關於 package.json 需要注意的點

package.json 裏面的配置信息非常重要,我解釋一下幾個重要的配置。

  • name: 包名,如果你學習的話建議加一個 scoped,就是我上面的 @taoweng/react-demo 而不是 react-demo,因爲 npm 包特別的多,很容易重複。這樣這個包就會是私有的,可以通過 npm publish --access=public 將這個包變爲共有的包。
  • version: 包的版本,每次發佈包的版本不能和上次一樣。詳細規範可見這裏
  • description:包的簡介。
  • repository:適合寫 Github 地址,建議寫成::username/:repository
  • license:認證。不知道該用什麼的,就寫MIT 吧。
  • main:包的入口文件。就是引入這個包的時候去加載的入口文件。
  • keywords:添加一些關鍵詞更容易使你的包被搜索到。

更詳細的 package.json 配置可見官網

我這裏簡單的添加了這些信息:

{
  "name": "@taoweng/react-demo",
  "version": "1.0.0",
  "description": "react demo",
  "main": "lib/index.js",
  "repository": "crazylxr/react-demo",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open development",
    "build": "webpack --mode production",
    "compile": "npx babel src --out-dir lib",
    "deploy": "gh-pages -d example/dist",
    "publish-demo": "npm run build && npm run deploy"
  },
  "keywords": ["react", "demo"],
  "author": "taoweng",
  "license": "MIT",
  "devDependencies": {
    "@babel/cli": "^7.2.3",
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "gh-pages": "^2.0.1",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "webpack": "^4.29.0",
    "webpack-cli": "^3.2.1",
    "webpack-dev-server": "^3.1.14"
  },
  "dependencies": {}
}

這些配置信息都會在 npm 包的頁面顯示出來的,所以能填還是填一下:

最後我們在項目中添加 .npmignore 文件,跟 .gitignore 的作用一樣,就是在發佈 npm 的時候需要忽略的文件和文件夾:

# .npmignore 
src
examples
.babelrc
.gitignore
webpack.config.js

這個時候我們就可以發佈到 npm 了:

npm publish

如果你是私有包,可以這樣發佈:

npm publish --access=public

結語

以後發佈新版本的時候,只需要更改一下 package.json 裏面的 version 版本號,然後執行 npm publish 和 npm run publish-demo 就可以同步 npm 和 demo。

不過如果想讓你的組件在社區裏給更多人用,你需要把 README 寫得更好一點,然後添加好自動化測試,不然別人不太敢用。

另外在寫組件之前可以先了解下有沒有類似的組件了,如果有就直接用吧,咱們就站在巨人的肩膀上,把自己寶貴的時間放在創造價值上。

最後整個項目的源代碼見 github

參考文章

另外

同時你也可以在這些地方找到這篇文章:

  1. 個人網站
  2. github blog

另外有興趣可以關注我的公衆號:前端桃園

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章