使用npm發佈一個vue組件

前言

這是一篇包教不包會的npm發佈教程,爲了不不少文章中的分享,跟着一步步作,最後發包失敗。。時間沒了,搞得心情都很差了。css

所以,在寫這篇文章的同時[2019-08-18]我從新創建一個npm包,按照如下的流程,發佈了一個npm包,也測試可用,因此童鞋們能夠放心跟着一步步走,學會發布npm包。發包的項目代碼在這裏已經發布上線的npm包地址在這裏html

​ 相信前端er對npm包不會陌生,npm 原本是 Node.js 的包管理工具,但隨着 JS 這幾年的蓬勃發展,如今的 npm 已經成了幾乎全部跟 JS 相關的工具和軟件包的管理工具了,此次也會從0到1的走一遍發包的流程,前端

一、本文是以vue項目爲例子進行講解,流程可通用,只是具體項目的安裝有些許區別,無論vue仍是react,相信對你們都有幫助vue

二、⚠️提示: 爲了讓童鞋們理解發包的流程和配置,因此仍是建議按照步驟(1)-(10)的順序來操做,爲了突出整個發包流程,因此封裝的測試組件很是簡單。待理解全部文件的內容和具體原理,併成功發出一個測試npm包後,童鞋們可自行更換成本身的組件,發佈屬於本身的npm包,發佈包的名字設置爲our-btnnode

初始化webpack項目 + 組件封裝 === 一鼓作氣

​ 在項目中,咱們都但願安裝的插件體積儘量的小,所以,咱們在發包的時候也要儘可能控制咱們的依賴,因此我選擇本身建立一個打包項目,而不是用笨重的vue和react腳手架。 話很少說,下面跟着作👇react

  • (1)下方是推薦的目錄結構,根據如下結構創建項目文件

可是因爲本文組件過於簡單,因此刪減assetsutils文件夾(有沒有這兩個文件夾不影響npm發包,僅僅方便你本身整理項目代碼)webpack

├── src
│ ├── assets # 本地靜態資源(本文沒有)
│ ├── components # 業務通用組件
│ │ ├── btnDemo.vue # 本文須要封裝的簡單button組件
│ ├── utils # 工具庫(本文沒有)
│ └── index.js # 應用入口 
├── .npmignore // 用於忽略不須要上傳到npm的文件
├── README.md
├── package-lock.json
├── package.json
└── webpack.config.js # webpack配置

// 注意
# utils 文件夾通常存放的是你組件常用的一些工具函數
# assets 文件夾通常存放的是你組件用到的樣式、圖片、icon等靜態資源
複製代碼
  • (2)button組件
// btnDemo.vue
<template>
  <div class="btn">
    <button>{{text}}</button>
  </div>
</template>

<script>
export default {
  name: 'btn', // 組件的name屬性(後面有提到這裏有個坑)
  props: {
    text: { // 文本
      type: String,
      default () {
        return ''
      }
    }
  },
  data () {
    return {
    }
  }
}
</script>
複製代碼
  • (3)index.js

該文件是爲了將咱們的組件暴露出去git

// src/index.js
// 這裏import 的 btn和btnDemo.vue的name屬性名相同 !

import btn from './btnDemo.vue'

btn.install = Vue => Vue.component(btn.name, btn) // 給組件配置install方法 

export default btn;
複製代碼

⚠️(這裏有個坑):因爲Vue.component(btn.name, btn)btn.name是指向btnDemo.vuename屬性,所以,建議在這裏最好用組件的name屬性值做爲import別名github

  • (4)webpack.config.js

webpack.config.js配置以下,因爲咱們使用的版本是webpack4,全部的配置都在webpack.config.js裏面,在咱們這裏僅僅須要把咱們的資源打包,寫的比較簡單,具體webpack配置細節能夠學習官方文檔web

這裏配置是用於將/src中的內容打包到/dist(打包時會自動生成/dist文件夾)中的btn.jsbtn.js其實就至關於咱們的插件(後面在package.jsonmain字段也是指向這裏)

// webpack.config.js
const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
  entry: {
    index: path.join(__dirname, "/src/index.js") // 入口文件(就是剛纔用於暴露組件的index.js)
  }, 
  output: {
    path: path.join( __dirname, "/dist"), // 打包後的文件存放在dist文件夾
    publicPath: '/dist/', // 設置公共路徑
    filename: "btn.js", // 打包後輸出文件的文件設置爲btn.js
    libraryTarget: 'umd' // 這個選項會嘗試把庫暴露給前使用的模塊定義系統,這使其和CommonJS、AMD兼容或者暴露爲全局變量
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.(scss|sass)$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.(png|jpg|svg|gif)$/,
        use: ['url-loader']
      },
      {
        test: /\.js$/,
        exclude: /node_modules|vue\/dist|vue-router\/|vue-loader\/|vue-hot-reload-api\//,
        loader: 'babel-loader'
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ]
}
複製代碼
  • (5)package.json

package.json字段以下,要強調的是,字段devDependencies中的依賴項不惟一,你能夠根據本身狀況去寫,可是此時此刻,請務必和我同樣,這也是爲了保證你能夠按照個人操做,成功發包

// 具體字段後面詳細說明
{
  "name": "our-btn", // 發佈npm包的名字
  "version": "1.0.0", // 你的npm包版本
  "description": "A test button", // 包的描述
  "main": "dist/btn.js", // *重點*:指定你組件的主入口文件
  "scripts": {
    "build": "webpack --mode production",
    "dev": "webpack-dev-server --open --mode development"
  },
  "keywords": [
    "our-btn",
    "button"
  ],
  "repository": {
    "type": "git",
    "url": "git+https://github.com/thomaszhou63/test-npm.git"
  },
  "author": "thomaszhou",
  "license": "MIT",
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "babel-preset-env": "^1.7.0",
    "css-loader": "^1.0.0",
    "file-loader": "^2.0.0",
    "style-loader": "^0.23.1",
    "url-loader": "^1.1.2",
    "node-sass": "^4.12.0",
    "sass-loader": "^7.2.0",
    "vue": "^2.5.2",
    "vue-hot-reload-api": "^2.2.4",
    "vue-html-loader": "^1.2.4",
    "vue-loader": "^15.4.2",
    "vue-style-loader": "^3.0.3",
    "vue-template-compiler": "^2.5.9",
    "webpack": "^4.19.0",
    "webpack-cli": "^3.1.0"
  }
}
複製代碼
  • 參數說明
    • name - 包名(包名應該是kebab-case, 即英文單詞全小寫或者中劃線分割)
    • version - 包的版本號(初版建議1.0.0,具體命名規則看這裏
    • description - 包的描述。在npmjs.com上搜索時會顯示,有助於用戶在搜索時進行篩選)
    • keywords - 關鍵字(在npm網站上搜索你這個npm包的關鍵詞)
    • author - 包的做者。格式通常是name <你的郵箱>,通常來講,用vue/react腳手架建立項目的時候會默認這個格式寫法, 固然也能夠是一個github地址,也能夠自定義,但就不那麼標準了
    • license - 版權許可證,MIT仍是ISC,或者其餘均可以,只是我看不少包都是MIT
    • contributors - 包的其餘貢獻者(我沒有寫這個)
    • repository - 包代碼的Repo信息,包括typeURLtype能夠是gitsvnURL則是包的Repo地址
      • 我這裏寫的git倉庫的地址,放着個人組件項目代碼,這樣在npm包頁面就有會個github的入口
    • main - 該字段指定了程序的主入口文件(最好寫dist文件夾內已經壓縮後的文件)
      • main定義了包的入口文件,在NodeJs環境中,語句import [pkg] from '[package]'時,其實導入的就是main定義的文件
    • scripts - 指定了運行腳本命令的npm命令行縮寫。如 npm startnpm run devnpm run build
    • dependencies / devDependencies - 生產/開發環境依賴包列表。它們將會被安裝在 node_module 目錄下
      • 對於一個開發者來講,dependenciesdevDependencies其實沒太多區別,由於在執行npm install/yarn add時都會所有下載
      • dependencies 是運行你的包必須安裝的依賴,即當用戶npm install [package]或者yarn add [package]時,這些依賴也會下載
      • devDependencies 是開發你的包時須要安裝的依賴,好比eslint, jest等開發工具,當用戶npm install [package]yarn add [package] 時,這些依賴並不會下載!

我這裏版本是1.0.1,是由於我本身後面迭代了一個版本,若是你是初版,最好是1.0.0

  • (6)README.md

這是個人README.md寫的東西,最終都會顯示在npm的內容介紹裏面(也就是上圖),各位童鞋若是發包,也請寫好README.md哈,畢竟是給人使用的嘛

## our-btn
>一個測試的npm包

# install

​```
npm install our-btn
​```
# use
​```
// main.js
import btn from 'our-btn'

Vue.use(btn)
​```
​```
// demo.js
<template>
  <div class="demo">
    <btn :text="msg"></btn>
  </div>
</template>

<script>
export default {
  name: 'demo',
  data () {
    return {
      msg: '成功'
    }
  }
}
</script>
​```
複製代碼
  • (7).npmignore

這個文件同.gitignore的功能同樣,.gitignore是忽略自選的文件上傳到github倉庫中,而.npmignore則是忽略自選的文件上傳到npm上。

可是呢,若是你的項目沒有.npmignore文件,但有 .gitignore文件,則發佈時會忽略 .gitignore中定義的文件;也就是說,.npmignore的優先級是高於.gitignore的。

.*
*.md
node_modules/
webpack.config.js
src/
複製代碼
  • (8)安裝依賴

以上文件都配置好後就能夠運行下面命令安裝package.json的依賴了,而後就會在大家的目錄中生成node_modules文件夾、package-lock.json文件

npm install
複製代碼
  • (9)打包咱們的組件
npm run build
複製代碼
  • (10) 目錄結構

下圖就是個人目錄結構,其中.gitattributes.gitignore文件你能夠忽略,由於我把這個項目放在github倉庫,因此纔會有這兩個文件的。

本地測試組件是否能夠用

在項目中執行以下命令

npm run build // 打包
npm pack // 本地生成一個our-btn-1.0.1.tgz的包
複製代碼

你本身在你本地新建一個vue/react項目,由於我是vue組件,因此我就新建一個vue項目,取名爲test-btn,咱們把our-btn-1.0.1.tgz放進咱們的本地項目test-btn

npm install our-btn-1.0.1.tgz
npm run dev // 啓動vue項目
複製代碼

而後在項目的main.js引入咱們的包

// src/main.js
// 注意:btn要保持和以前我們封裝組件的index.js同樣
import btn from 'our-btn' // 引入包

Vue.use(btn)
複製代碼

在咱們demo頁面中引用這個組件

// demo.vue
<template>
  <div class="demo">
    <btn :text="msg"></btn> 
  </div>
</template>

<script>
export default {
  name: 'demo',
  data () {
    return {
      msg: '成功'
    }
  }
}
</script>
複製代碼

若測試可用,在測試項目test-btn中運行npm uninstall our-btn卸載插件,而後那麼就能夠發佈到npm包上了

發佈到npm

  • (1)註冊npm帳號

發佈以前,你得註冊一個npm帳號吧,否則你怎麼上傳呢,建議上官網註冊一個帳號(順便熟悉那個網站),註冊完帳號以後,咱們就要在本地登陸併發布咱們的組件了

提示:由於有點童鞋會常常用cnpm源,因此呢,必定要切換到npm源上才能夠,否則就會報出以下錯誤

error: no_perms Private mode enable, only admin can publish this module
複製代碼

所以你要切換到npm源,經過npm config set registry http://registry.npmjs.org命令

  • (2)開始發佈

在發包以前,先去npm官網搜索一下有沒有和你包名相同的,若是相同就改一個其餘的名字吧

npm login // 登錄npm
// 而後輸入你的帳號、密碼、郵箱
// 當你在控制檯看到 Logged in as <Username> on https://registry.npmjs.org 說明登錄成功

// 若是你保證是最新版本且已經打包過,則跳過npm run build這一步
npm run build 
npm publish // 發佈你的包(若是你出現👇,顯示 +[package]@版本信息 ,那就發佈成功了)
複製代碼

👇這是個人輸入及其對應顯示的東西

🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉此時此刻你的包已經發布成功!!!🎉🎉🎉🎉🎉🎉🎉🎉🎉

⚠️拓展知識:一個版本只能發佈一次,也就是你不能發了1.0.0,下次還繼續1.0.0,理論上能夠覆蓋,可是npm不容許這樣,由於你這樣覆蓋,就沒法知道你的版本信息了啊,插件和項目都是迭代的,like git,是有版本信息的。

​ 方法一:每一次npm publish前,自行手動更改package.json的version

​ 方法二:經過如下命令來發布

假設初始版本爲1.0.0
➜ npm version preminor (執行這個命令,就會價格當前包發佈爲版本v0.1.0-0)
v1.0.0-0
➜ npm version prepatch
v1.0.1-0
➜ npm version patch    (執行這個命令,就會價格當前包發佈爲版本v1.0.1)
v1.0.1
複製代碼

查看npm && 使用咱們的包

​ 這個時候,你稍微等幾分鐘去npm官網搜索一下你的包名字,就能夠找到啦。若是搜不到,那就再等等,或許更新慢,沒有徹底更新,可是你在本身npm帳號能夠查看到本身發佈的包

​ 你本身在你本地新建一個vue/react項目,由於我是vue組件,因此我就新建一個vue項目,具體使用包的方法就是(以個人測試包爲例)

npm install our-btn // 安裝咱們的包
複製代碼

而後在項目的main.js引入咱們的包

// src/main.js
// 注意:btn要保持和以前我們封裝組件的index.js同樣
import btn from 'our-btn' // 引入包

Vue.use(btn)
複製代碼

在咱們demo頁面中引用這個組件

// demo.vue
<template>
  <div class="demo">
    <btn :text="msg"></btn> 
  </div>
</template>

<script>
export default {
  name: 'demo',
  data () {
    return {
      msg: '成功'
    }
  }
}
</script>
複製代碼

若是錯誤請指正,我也好糾錯更新

若有講的不明白的,請留言,我看到會回覆

over

相關文章
相關標籤/搜索