目前最新的vuecli版本是3,而vuecli3与vuecli2都使用了相同的命令vue,所以vuecli2被覆盖了,如果要使用vuecli2的init
命令创建工程,需要安装一个桥接工具:@vue/cli-init
npm install -g @vue/cli-init
# `vue init` 的运行效果将会跟 `vue-cli@2.x` 相同
vue init webpack my-project
官方说明地址:创建一个项目
- 创建一个vuecli2项目
在创建项目的过程中,选项如下:vue init webpack demo-vuecli2-ui
- Vue build:选择只要运行时版本的,因为这里不需要编译模板字符串版本,读者可以根据需要自行配置,对本次按需引入打包配置无关;
- 不需要vue-router
- 不需要eslint
- 不需要unit test
- 不需要e2e test
- 不要自动执行npm install,自行处理
- 打开项目,执行
npm install
安装依赖 - 安装完之后,
npm run dev
启动,检查是否正常。
一切正常 - 这里组件库的名字为:
demo-vuecli2-ui
,现在开始写组件,这里只写两个组件:- pl-button
- pl-input
除了这两个组件之外,还需要有一个体积比较大的组件,不然到时候测试按需引入的时候,很难观察到只引入部分组件(比如只引入button)所带来的打包体积优化效果。这里这个体积比较大的组件,使用element-ui来替代,把element-ui当做一个组件看待
- 安装element-ui
这里为什么要npm i element-ui -D
-D
,-D
是--save-dev
的缩写,-S
是--save
的缩写,--save
会将依赖添加到package.json
的dependency
列表中,如果是--save-dev
,会将依赖添加到devDependency
列表中。将组件打包,然后发布到npm仓库之后,用户可以通过npm i demo-vuecli2-ui --save
安装依赖,这时候,用户安装的时候也会去下载element-ui,这个可以通过观察node_modules/demo-vuecli2-ui
目录验证,这个目录下面也会有一个node_modules文件夹,其中就是demo-vuecli2-ui的dependency列表。实际上用户是不需要再次安装下载element-ui的,所以这里是-D
; - 编写组件,根目录下创建components文件夹,目录结构:
文件内容:- components - button - index.js - pl-button.vue - ele - index.js - input - index.js - pl-input.vue - index.js
/*components/button/index.js*/ import Button from './pl-button' Button.install = (Vue) => Vue.component(Button.name, Button); export default Button
/*components/button/pl-button.vue*/ <template> <div class="pl-button"> pl-button </div> </template> <script> export default { name: "pl-button" } </script> <style lang="scss"> .pl-button { background-color: maroon; color: white; } </style>
/*components/ele/index.js*/ import ELE from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' export default { install(Vue) { Vue.use(ELE) }, }
/*components/input/index.js*/ import Input from './pl-input' Input.install = (Vue) => Vue.component(Input.name, Input) export default Input
这个是总的打包入口/*components/input/pl-input.vue*/ <template> <div class="pl-input"> pl-input </div> </template> <script> export default { name: "pl-input" } </script> <style lang="scss"> .pl-input { background-color: #42b983; color: white; } </style>
/*components/index.js*/ import Button from './button' import Input from './input' import Ele from './ele' export default { install(Vue) { Vue.use(Button) Vue.use(Input) Vue.use(Ele) }, }
这样用户在全引入组件库`demo-vuecli2-ui`,因为element-ui的存在,打包的体积会非常大,而用户在按需引入button以及input的时候,因为没有element-ui,打包的体积会大大缩小; - 修改webpack配置文件,配置好调试组件以及打包组件的相关配置
- 修改
src/main.js
,全引入组件,用来调试组件:import Vue from 'vue' import App from './App' import DVU from 'demo-vuecli2-ui' Vue.use(DVU) Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', render: h => h(App) })
- 修改
src/app.vue
,调试组件:<template> <div id="app"> <img src="./assets/logo.png"> <pl-button/> <pl-input/> <el-button>hello world</el-button> <el-input/> </div> </template> <script> export default { name: 'App', components: {} } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
- 修改config/index.js,设置打包的输出文件夹为lib,同时js,css等资源文件输出路径由原来的lib/static改为lib。
- 修改build.assetsRoot为:
path.resolve(__dirname, '../lib'),
; - 修改build.assetsSubDirectory为:’’,就是一个空的字符串;
- 修改build.assetsRoot为:
- 修改package.json
- 删除"private":true
- 添加"main":“lib/index.js”
- 添加"files":[“lib”]
- 修改build/utils.js
- 在底部添加以下方法,用来扫描组件入口信息
const fs = require('fs') const join = path.join const resolve = (dir) => path.join(__dirname, '../', dir) exports.getComponentEntries = (path) => { let files = fs.readdirSync(resolve(path)); const componentEntries = files.reduce((ret, item) => { const itemPath = join(path, item) const isDir = fs.statSync(itemPath).isDirectory(); if (isDir) { ret[item] = resolve(join(itemPath, 'index.js')) } else { const [name] = item.split('.') ret[name] = resolve(`${itemPath}`) } return ret }, {}) console.dir(componentEntries) return componentEntries }
- 在底部添加以下方法,用来扫描组件入口信息
- 修改build/webpack.base.conf.js
- 删除module.exports.entry,里面应该只有一个app入口;
- resolve.alias添加一个:
'demo-vuecli2-ui': resolve('components/index.js'),
- 修改build/webapck.dev.conf.js
- module.exports中添加app入口,因为现在打包组件不需要打包页面了,只有调试组件的时候才需要这个入口,所以这里将这个app入口从webpack.base.conf.js中移到webpack.dev.conf.js:
entry: { app: './src/main.js' },
- module.exports中添加app入口,因为现在打包组件不需要打包页面了,只有调试组件的时候才需要这个入口,所以这里将这个app入口从webpack.base.conf.js中移到webpack.dev.conf.js:
- 修改build/webapck.prod.conf.js
- module.exports添加入口:
entry: { ...utils.getComponentEntries('components') },
- module.exports.output改为:
path: config.build.assetsRoot, filename: utils.assetsPath('[name].js'), libraryTarget: 'commonjs2', libraryExport: 'default', library: 'demo-vuecli2-ui',
- ExtractTextPlugin中的filename配置为:
filename: utils.assetsPath('css/[name].css'),
- 删除new HtmlWebpackPlugin(打包组件不需要页面)
- 删除所有的new webpack.optimize.CommonsChunkPlugin(打包组件的时候不需要抽离公共的部分,否则在按需引入组件的时候,还得引入一些chunk-vendor以及chunk-common等js文件)
- 删除new CopyWebpackPlugin(不需要将static目录拷贝到组件打包的目录)
- module.exports添加入口:
- 修改
- 修改完毕,启动本地调试,查看效果:
自定义的pl-button、pl-input以及element-ui的组件都显示正常; - 打包:
npm run build
,打包结果:
- 发布到npm中,没有npm账号的同学,请自行注册账号以及在本地设备终端中登录;修改package.json文件中的版本号为
0.0.1
,然后发布:
发布结果:npm publish
看到这个+ demo-vuecli2-ui@0.0.1
表示发布成功。 - 接下来使用上一篇文章创建的
test-load-on-demand
工程测试按需引入是否配置成功。- 打开test-load-on-demand工程,安装
demo-vuecli2-ui
:npm i vuecli2-ui@0.0.1 -S
- 修改
.babelrc
文件:{ "presets": ["@vue/app", ["@babel/preset-env", { "modules": false }]], "plugins": [ [ "component", { "libraryName": "demo-vuecli2-ui", "style": true, "styleLibrary": { "base": false, "name": "css" } } ] ] }
- 修改src/main.js,全引入demo-vuecli2-ui:
import Vue from 'vue' import App from './App.vue' import DVU from 'demo-vuecli2-ui' import 'demo-vuecli2-ui/lib/css/index.css' Vue.use(DVU) Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app')
- 修改App.vue,显示所有demo-vuecli2-ui的组件:
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <pl-button/> <pl-input/> <el-button>hello world</el-button> <el-input/> </div> </template> <script> export default { name: 'app', } </script> <style lang="scss"> </style>
- 启动,检查效果:
可以看到,app.js文件大小为4.0m - 打包页面,在浏览器中打开index.html
可以看到,chunk-vendor文件大概800多k; - 配置为按需引入,src/main.js:
import Vue from 'vue' import App from './App.vue' import {Button, Input} from 'demo-vuecli2-ui' Vue.use(Button) Vue.use(Input) Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app')
- 启动,检查效果:
可以看到,app.js变为了1.8m - 打包,然后直接打开index.html,检查效果:
可以看到,chunk-vendor变成了80k大小 - 至此,vuecli2工程组件库按需引入说明已经结束
- 打开test-load-on-demand工程,安装