寫一個vue組件(todo-list)發佈到npm上

前言

最近幾我的合做完成了一個項目,發現有一些公用的基礎業務組件,能夠提取出來,不只方便你們在各自模塊直接引用,也能夠在之後的項目中使用。想到了可不能夠本身動手把組件打包發佈到內部的npm上,避免之後小夥伴們的重複工做呢?因而乎,說幹就幹,在這裏操練一下,寫個todo-list的vue組件案例。案例源碼:https://github.com/wuwhs/todo...javascript

創建npm項目

1. 初始化npm項目

建一個文件夾(todoList),在這個文件夾路徑下打開cmd窗口,輸入指令npm init,前提是已經裝好了node(自帶npm)。css

$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (todolist)

提示輸入項目包名稱,這裏的名稱將做爲發佈到npm上這個包的名稱,之後別人使用就能夠直接importrequire到項目中使用。html

package name: (todolist) todolist
version: (1.0.0)

接下來提示輸入版本,這裏的版本將做爲發佈到npm上這個包版本控制號,每次發佈必需要改一下版本號,才容許發佈,在這裏做爲第一個版本能夠直接回車,默認是1.0.0vue

version: (1.0.0)
description:

而後提示輸入描述信息,描述一下這個包的功能做用。因而輸入:java

description: a vue component of todolist
entry point:(webpack.config.js)

再者,提示整個項目的入口文件,這裏是咱們打包後的文件,打包後文件都放到dist目錄下,先設定生成的文件是todoList.min.js,因而:node

entry point:(webpack.config.js) ./dist/todoList.min.js
test command:
git repository:

接下來提示輸入測試命令、git倉庫,先無論,後面再詳細寫,回車默認空。webpack

再提示輸入關鍵字,便於其餘人在npm上搜索獲得你寫的包,最後就是做者和認證,根據本身實際狀況填。git

keywords: todolist vue
author: wuwhs
license: (ISC)
About to write to D:\WampServer\wamp\www\todoList\package.json:

{
  "name": "vue-todolist",
  "version": "1.0.0",
  "description": "a vue component of todolist",
  "main": "dist/todolist.min.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "todolist",
    "vue"
  ],
  "author": "wuwhs",
  "license": "ISC"
}

Is this ok? (yes) yes

這樣,一個npm項目就初始化完了。接下來,來發佈一個已經打包好了的組件包(先爲空的)到npm上。github

發佈包到npm上

首先須要有npm官網的一個註冊帳號,而後輸入npm adduser,依次輸入npm登陸帳號、密碼和註冊激活郵箱。這樣就輕鬆的登陸上了。(PS:在window的CMD窗口,輸入密碼時不顯示輸入密碼,盲輸入,肯定後回車便可,這裏被坑了一下)web

$ npm adduser
Username: wuwhs
Password: balabala...
Email: (this IS public) balabala...
Logged in as wuwhs on https://registry.npmjs.org/.

最後,直接輸入指令publish便可大功告成。

$ npm publish
+ vue-todolist@1.0.0

不過,好事多磨,可能事情沒有那麼順利。

一個可能取的包名稱跟別人的重名了,這樣是不能上傳上去的,會提示你沒有權限發佈這個包。

$ npm publish
npm ERR! publish Failed PUT 403
npm ERR! code E403
npm ERR! You do not have permission to publish "vue-router". Are you logged in as the correct user? : vue-router

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2018-04-02T15_41_56_696Z-debug.log

解決方法:須要到package.json裏改一下包名稱name,或者去npm官網搜一下你要取的名稱,有沒有同名,再回頭來改。

還有就是每次發佈,沒改版本號。

$ npm publish
npm ERR! publish Failed PUT 403
npm ERR! code E403
npm ERR! You cannot publish over the previously published versions: 1.0.1. : vue-todolist

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2018-04-02T15_40_28_571Z-debug.log

解決方法:須要到package.json裏改一下版本號後發佈。

把npm線路打通了,接下來就是打包輸出,上傳資源了。

webpack打包

組件寫好後,通常要藉助自動化工具,將資源整合打包壓縮,提供一個入口文件,供別人直接引用。在這裏,選用webpack來打包。

爲了方便演示,寫一個vue官網上todo-list的例子,做爲組件打包發佈。

整個目錄結構

--todoList
    --src
        --components
            --todoItem.vue
            --todoList.vue
        --App.vue
        --index.js
        --main.js
    --index.html
    --webpack.config.js
    --package.json
    --.babelrc
    --.npmignore

下面來分別說明文件內容:

1. package.json文件

{
  "name": "vue-todolist",
  "description": "a vue component of todolist",
  "version": "1.0.0",
  "author": "wuwhs",
  "license": "MIT",
  "private": false,
  "main": "./dist/todoList.min.js",
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
  },
  "dependencies": {
    "vue": "^2.5.11"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ],
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.0",
    "babel-preset-stage-3": "^6.24.1",
    "cross-env": "^5.0.5",
    "css-loader": "^0.28.7",
    "file-loader": "^1.1.4",
    "vue-loader": "^13.0.5",
    "vue-template-compiler": "^2.4.4",
    "webpack": "^3.6.0",
    "webpack-dev-server": "^2.9.1"
  }
}

主要安裝一些必要的依賴插件,如vue、babel和webpack

2. webpack.config.js文件

var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'build.js'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ],
      },      
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loaders: {
          }
          // other vue-loader options go here
        }
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    },
    extensions: ['*', '.js', '.vue', '.json']
  },
  devServer: {
    historyApiFallback: true,
    noInfo: true,
    overlay: true
  },
  performance: {
    hints: false
  },
  devtool: '#eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      compress: {
        warnings: false
      }
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true
    })
  ])
}

webpack的基本熱更新以及打包配置,能夠參考webpack中文官網入門Webpack,看這篇就夠了

3. .babelrc文件

{
  "presets": [
    ["env", { "modules": false }],
    "stage-3"
  ]
}

ES6轉化工具babel配置

4. main.js項目入口文件

import Vue from 'vue'
import App from './App.vue'

new Vue({
  el: '#app',
  render: h => h(App)
})

5. App.vue vue根組件

<template>
  <div id="app">
    Hello, todo-list!
  </div>
</template>

<script>
export default {
  name: 'app'
}
</script>

6. index.html 頁面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>todolist</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="./dist/build.js"></script>
  </body>
</html>

輸入命令npm install,全部依賴包安裝完成後,npm run dev,啓動成功。

PS:遇到一個坑,先用npm install感受太慢了,因而斷掉了,用cnpm install,安裝完成後,啓動老是缺乏這個依賴包,那個依賴包,沒完沒了,因而,把node_modules全刪了,從新cnpm install一鼓作氣正常了。cnpm安裝會引入一些版本文件,前面npm已裝好的包沒有,因而就出現了報錯,找不到某某依賴包。

至此,打包工具webpack的基本配置就完成了,接下來就是寫vue組件了。

寫todo-list的vue組件

todo-list組件在不少地方都會做爲一個案例使用,在這就直接模範vue官網的案例來寫了。

1. todoList.vue組件——列表

<template>
<div">
  <input
    v-model="newTodoText"
    v-on:keyup.enter="addNewTodo"
    placeholder="Add a todo"
  >
  <ul>
    <li
      is="todo-item"
      v-for="(todo, index) in todos"
      v-bind:key="todo.id"
      v-bind:title="todo.title"
      v-on:remove="todos.splice(index, 1)"
    ></li>
  </ul>
</div>
</template>

<script>
import TodoItem from './TodoItem'
export default {
  components: {
    TodoItem
  },
  data () {
    return {
      newTodoText: '',
      todos: [
        {
          id: 1,
          title: 'Do the dishes',
        }
      ],
      nextTodoId: 2
    }
  },
  methods: {
    addNewTodo: function () {
      this.todos.push({
        id: this.nextTodoId++,
        title: this.newTodoText
      })
      this.newTodoText = ''
    }
  }
}
</script>

2. todoList.vue組件——列表項

減少耦合度,把列表項單獨拿出來作一個組件。

<template>
<li>
  {{ title }}
  <button v-on:click="$emit('remove')">X</button>
</li>
</template>

<script>
export default {
  props: ['title']
}
</script>

3. App.vue根組件

將todo-list組件引入並掛載到根節點。

<template>
  <div id="app">
    <todo-list></todo-list>
  </div>
</template>

<script>
import TodoList from './components/todoList'
export default {
  name: 'app',
  components: {
    TodoList
  }
}
</script>

刷新瀏覽器,查看效果

OK,組件基本完成。

組件打包

前面已經驗證了,咱們寫的todo-list組件沒問題了,要將這個組件獨立打包成一個文件。這時就須要更換一下入口文件了,把測試案例用的main.js換成index.js文件。

獨立組件入口文件 index.js

目的只是將要打包的組件引入。

import TodoList from './components/todoList.vue'

export default TodoList

更改webpack配置 webpack.config.js

將入口文件更換成./src/index.js,文件出口路徑和名稱更換成package.jsonmain的路徑和名稱,這樣方便不調整npm的發佈目錄。

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'todoList.min.js'
  },
  ...
}

改好後,npm run build,打包組件,結果就在dist目錄下有了todoList.min.js文件。這就是打包組件後的文件。也是將要發佈到npm上別人真正使用的入口文件。

測試打包好的文件

剛打包好的文件能不能直接使用,在發佈到npm上以前先在本地測試一下。要測試方法很簡單,就是把跟組件引入的vue組件改爲引入剛打包的文件。因而App.vue這樣改:

<script>
import TodoList from '../dist/todoList.min.js'
export default {
  name: 'app',
  components: {
    TodoList
  }
}
</script>

再改回測試案例入口,刷新瀏覽器,報錯!

vue.esm.js?3153:591 [Vue warn]: Failed to mount component: template or render function not defined.

found in

---> <TodoList>
       <App> at src\App.vue
         <Root>

有點小奔潰,沒有渲染函數?難道本身打包出來的組件居然不能用!後來查資料才知道,打包須要指定一種模塊輸出類型,能夠是commonjs,AMD,script,UMD模式。在這裏是寫插件,要採用UMD模式,即libraryTarget: 'umd'。因而webpack.config.js出口文件配置修改成:

output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'todoList.min.js',
    library: 'vueTodoList',
    libraryTarget: 'umd',
    umdNamedDefine: true
  }

再打包獨立組件,更新todoList.min.js文件,改回測試文件(entry: './src/main.js',)入口,npm run dev,刷新瀏覽器,成功!

發佈和使用npm組件包

發佈npm組件包

已經驗證了咱們已經打包生成的todoList.min.js能夠正常使用,接下來就能夠發佈到npm上了,一樣npm跟git同樣,可使用.npmignore忽略一些上傳文件,好比node_moudules就不要上傳上去了。

.DS_Store
node_modules/
npm-debug.log
yarn-error.log

# Editor directories and files
.idea
.editorconfig
*.suo
*.ntvs*
*.njsproj
*.sln

更改一下package.jsonversion,執行npm publish便可

$ npm publish
+ vue-todolist@1.0.3

使用npm組件包

發佈成功後,這就是一個日常使用的插件了,cnpm install vue-todolist --save便可安裝(使用npm或cnpm安裝都可)完成,

$ cnpm install vue-todolist --save
√ Installed 1 packages
√ Linked 1 latest versions
√ Run 0 scripts
Recently updated (since 2018-03-27): 1 packages (detail see file D:\appSoft\wampserver\wamp64\www\todoList\node_modules\.recently_updates.txt)
  Today:
    → vue-todolist@*(1.0.3) (11:15:22)
√ All packages installed (1 packages installed from npm registry, used 564ms, speed 528.68kB/s, json 2(281.56kB), tarball 16.62kB)

而後直接在頁面中引入使用。

在App.vue引入todolist組件,就不須要引入本地寫的了,直接引入剛纔安裝好的

<script>
import TodoList from 'vue-todolist'
export default {
  name: 'app',
  components: {
    TodoList
  }
}
</script>

再次運行npm run dev,刷新瀏覽器,一切正常,good。

總結

至此,打包、發佈和使用本身寫的vue組件就完成了。總結一下這幾條須要關注:

  1. npm包配置(package.json)中,提供對外使用的入口文件最好跟打包後的文件一致,這樣打包完成後就可直接測試和發佈;
  2. 每次發佈要改版本號;
  3. webpack配置文件出口要加庫輸出類型libraryTarget: 'umd';
  4. 最好單獨用一個文件做爲組件輸出打包,不要跟測試案例入口文件弄混;
相關文章
相關標籤/搜索