很多前端开发者学习到必定阶段都会去封装一些本身的组件并将其开源。笔者在学习过程当中发现,发布的资源包基本分为两类:javascript
那么这两种方式有何不一样呢,他们的使用场景如何,具体的操做步骤又是怎么样的。本文将基于这两种发布方式,对比他们的不一样,详解其步骤,并对在封装Vue组件和发布npm依赖过程当中所遇到的问题进行概括和解答。相信对于更加全面的了解前端工程化和npm发布流程会有些许帮助。css
本文将涉及到:html
待封装的Vue组件(组件) 需引用的第三方依赖(第三方依赖) 测试使用的Vue项目(项目)
为了后文不至混淆,将分别使用括弧中内容指代,请读者注意区分。前端
这种方式是将封装好的组件最终打包成一个js文件发布。这种方式使得发开和调试时更接近与一个前端项目。可是一旦引用图片等静态资源需经过BASE64方式打包到js,而对于字体一类较大的静态资源则根本没法被引用。vue
适用范围:没有或极少的依赖第三方插件、图片的组件的封装或JS方法的封装java
使用webpack构建前端工程,此处注意webpack配置文件应当区分开发和打包。base.js
、dev.js
和build.js
经过merge语句连接。node
// 项目结构 module |——src | |——asset | |——components // 组件包文件夹 | | |——index.js // 组件包打包入口 | | └——componentA.vue // 组件 | |——pages // 供开发时预览的页面 | |——router | |——template // html模板 | |——tools | |——app.vue // 供开发时预览的vue入口 | └——main.js // 供开发时预览的项目入口 |——webpack // webpack配置文件夹 | |——base.js // 通用配置 | |——dev.js // 开发用配置 | └——build.js // 打包用配置 |——package.json └——README.md
只放基础配置如module
和通用的plugins
,不要包含打包入口,和出口。webpack
htmlWebpackPlugin
和WebpackDevServer
服务相关。var webpack = require('webpack'); config.entry = { app:[path.join(APP_SRC, 'main.js')], vendors: [ 'vue', 'vuex', 'vue-router', 'axios' ] }, config.entry.app.unshift("webpack-dev-server/client?http://localhost:8088/") config.plugins.push(new htmlWebpackPlugin({ hash: true, minify: { removeComments: true, collapseWhitespace: true, }, // favicon: path.join(APP_SRC, '/asset/images/ico.ico'), template: path.join(APP_SRC, '/template/index.html'), })) var compiler = webpack(config); var serve = new WebpackDevServer(compiler, { quiet: false, stats: { colors: true }, compress: true, //gzip压缩 publicPath: 'http://localhost:8088/', contentBase: '../dist/', //默认状况下,webpack-dev-server会从项目的根目录提供文件,能够经过此选项设置文件的目录名 historyApiFallback: true, //当设置为true时,访问全部服务器上不存在的文件,都会被重定向到/,也就是index.html文件 }).listen(8088);
components
目录下的index.js
(index.js
引入并导出咱们须要封装的组件)。var config = require("./base.js"); module.exports = merge(config, { entry: [path.join(APP_SRC, '/components/index.js')], output: { path: APP_DIST, filename: 'index.js', library: 'module_name', // 指定的就是你使用require时的模块名 libraryTarget: 'umd', // 指定输出格式 umdNamedDefine: true // 会对 UMD 的构建过程当中的 AMD 模块进行命名。不然就使用匿名的 define }, devtool: false, mode: 'production', });
package.json
中须要包含引包的入口,包名称和版本号。项目在引用组件时会根据main
找到组件入口。ios
{ "name": "my_module", "version": "1.0.0", "main": "dist/index.js" ... }
组件开发无需多说,只要执行npm run dev
将所需封装的组件引入到预览页面中开发调试便可。
组件入口component/index.js需引入并导出组件,更加详细请看下一章节。web
手动修改package.json
中的version
或者执行npm version patch
生成迭代一个版本
npm run build
注意这一须要登录官方仓库,若是以前链接的是淘宝镜像须要线切换回来。下面是查看仓库源和切换仓库的命令。
npm config get registry // 查看仓库源 npm config set registry https://registry.npm.taobao.org npm config set registry http://registry.npmjs.org
登录npm,输入帐号、密码、邮箱
npm login
npm publish
封装好的组件不通过打包,直接发布,用户在引用时不是引用一个独立的js文件,而是用过一个入口文件引用一些列的文件。这种方式由于不是在单独引用一个js因此能够完美解决第三方插件的引用、图片、字体等静态文件的引用可是对于组件项目自己而言开发时的预览调试方法则须要另寻他路。并且笔者暂时没有想到不适用测方法的,是笔者认为较为完美的封装发布方案。
由于无需打包,所以再也不须要webpack配置,项目结构也更加精炼。能够将组件的入口已到根目录。
// 项目结构 module |——src | |——asset | |——components // 组件包文件夹 | | |——componentA // 组件A | | └——componentB.vue // 组件B | └——tools |——index.js // 组件入口 |——package.json └——README.md
组件的名字、版本、入口文件这三个属性必备以外,须要注意的是dependencies
中记录的第三方依赖都会在执行npm install
的时候被安装。
{ "name": "my_module", "version": "1.2.16", "main": "index.js", "dependencies": { "view-design": "^4.0.2", ... } ... }
使用正确的相对路径将组件和静态文件引入到index.js
import './src/asset/css/index.less' import ComponentA from './src/components/ComponentA.vue' import ComponentB from './src/components/ComponentB.vue'
若是你想经过Vue.use(MyComponent)
的方式使用组件,须要导出一个包含了全部组件的对象,并给这个对象定义install
方法供Vue.use()方法调用。
let ModuleObj = { ComponentA, ComponentB } let MyModule = {} MyModule.install = (Vue) => { for (let i in ModuleObj) { Vue.component(i, ModuleObj[i]) } } export default MyModule
export { ComponentA, ComponentB }
以引用iview为例,在组件(components/ComponentA.vue)内部局部注册iview组件。这样至关于按需加载有助于减少最终项目打包的体积。
<script> import { Poptip, Dropdown, DropdownMenu, DropdownItem, Icon, Input } from 'view-design'; export default { components: { Poptip, Dropdown, DropdownMenu, DropdownItem, Icon, Input } } </script>
使用正确的相对路径引用css、图片或字体,若是以前习惯使用webpack的alias路径别名,此时固然也是不生效的。
无需打包,但一样须要维护版本,直接发布
手动修改package.json
中的version
或者执行npm version patch
生成迭代一个版本
npm login npm publish
由于组件项目再也不有供开发调试的特面,所以须要在引用组件的项目中对组件进行调试,安装组件以后,在node_module
中找到组件的所在的文件夹,进入修改便可完成调试。最后将调试好的组件文件夹拷贝出来,除package.json
单独维护,发布便可。
两种引用方式:
// 全局安装 import MyModule from 'my_module' Vue.use(MyModule) // 按需加载 import { ComponentA, ComponentB } from 'my_module' Vue.component('ComponentA', ComponentA) Vue.component('ComponentB', ComponentB)
打包发布 | 非打包发布 | |
---|---|---|
webpack | 须要配置 | 无需配置 |
发布 | 发布前须要打包 | 发布前无需打包 |
引用静态文件 | 较小的图片能够经过BASE64方式打包仅js文件 | 随意使用 |
引用第三方依赖 | 能够引用,但若是第三方依赖包含较多的静态文件时可能会出现引用不到的状况 | 随意引用 |
被应用的文件 | 一个打包好的js | 组件的入口文件 |
调试方法 | 在组件项目中便可调试 | 须要在引用组件的项目中的node_module中对用模块中调试 |
对比两种方式,笔者更倾向于后者,但只要理解了前端项目引用依赖的原理就会发现其实二者本质上都是同样的,读者可根据本身的须要选择一种方式进行封装。文中若有错误也但愿各位不吝赐教及时指出。