Kbone 是什么?
Kbone 是一个致力于微信小程序和 Web 端同构的解决方案,在适配层里模拟出浏览器环境,让 Web 端的代码可以不做什么改动便可运行在小程序里。
开发准备
- 安装脚手架/初始化项目
npm install -g kbone-clikbone init to-do-list - 代码构建
npm run build
(具体的页面介绍后面会讲到) - 项目运行
小程序端:npm run mp
Web端:npm run web
通过两个命令把项目运行起来你就会发现 Kbone 的神奇之处,通过一份代码(这里我是基于 Vue)你就可以拥有两端的效果,再也不用担心同时维护两份代码了。
预览
正式开始之前我们先看看效果图,感受一下 Kbone 框架一份代码跑两端的神奇
Kbone 目录了解
├─ build
│ ├─ miniprogram.config.js // mp-webpack-plugin 配置
│ ├─ webpack.base.config.js // Web 端构建基础配置
│ ├─ webpack.dev.config.js // Web 端构建开发环境配置
│ ├─ webpack.mp.config.js // 小程序端构建配置
│ └─ webpack.prod.config.js // Web 端构建生产环境配置
├─ dist
│ ├─ mp // 小程序端目标代码目录,使用微信开发者工具打开,用于生产环境
│ └─ web // web 端编译出的文件,用于生产环境
├─ src
│ ├─ common // 通用组件
│ ├─ mp // 小程序端入口目录
│ │ ├─ home // 小程序端 home 页面
│ │ │ └─ main.mp.js // 小程序端入口文件
│ │ └─ other // 小程序端 other 页面
│ │ └─ main.mp.js // 小程序端入口文件
│ ├─ detail // detail 页面
│ ├─ home // home 页面
│ ├─ list // list 页面
│ ├─ router // vue-router 路由定义
│ ├─ store // vuex 相关目录
│ ├─ App.vue // Web 端入口主视图
│ └─ main.js // Web 端入口文件
└─ index.html // Web 端入口模板
通过官方给我们的这个目录结构,我们可以很清晰的看到每个目录下各个文件的作用。这里我就对其中的一些文件进行解释一下。
miniprogram.config.js
这个文件是关于小程序端的一些配置,类似于原生的 json 配置
webpack.mp.config.js
小程序端构建配置,也就是构建小程序端代码的 webpack 配置,多页开发中会用到其中的一部分配置。
src/mp & main.mp.js
mp 用来存放小程序端的入口文件,这里设置小程序的一些页面,main.mp.js 相当于一个挂载操作,把它看成 mpvue 里面的 main.js 比较好理解,设置页面路由和挂载映射 Vue 里面的页面。
(其他的比较好理解,我就不一一赘述了)
Kbone 进阶 —- 多页开发
Vue 路由配置
Vue 的路由配置比较简单,直接在 src/router/index.js 下配置就好了,比较简单,不多说。
import Vue from 'vue';import Router from 'vue-router';const Home = () => import( /* webpackChunkName: 'Home' */ '@/pages/home/Index.vue');const About = () => import( /* webpackChunkName: 'About' */ '@/pages/home/about.vue');const Cart = () => import( /* webpackChunkName: 'Cart' */ '@/pages/cart/index.vue');Vue.use(Router);export default new Router({mode: 'history',routes: [{path: '/(home|index)?',name: 'Home',component: Home,},{path: '/list',name: 'About',component: About,},{path: '/cart',name: 'Cart',component: Cart}],});
小程序端页面建立/挂载
之前已经介绍过 src/mp 下存放的是小程序端的入口文件,也就是相当于小程序端页面的对于 Vue 页面的映射,每个文件夹下很简单,就一个 main.mp.js
import Vue from 'vue'import Router from 'vue-router'import {sync} from 'vuex-router-sync'import App from '../App.vue'import store from '../store'import Home from '../pages/home.vue'import KboneUI from 'kbone-ui'import 'kbone-ui/lib/weui/weui.css'Vue.use(Router)const router = new Router({mode: 'history',routes: [{path: '/(home|index)?',name: 'Home',component: Home,}],})export default function createApp() {const container = document.createElement('div')container.id = 'app'document.body.appendChild(container)Vue.config.productionTip = falsesync(store, router)Vue.use(KboneUI)return new Vue({el: '#app',router,store,render: h => h(App)})}
小程序入口
配置到了上一步,你可能觉得已经差不多了,因为在 Web 端已经可以通过路由看到效果了,然而在小程序端还看不到具体的效果甚至还在报错,这是因为少了关键的一步 —- 小程序页面入口文件的设置。
举个例子来说,上一步我们是给小程序的页面配好了钥匙,但是还没有把它拿过来去开相应的锁,现在我们就要拿它来开相应的的锁(小程序入口配置) —- webpack.mp.config.js
// webpack.mp.config.jsentry: {// js 入口home: path.resolve(__dirname, '../src/mp/home/main.mp.js'),list: path.resolve(__dirname, '../src/mp/list/main.mp.js'),cart: path.resolve(__dirname, '../src/mp/cart/main.mp.js'),},
tabBar 配合
配置好了入口仅仅只能看到首页(/index)的效果,这就需要使用 tabBar 了。
tabBar: {
color: "#000000",
selectedColor: "#ffbf37",
backgroundColor: "#ffffff",
list: [{
pageName: 'home',
text: '英雄',
iconPath: path.resolve(__dirname, '../src/assets/image/1.png'),
selectedIconPath: path.resolve(__dirname, '../src/assets/image/1.png'),
}, {
pageName: 'list',
text: '地图',
iconPath: path.resolve(__dirname, '../src/assets/image/2.png'),
selectedIconPath: path.resolve(__dirname, '../src/assets/image/2.png'),
}],
// 使用自定义 tabBar
custom: path.join(__dirname, '../src/custom-tab-bar'),
},
小结
总的来说使用 Kbone 进行多页开发的步骤就是:
- 设置 Vue 路由
- 建立对应页面并进行小程序页面挂载注册
- 修改小程序入口并配置对应的路由(如果有需要可以继续配置 tabBar)
采坑总结
关于样式
scss配置
小程序默认是less语言,如果要使用scss语言需要配置scss。命令行:npm install sass node-sass sass-loader —save
// 文件 webpack.dev.config.js
{
test: /\.(scss|sass)$/,
use: [{
loader: 'vue-style-loader',
}, {
loader: 'css-loader',
}, {
loader: 'postcss-loader',
options: {
plugins: [
autoprefixer,
],
}
}, {
loader: 'sass-loader',
}],
}
// 文件 webpack.mp.config.js
{
test: /\.(scss|sass)$/,
use: [{
loader: MiniCssExtractPlugin.loader,
options: {
modules: true,
},
},
{
loader: 'css-loader'
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => {
return [
autoprefixer,
stylehacks(), // 剔除 ie hack 代码
]
}
}
},
{
loader: 'sass-loader'
}
],
},
// 文件 webpack.prod.config.js
{
test: /\.(scss|sass)$/,
use: [{
loader: MiniCssExtractPlugin.loader,
}, {
loader: 'css-loader',
}, {
loader: 'postcss-loader',
options: {
plugins: [
autoprefixer,
],
}
}, {
loader: 'sass-loader',
}],
}
图片资源
在写 demo 的时候发现一个问题,页面需要的图片资源构建的时候始终带不过去,查了一下官方提供的文档,目前暂不支持相对路径,静态资源可以考虑转成 base64 或者使用网络地址,我这里的处理办法是将图片上传到重构服务器,然后在webpack配置公共url,页面写相对路径,就能正常显示啦。(注意:本地的图片名要与服务器的图片名保持一致)
// webpack.base.config.js
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
name: '[name].[ext]',
limit: 1024,
publicPath: 'https://test.mwegame.qq.com/ui/images', // 对于资源文件直接使用线上的 cdn 地址
},
}
// webpack.mp.config.js
{
test: /\.(png|jpg|jpeg|gif|svg|eot|woff|woff2|ttf)$/,
use: [{
loader: 'url-loader',
options: {
limit: 1024,
name: '[name].[ext]',
publicPath: 'https://test.mwegame.qq.com/ui/images', // 对于资源文件直接使用线上的 cdn 地址
emitFile: false,
}
}],
},
小程序适配
rpx 在 kbone 中好像不支持,尝试过 vue+kbone 对 web 端采用px适配,在构建小程序时希望能转成rpx,但可惜的是不会这样,去微信开放社区看了一下说要用 rem 做适配(要在 mp-webpack-plugin 这个插件的配置中的 global 字段内补充 rem 配置)
// miniprogram.config.js
global: {
rem: true
},
// 结合重构适配规则,需要在App.vue做适配
created() {
window.onload = function () {
if (process.env.isMiniprogram) {
document.documentElement.style.fontSize = 100 / 1080 * wx.getSystemInfoSync().screenWidth + "px"
}
}
}
关于分包
由于小程序最大限制是2048KB,我这边小程序构建出的代码超出这个限制就预览不了,后面我配置了小程序分包,查看分包成功了但是小程序还是报超出限制。查了资料,原来是kbone打包的mp文件不会自动更新,需要手动删除重新打包,小程序工具也需要重新打开。
subpackages: {
// all:['all'], // 默认首次进入的页面不需要配置分包
login: ["login"],
home: ["home"]
},
},
构建npm样式
开发者工具报错 Uncaught Error: module "pages/ home/miniprogram-render" is not defined
解决方案:开发者工具重新构建 npm
如果还是无法解决,删除打包出来的小程序文件,重新打包
总结
kbone解决了长久以来微信小程序和 Web 两个端的代码问题,在实际中可以少写一份代码,极大的减轻了开发和维护的工作量,虽然目前还存在一些 bug,但是我相信开发团队一定会努力的完善它。如果你觉得有用的话也用起来吧~ (Kbone 官方技术文档👉文档)

