首页
bv伟德登录入口分享
实用工具 发布伟德伟诺官网 新浪微博 Github

原文地址:https://vuejsdevelopers.com/2017/07/31/vue-component-publish-npm/

当你开发出一款NB累累的 Vue 组件,并希望其他开发者在的项目中使用它。你将怎么分享组件给他们使用呢?

在这篇伟德伟诺官网中我将告诉你如何准备你的组件,打包并发布到 NPM。我将使用一个示例项目演示以下内容:

  • 确保包中不包含任何依赖项
  • 使用 Webpack 分别构建应用于浏览器和Node环境中的代码
  • 创建一个应用于浏览器的插件
  • 配置 package.json
  • 发布到 NPM
  • 项目案例: Vue Clock

    我创建了这个简单的时钟组件,我会把它发布到 NPM 上。也许它不是你见过的最酷的组件,但它足以演示。

    enter image description here

    这是组件文件。这里没有什么特别的东西,但是请注意,我正在引入 moment 库用于格式化时间。
    从你的包中排除依赖关系很重要,稍后我们会看到。

    Clock.vue

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <template>
    <div></div>
    </template>
    <script>
    import moment from 'moment';

    export default {
    data() {
    return {
    time: Date.now()
    }
    },
    computed: {
    display() {
    return moment(this.time).format("HH:mm:ss");
    }
    },
    created() {
    setInterval(() => {
    this.time = Date.now();
    }, 1000);
    }
    }
    </script>

    关键工具: Webpack

    我为将组件发布到 NPM 上所做的大部分准备工作都是由 Webpack 完成的。 下面示例代码是本文中将要添加的基本 Webpack 配置。 如果您以前使用过Vue和Webpack,可以忽略没什么特别的地方:

    webpack.config.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    const webpack = require('webpack');
    const path = require('path');

    module.exports = {
    entry: path.resolve(__dirname + '/src/Clock.vue'),
    output: {
    path: path.resolve(__dirname + '/dist/'),
    filename: 'vue-clock.js'
    },
    module: {
    loaders: [
    {
    test: /\.js$/,
    loader: 'babel',
    include: __dirname,
    exclude: /node_modules/
    },
    {
    test: /\.vue$/,
    loader: 'vue'
    },
    {
    test: /\.css$/,
    loader: 'style!less!css'
    }
    ]
    },
    plugins: [
    new webpack.optimize.UglifyJsPlugin( {
    minimize : true,
    sourceMap : false,
    mangle: true,
    compress: {
    warnings: false
    }
    })
    ]
    };

    Externals

    externals 配置选项可以配置,从 Webpack 打包的代码中排除某个特定的依赖。 我不希望我的组件中包含依赖关系,因为那会使打包出来的代码变得臃肿,并可能导致用户环境中的版本冲突。 用户必须自己安装依赖项。

    在这个例子中,我的包依赖于 moment 库。 为了确保它不会被打包,在 WebPACK 配置中我将指定 moment 为一个 external (外部引用):

    webpack.config.js

    1
    2
    3
    4
    5
    6
    7
    module.exports = {
    ...
    externals: {
    moment: 'moment'
    },
    ...
    }

    环境搭建

    在Vue.js中,用户可能通过两种途经使用组件。 首先是,浏览器引入:

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

    其次,基于Node.js的开发环境,例如:

    1
    import VueClock from 'vue-clock';

    理想情况下,我希望用户能够在任意一个环境中使用 Vue Clock。 不幸的是,这些环境需要将代码以不同方式打包,这意味着我必须设置两个不同的构建配置。

    为此,我将创建两个单独的Webpack配置。 这比听起来更容易,因为配置几乎相同。 首先,我将创建一个常见的配置对象,然后使用 webpack-merge 将其包含在两个环境配置中:

    webpack.config.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    const webpack = require('webpack');
    const merge = require('webpack-merge');
    const path = require('path');

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

    module.exports = [

    // Config 1: For browser environment
    merge(commonConfig, {


    }),

    // Config 2: For Node-based development environments
    merge(commonConfig, {

    })
    ];

    常见的配置与之前完全一样(我简写了大部分内容以节省空间),除了我已经删除的 entryoutput.filename 选项。 我将在单独的构建配置中单独配置它们。

    用于浏览器环境的打包

    浏览器不能像 Node 那样,可以从另一个 JavaScript 模块文件引入。但是它们可以使用像AMD这样的脚本加载器,为了最大限度地简化,我让组件脚本作为一个全局变量,这样可以更简单地添加。

    另外,我不希望用户必须想很多才能弄清楚如何使用组件。我会这样做的,当用户引入脚本时,组件可以很容易地注册为全局组件。Vue的插件系统将有助于实现这个功能。

    我的目标是这个简单的设置:

    index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <body>
    <div id="app">
    <vue-clock></vue-clock>
    </div>
    <script type="text/javascript" src="vue-clock.js"></script>
    <script type="text/javascript">
    Vue.use(VueClock);
    </script>

    </body>

    Plugin

    首先,我将创建一个插件包装器,以方便安装组件:

    plugin.js

    1
    2
    3
    4
    5
    6
    7
    import Clock from './Clock.vue';

    module.exports = {
    install: function (Vue, options) {
    Vue.component('vue-clock', Clock);
    }
    };

    该插件全局注册组件,因此用户可以在其应用程序的任何位置调用 clock 组件。

    webpack配置

    现在,我使用plugin.js路径作为浏览器构建的入口点。我会输出一个名为 vue-clock.min.js 的文件,这对用户来说是最明显的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    module.exports = [
    merge(config, {
    entry: path.resolve(__dirname + '/src/plugin.js'),
    output: {
    filename: 'vue-clock.min.js',
    }
    }),
    ...
    ];

    以库的形式导出

    Webpack 可以以各种不同的方式导出你的脚本,例如:作为一个对象,作为一个全局变量,遵循AMD或CommonJS规范的模块。您可以使用 libraryTarget 选项指定。

    对于浏览器打包方式,我将使用 window 导出方式。 我也可以使用 UMD 来获得更多的灵活性,但是由于我已经创建了两个打包方式,所以我只是将这个打包方式限制在浏览器中。

    我还将库名称指定为 VueClock。 这意味着当浏览器引入包时,它将挂载在全局上 window.VueClock

    1
    2
    3
    4
    5
    output: {
    filename: 'vue-clock.min.js',
    libraryTarget: 'window',
    library: 'VueClock'
    }

    Node 环境打包

    为了允许用户在 Node 开发环境中使用组件,我将使用 UMD 方式打包输出提供给 Node 环境使用。 UMD是一种灵活的模块类型,可以在各种不同的脚本加载器和环境中使用代码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    module.exports = [
    ...
    merge(config, {
    entry: path.resolve(__dirname + '/src/Clock.vue'),
    output: {
    filename: 'vue-clock.js',
    libraryTarget: 'umd',

    // These options are useful if the user wants to load the module with AMD
    library: 'vue-clock',
    umdNamedDefine: true
    }
    })
    ];

    注意,在Node 环境中使用单个文件组件作为入口,不需要使用插件包装器。这样可以更灵活的引入:

    1
    2
    3
    4
    5
    6
    7
    import VueClock from 'vue-clock';

    new Vue({
    components: {
    VueClock
    }
    });

    package.json

    在发布到NPM之前,我将设置我的 package.json 文件。 有关每个选项的详细说明,请访问 npmjs.com。

    package.json

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    {
    "name": "vue-clock-simple",
    "version": "1.0.0",
    "description": "A Vue.js component that displays a clock.",
    "main": "dist/vue-clock.js",
    "scripts": {
    "build": "rimraf ./dist && webpack --config ./webpack.config.js"
    },

    "author": "Anthony Gore",
    "license": "MIT",
    "dependencies": {
    "moment": "^2.18.1"
    },

    "repository": { ... },
    "devDependencies": { ... }
    }

    我省略了这个文件的大部分,但重点要注意的是:

    1. 主脚本文件即 "main": "dist/vue-clock.js"。 这指向 Node bundle 文件,确保模块加载器知道文件的准确路径,即
    1
    import VueClock from 'vue-clock' // this resolves to dist/vue-clock.js
    1. 依赖关系,由于我从包中排除了所有依赖关系,用户必须自行安装依赖才能使用该包。

    发布到 NPM

    现在我的组件设置正确,可以在NPM上发布。 我不会重复的在这里说明,因为它们在npmjs.com上很好地介绍。

    结果如下:

    enter image description here

    https://github.com/anthonygore/vue-clock-simple/blob/master/webpack.config.js
    https://vuejsdevelopers.com/2017/07/31/vue-component-publish-npm/