美文网首页
一步一步教你如何发布一个vue组件到NPM

一步一步教你如何发布一个vue组件到NPM

作者: bcb84a30ed08 | 来源:发表于2018-07-04 14:14 被阅读0次

Vue.js已经火了好久了,组件化代码的思想已经深入人心。自己写了一个自我感觉超牛逼的组件,好想分享给别人,这时候怎么做呢?这篇文章就教你如何一步步把你的组件发到npm上。

下面我将通过一个例子来演示整个流程:

  • 确认包里没有包含其他依赖
  • 通过webpack分别构建出browser和node场景的版本
  • package.json配置
  • 发布到NPM

Example: Vue Countup 数字滚动

这是一个数字滚动的组件,我们将通过它来演示整个过程。


vue-countup-v2.gif

下面是数字滚动组件的代码
Countup.vue

<template>
  <span :id="targetId"></span>
</template>

<script>
import CountUp from 'countup.js'

export default {
  data () {
    return {
      targetId: '',
      numAim: null
    }
  },

  props: {
    endVal: Number,
    decimals: {
      type: Number,
      default: 0
    },
    duration: {
      type: Number,
      default: 4
    }
  },

  watch: {
    endVal: function (val) {
      this.numAim.update(val)
    }
  },

  created () {
    this.targetId = 'countup_' + Math.random().toString(36).substr(2, 9)
  },

  mounted () {
    this.numAim = new CountUp(this.targetId, 0, this.endVal, this.decimals, this.duration / 2)
    this.numAim.start()
  }

}
</script>

构建工具:Webpack

Webpack神器我就不介绍了,相信你们有用Vue的应该都知道。我们的大部分工作都是通过配置webpack.config.js来完成的。我这里用的是webpack4,关于webpack4的改动,可以翻看我上一篇文章《Webpack 4.0发布了!!》

webpack.config.js

const webpack = require('webpack');
const { VueLoaderPlugin } = require('vue-loader');
const path = require('path');

module.exports = {
  entry: path.resolve(__dirname + '/src/CountUp.vue'),
  output: {
    path: path.resolve(__dirname + '/dist/'),
    filename: 'vue-countup.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        include: __dirname,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.vue$/,
        use: {
          loader: 'vue-loader'
        }
      },
      {
        test: /\.css$/,
        use: {
          loader: 'css-loader'
        }
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ]
}

Externals

组件中我们引入了countup.js,但我不希望我的组件包含这个依赖,因为这会导致我这个组件体积变大,而且可能会跟用户的环境造成版本冲突。这时候externals就派上用场了,官网文档解释的很清楚,就是webpack可以不处理应用的某些依赖库,使用externals配置后,依旧可以在代码中通过CMD、AMD或者window/global全局的方式访问。
webpack.config.js

module.exports = {
  ...
  externals: {
    countup: 'countup'
  },
  ...
}

构建环境

在Vue.js中,有两种引入组件的方式,一种是浏览器引入:

<script type="text/javascript" src="vue-countup.js"></script>

另一种是通过Node模块引入:

import VueCountup from 'vue-countup';

这两种引入方式意味着我们要构建出两份代码,我们只好通过两套配置来实现。使用两个conf文件不好,我们可以通过webpack-merge来解决!
webpack.config.js

const webpack = require('webpack');
const merge = require('webpack-merge');
const path = require('path');

var commonConfig = {
  output: {
    path: path.resolve(__dirname + '/dist/'),
  },
  module: {
    rules: [ ... ]
  },
  plugins: [ ... ]
};

module.exports = [
  // For browser env
  merge(commonConfig, {
  
  }),
  // For Node-based development env
  merge(commonConfig, {
  
  }),
]

注意我在commonConfig里把entryoutput.filename移除了。

浏览器环境

大部分浏览器暂时还不能跟Node一样引入模块,它们可以通过AMD等装载器来引入,不过为了最简单化,我将我的组件作为全局变量添加到window里。

Vue插件的使用方式主要是通过Vue.use(),我也希望我们的组件以这种方式来调用:

// 实际上就是调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)

那么最终我们的调用方式就是这样:

<body>
  <div id="app">
    <vue-clock></vue-clock>
  </div>
  <script type="text/javascript" src="vue-countup.js"></script>
  <script type="text/javascript">
    Vue.use(VueCountup);
    new Vue({
      el: '#app',
    })
  </script>
</body>

插件化

plugin.js

import VueCountup from './VueCountup.vue';

module.exports = {
  install: function (Vue) {
    Vue.component('vue-countup', VueCountup);
  }
};

Webpack 配置

webpack支持多种导出方式,可通过output.libraryTarget来设置,默认是var,会将值作为变量声明导出,这里我们用window,你也可以使用umd这种通用性高的,不过鉴于我们已经分开成两份配置了,这里只需要考虑浏览器端的。

output.library的值取决于libraryTarget的配置,这里会将我们的模块赋值到window.VueCountup

module.exports = [
  merge(commonConfig, {
    entry: path.resolve(__dirname + '/src/plugin.js'),
    output: {
      filename: 'vue-countup.min.js',
      libraryTarget: 'window',
      library: 'VueCountup',
    }
  });
]

Node-based 开发环境

使用UMD的方式导出,可让我们的组件支持以多种方式加载。

module.exports = [
  // For Node-based development environments
  merge(commonConfig, {
    entry: path.resolve(__dirname + '/src/VueCountup.vue'),
    output: {
      filename: 'vue-countup.js',
      libraryTarget: 'umd',
      // if the user wants to load the module with AMD
      library: 'vue-countup',
      umdNamedDefine: true
    },
  })
]

注意我们entry是直接引入组件的,不是plugin.js了,这样我们可以这样引用组件:

import VueCountup from 'vue-countup';

new Vue({
  components: {
    VueCountup
  }
})

package.json

至此我们大部分工作已经完成,但要发布到NPM上还需要修改一下 package.json
package.json

{
  "name": "vue-countup",
  "version": "1.0.0",
  "description": "A Vue.js component that countup number with animation",
  "main": "dist/vue-countup.js",
  "scripts": {
    "build": "rimraf ./dist && webpack --mode production"
  },
  "author": "Tofuxb",
  "license": "ISC",
  "dependencies": {
    "countup.js": "^1.9.3"
  },
  "devDependencies": { ... }
}

注意:

  1. "main": "dist/vue-countup.js" 可告知模块加载时所映射的文件。
  2. Dependencies. 我们的组件里没有把countup.js构建进来,但是要写到这里。

最后一步:发布到NPM

具体我不在这里演示了,参考官方教程

相关文章

网友评论

      本文标题:一步一步教你如何发布一个vue组件到NPM

      本文链接:https://www.haomeiwen.com/subject/hgsjuftx.html