使用webpack4搭建一个基于Vue的组件库

组内负责的几个项目都有一些一样的公共组件,所以就着手搭建了个公共组件开发脚手架,第一次开发 library,所以是参考着 iview 的配置来搭建的。记录如何使用webpack4搭建一个library的脚手架

前言

使用 webpack4,需要安装 webpack 和 webpack-cli

yarn add webpack webpack-cli -D

然后就是书写配置文件。

项目脚手架结构

我写的 library 的目录结构如下,仅供参考,主要是模仿 iview 的结构,其中部分配置参考了 vue-cli的 webpack 配置文件。

├─build
│      build.js  // 用于执行构建
│      check-versions.js    // vue-cli 留下的,主要就是检查npm版本和node版本
│      webpack.base.conf.js   // 通用配置
│      webpack.dev.conf.js   // 开发环境
│      webpack.dist.prod.conf.js //  用于生成library的代码 -- hbf.min.js
│      webpack.prod.conf.js  // 用于生成example文件的打包代码,这个其实是没有必要的.
│
├─dist
│   └─example // example生成的打包文件夹,可以通过githubPage来预览,或者本地使用anywhere预览
│     hbf.min.js // library 文件
│
├─example    // example目录
│      App.vue
│      index.html
│      main.js
│
├─lib
│  │  index.js  // 全量引入公共组件,并暴露出来,包含install方法可供vue引入使用该插件
│  │  README.md
│  │  
│  └─components // 公共组件
│
├─package.json  // 项目包依赖

更为具体信息的可以到github仓库阅览。

经过 webpack 编译后的代码

为了更好的理解,先来了解下 webpack 编译后的代码。

经过webpack处理过的代码通常都是如下所示

// webpack编译后的代码

/*
* @param {Array} modules
*/
;(function(modules) {
  function __webpack_require__(moduleId) {
    var module = {
      i: moduleId, // 模块ID
      l: false,
      exports: {}, // 作为结果返回.
    }
    // 调用modules数组的某个元素(类型为函数)
    modules[moduleId].call(
      module.exports,
      module,
      module.exports,
      __webpack_require__
    )
    return module.exports
  }

  return __webpack_require__(0)
})([
  /** 省略了代码, 该数组的每一项代表一个模块,实际是一个函数,接受三个参数,module对象,module.exports对象,__webpack_require__函数 **/
])

webpack 编译后的代码的整体结构就是一个IIFE函数,接受一个 modules: Array参数。

对于模块处理,无论是 ES Moduleimport 还是 commonjsrequire 都转化为__webpack_require__ 这个函数来引入模块。

__webpack_require__ 函数,会从 modules 数组的第一个元素开始(moduleId 为 0,也就是入口文件),执行该模块(实为一个函数)的逻辑,利用传入的module.exports的数据类型为引用类型Object,间接地给module.exports添加属性。

return __webpack_require__(0)

从入口文件开始,逐个引入依赖模块,最后返回入口模块的 module.exports

此时这个编译后的 js 文件,是无法被其他模块所引用的,只在当前作用域内有效, webpack 就提供了创建 library 的方式,就是在output里定义librarylibraryTarget。使得构建完的 js 可以供其他模块引入使用。

设置library配置

对于作为一个 library 使用的项目来说,output 选项需要设置 library

// webpack.dist.pord.conf.js

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

library 可以是字符串,也可以是对象,(对象仅限于 libraryTarget 的值为 umd 的情况下使用)

output: {
  library: {
    root:'Hbf',  // 暴露给全局变量,window.Hbf进行调用
    commonjs: 'hbf-public-components'
  },
  libraryTarget: 'umd'
}

commonjscommonjs2 的区别。

commonjs 规范就是定义了一个 exports 对象,而 nodejs 在实现的时候,在 commonjs 规范的前提下做了一些扩展,定义了 module.exports ,从而也叫这种为 commonjs2 规范。

我们在引用别人的库的时候,通常都是可以通过多种方法引入的,比如

输出

使用webpack4搭建一个基于Vue的组件库_第2张图片

全量引用

可以像使用其他 vue 插件库/组件库一样使用。

import hbf from 'hbf-public-components'

// 使用use方法触发hbf的intall方法,注册全部组件
Vue.use(hbf)

如果是没有导出default变量,则使用另外一种方式全量引入

import * as hbf from 'hbf-public-components'

按需引用

import { publicMenu } from 'hbf-public-components'

按需引用,如果 library 使用的是ES2015 Module规范,则不需要安装任何插件,webpack 会对其进行tree-shaking,去除未引用的代码。

前面提过,webpacktree-shaking是由Uglylify插件实现的,我在开发环境下,没有启用Uglylify来压缩代码,所以查看模块打包图,会发现整个库都被引入了,虽然我只引入了一个组件。webpack4在生产环境下,才会进行tree-shaking,设置mode的值为production就会开启生产环境下的优化。

如果是使用 commonjs 规范的 library 则需要一个插件支持,babel-plugin-import。该插件是ant官方开发的。许多 UI 组件库的按需引入也是依赖于这个插件。

安装

yarn add babel-plugin-import -D

修改.babelrc文件,

"plugins": [
  ["import", {
    "libraryName": "hbf-public-components",
    "libraryDirectory": "lib/components"
  }]
],

总结

其实如果对于一个不是很稳定,需要一直迭代更新公用组件库来说,使用 npm 包的话,会比较不方便,经常更新的公共组件代码可以使用Git subtree教程)来维护,可以等到一定地步之后,公共组件库稳定下来之后再考虑发布一个 npm 包。

而开发一个组件库,也可以使用 rollup.js 来搭脚手架,rollup.js 默认使用的就是 ES2015 Module,可以进行静态分析,去除未引用的代码,tree-shaking 也是 rollup.js 先提出的。Rollup相比较于Webpack,更适合用于构建libraryVue.js就是使用 Rollup 构建的。Webpack 在代码分割这方面比较有优势,所以webpack 相对来说比较适合构建应用程序,不过使用 webpack 构建 library 也是可以的。

这个项目也可以用做 webpack 构建 library 的通用脚手架。下次再尝试Rollup构建 library

有帮助的话,可以给个star的话就最好啦。有问题也可以联系我。

项目地址: https://github.com/huya-base-...

npm 地址:https://www.npmjs.com/package...

关于模块规范,以及 webpack,babel 是如何编译转换模块的文章

你可能感兴趣的:(npm,webpack4,library,vue.js,webpack)