Vue项目使用kbone打包成小程序的踩坑笔记
以下内容是初版kbone的笔记,现在kbone进行了大量的更新升级,以下配置方法大部分已经不适用新版kbone了,如需详细了解kbone的使用方法,请参考官方文档
kbone是大佬 @June 开发的一款Vue项目打包成小程序的工具(暂时只支持微信小程序)
已有的Vue项目只需通过简单的配置即可打包成小程序的代码,新项目也可以使用这个工具进行同步开发,项目中提供了很多示例供参考
Github连接:https://github.com/wechat-miniprogram/kbone
为什么选择kbone?
市面上有很多跨平台的框架,如: WePY、mpvue、uni-app、taro等
他们都有一些弊端和限制,现有的项目迁移不方便,对第三方组件库不兼容等
kbone作为一款工具,也可以说是一款webpack插件(Vue项目只需要引入 mp-webpack-plugin 插件,通过简单的webpack配置即可),无论是对新项目还是已有项目都是非常友好的,因为他完整的移植了Vue Runtime,通过webpack将Vue代码打包成小程序兼容的代码,通过适配器运行,所以大部分的第三方组件库是兼容的
如何使用?
Github仓库中提供了很多示例,有兴趣的可以体验下,下面介绍下我的使用过程
创建项目
因为习惯了使用Vue Cli,所以我选择使用这个工具初始化一个项目,使用的版本是Vue Cli 3(这个工具提供了一套完全图形化的用户界面,这里就不介绍使用方法了,没有使用过的同学可以 点击这里 查看创建方法)
集成插件
kbone目前还没有提供Vue Cli的插件(大佬很忙,有能力的同学可以在Github上提PR),所以需要手动添加,具体的操作方式请参考QuickStart文档
安装 mp-webpack-plugin 插件
[代码]yarn add mp-webpack-plugin --dev
# 或者
npm install mp-webpack-plugin --save-dev
[代码]
在 src 目录中新增 main.mp.js 入口文件
[代码]import Vue from 'vue'
import App from '@/App'
import router from '@/router'
import store from '@/store'
// 需要将创建根组件实例的逻辑封装成方法
export default function createApp () {
// 在小程序中如果要注入到 id 为 app 的 dom 节点上,需要主动创建
const container = document.createElement('div')
container.id = 'app'
document.body.appendChild(container)
Vue.config.productionTip = false
return new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
}
[代码]
在根目录创建 miniprogram.config.js 文件,添加 mp-webpack-plugin 插件配置
[代码]module.exports = {
// 页面 origin,默认是 https://miniprogram.default
origin: '', // 填写项目中的图片资源地址,建议图片资源使用线上地址
// 入口页面路由,默认是 /
entry: '/',
// 页面路由,用于页面间跳转
router: {
// 路由可以是多个值,支持动态路由
index: []
},
// 特殊路由跳转
redirect: {
// 跳转遇到同一个 origin 但是不在 router 里的页面时处理方式,支持的值:webview - 使用 web-view 组件打开;error - 抛出异常;none - 默认值;什么都不做,router 配置项中的 key
notFound: 'index',
// 跳转到 origin 之外的页面时处理方式,值同 notFound
accessDenied: 'index'
},
// app 配置,同 https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#window
app: {
navigationStyle: 'custom' // 自定义navigation
},
// 全局配置
global: {},
// 页面配置,可以为单个页面做个性化处理,覆盖全局配置
pages: {},
// 优化
optimization: {
domSubTreeLevel: 5, // 将多少层级的 dom 子树作为一个自定义组件渲染,支持 1 - 5,默认值为 5
// 对象复用,当页面被关闭时会回收对象,但是如果有地方保留有对象引用的话,注意要关闭此项,否则可能出问题
elementMultiplexing: true, // element 节点复用
textMultiplexing: true, // 文本节点复用
commentMultiplexing: true, // 注释节点复用
domExtendMultiplexing: true, // 节点相关对象复用,如 style、classList 对象等
styleValueReduce: 5000, // 如果设置 style 属性时存在某个属性的值超过一定值,则进行删减
attrValueReduce: 5000 // 如果设置 dom 属性时存在某个属性的值超过一定值,则进行删减
},
// 项目配置,会被合并到 project.config.json
projectConfig: {
appid: '', // 填写小程序的AppId
projectname: '' // 填写小程序的项目名称
},
// 包配置,会被合并到 package.json
packageConfig: {
name: '', // 项目名称
description: '', // 描述
author: '' // 作者信息
}
}
[代码]
在根目录创建 .env.mp 文件,添加 mp 环境变量
[代码]NODE_ENV = mp
[代码]
修改 vue.config.js 文件,添加打包小程序的 webpack 配置
[代码]const path = require('path')
function resolve (dir) {
return path.join(__dirname, dir)
}
const webpack = require('webpack')
const MpWebpackPlugin = require('mp-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
css: {
extract: true
},
outputDir: process.env.NODE_ENV === 'mp' ? './dist/mp/common' : './dist/web',
configureWebpack: {
resolve: {
extensions: ['*', '.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src')
}
}
},
chainWebpack: config => {
if (process.env.NODE_ENV === 'mp') {
config
.devtool('node')
.entry('app').clear().add('./src/main.mp.js').end()
.output.filename('[name].js')
.library('createApp')
.libraryExport('default')
.libraryTarget('window').end()
.target('web')
.optimization.runtimeChunk(false)
.splitChunks({
chunks: 'all',
minSize: 1000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 100,
maxInitialRequests: 100,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}).end()
.plugins.delete('copy').end()
.plugin('define').use(new webpack.DefinePlugin({
'process.env.isMiniprogram': process.env.isMiniprogram // 注入环境变量,用于业务代码判断
})).end()
.plugin('extract-css').use(new MiniCssExtractPlugin({
filename: '[name].wxss',
chunkFilename: '[name].wxss'
})).end()
.plugin('mp-webpack').use(new MpWebpackPlugin(require('./miniprogram.config.js'))).end()
}
}
}
[代码]
修改 package.json 中的 scripts 属性,添加用于开发和打包的任务
[代码]# 开发
"mp-serve": "vue-cli-service build --watch --mode mp"
# 打包
"mp-build": "vue-cli-service build --mode mp"
[代码]
配置完成,尽情玩耍吧!
目前已知的问题
小程序中无法支持 getComputedStyle 和 getBoundingClientRect 的同步接口,只能异步,所以依赖这两个方法的第三方库,需要进行改造
因为大佬很忙目前还处于开发阶段,很多组件还没有适配,有能力和有精力的同学欢迎去Github提PR
再次奉上Github连接:https://github.com/wechat-miniprogram/kbone