小程序多业务线融合【完整分包业务接入】 (2)

我们对测试环境和正式环境分别配置了webpack,通过对webpack配置替换全局变量,直接修改项目的全局参数
通过npm命令动态执行替换。

为了分开配置,我们拷贝了一份build.js更名为build-subpkg.js

"scripts": { ..., "build_subPkg": "node build/build-subpkg.js && sh ./scripts/path-replace.sh" }

build_subPkg命令就是读取的build-subpkg.js文件
build.js和build-subpkg.js中99%的内容都一样,只有一行不一样

var webpackConfig = require('./webpack.prod.conf') 变更为 var webpackConfig = require('./webpack.subpkg.prod.conf')

所以下一步就是创建webpack.subpkg.prod.conf文件
webpack.subpkg.prod.conf由webpack.prod.conf拷贝而来,里面依旧99%的内容一致

// webpack.prod.conf

... var config = require('../config') var env = config.build.env ... var webpackConfig = merge(baseWebpackConfig, { ... plugins: [ new webpack.DefinePlugin({ 'process.env': env, 'app.source': env.APP_SOURCE, 'app.udeskDebug': env.UDESK_DEBUG, 'app.id': env.APP_ID, 'app.pathPrefix': env.APP_PATH_RREFIX, 'app.isUseCrazyFormId': env.IS_USE_CRAZY_FORMD_ID }), ... ] })

// webpack.subpkg.prod.conf

... var config = require('../config') var env = config.build.env ... var webpackConfig = merge(baseWebpackConfig, { ... plugins: [ new webpack.DefinePlugin({ 'process.env': env, 'app.source': env.APP_SUB_PKG_SOURCE, 'app.udeskDebug': env.UDESK_DEBUG, 'app.id': env.APP_SUB_PKG_ID, 'app.pathPrefix': env.APP_SUB_PKG_PATH_RREFIX, 'app.isUseCrazyFormId': env.IS_USE_CRAZY_FORMD_ID }), ... ] })

DefinePlugin插件是用来进行全局替换的
如:'process.env': '"hahaha"', 指的就是全局process.env替换为"hahaha"

里面通过定义多个全局变量,实现打包时,通过不同的命令替换对应环境下的全局变量
我们看一下../config/index.js中的文件

var path = require('path') module.exports = { build: { env: require('./prod.env'), ... }, dev: { env: require('./dev.env'), ... } }

引入了dev.env.js和prod.env.js

以prod.env.js为例

module.exports = { // 环境 NODE_ENV: '"production"', // 欢乐送独立小程序source APP_SOURCE: '114', // 欢乐送分包小程序source APP_SUB_PKG_SOURCE: '103', // 欢乐送独立程序appid APP_ID: '"wxaaaaaaaaaaaaaaa"', // 欢乐送分包程序appid APP_SUB_PKG_ID: '"wxbbbbbbbbbbbbbbbb"', // udesk测试标志位 UDESK_DEBUG: false, // 欢乐送独立小程序页面路径前缀 APP_PATH_RREFIX: '""', // 欢乐送分包小程序页面路径前缀 APP_SUB_PKG_PATH_RREFIX: '"/subPages/enjoy_given"', // 是否启用crazyFormId IS_USE_CRAZY_FORMD_ID: true }

然后我们再来看一下存放全局变量的文件src/vars.js(上面项目截图中有)

// 小程序常量 export default { ... // 小程序版本号 version: '1.3.5', // 小程序appid appId: app.id, // 小程序source(由webpack根据不同环境统一替换) source: app.source, // 路径前缀 pathPrefix: app.pathPrefix, // 是否启用CrazyFormId isUseCrazyFormId: app.isUseCrazyFormId } var webpackConfig = merge(baseWebpackConfig, { ... plugins: [ new webpack.DefinePlugin({ 'process.env': env, 'app.source': env.APP_SUB_PKG_SOURCE, 'app.udeskDebug': env.UDESK_DEBUG, 'app.id': env.APP_SUB_PKG_ID, 'app.pathPrefix': env.APP_SUB_PKG_PATH_RREFIX, 'app.isUseCrazyFormId': env.IS_USE_CRAZY_FORMD_ID }), ... ] })

在打包完成后,全局变量文件中的"app.xxx"会被webpack中的同名变量替换掉

如vars.js中 appId: app.id的app.id会被替换,独立小程序时该值为"wxaaaaaaaaaaaaaaa",作为分包业务时,该值为"wxbbbbbbbbbbbbbb"

这样整个替换全局变量的流程就跑完了

==作为分包,接入主程序中,自己的main.js和App.vue都不会执行==

这个是大坑,因为很多通用业务的初始化如登录、cookie、统计都是在这里完成的。

解决方案

把基础功能的装配业务(如在录、统计、识别渠道号等逻辑)从main.js中抽离到另一个文件,我这里叫baseInstall.js。
里面我还加入了对query的处理,比如渠道号channel和微信入口scene。

那这样的话,src/main.js就会变得非常简单,

import Vue from 'vue' import App from './App' import baseInstall from './baseInstall' App.mpType = 'app' baseInstall.init() // !!!最关键就是这行代码!!! const app = new Vue(App) app.$mount() export default { config: { pages: [ '^pages/content/index/main', // 首页 ... ], window: { ... } } }

里面最关键的是baseInstall.init()这行代码

下面我们来看看baseInstall.js

// 通用业务装配初始化 ... async function init (opts) { let options = opts ... // 获取指定渠道号 const channel = options.channel || options.c || '' // 设置渠道号 if (channel) { VARS.channel = channel.indexOf('waeg_') === 0 ? channel : ('waeg_' + channel) } ... if (!VARS.baseInstallFlag) { // 为了避免重复装备,通过标志位进行区分 VARS.baseInstallFlag = true ... // 登录配置 ZZLogin.config({ source: VARS.source }) ZZLogin.install() Navigator.install() // 统计 LeStatic.config({ appid: VARS.source, pageTypePrefix (currentRoute) { return 'waeg_' } }).install() ... } // 写入cookie cookie.set({ channelid: VARS.channel, fromShareUid: VARS.shareUid }) return options } export default { init } 为什么要用VARS.baseInstallFlag标志位

因为,在分包时候是不执行main.js的,实际场景,会从主包的业务直接跳转到分包的一些页面。

由于没有固定入口,所以在这些页面中都要加入baseInstall.js的引入,为了避免重复装配,才会设置这个标志位。

为什么要把这些业务抽离

baseInstall.init里面涵盖了所有启动小程序时需要初始化的业务

前面也提到了在作为分包时,自己的App.vue和main.js是不会执行的。

那怎么办,这样,就在所有的页面中,在onLoad的生命周期中加入baseInstall.init方法。
,所以我们抽离肯定是为了更方便的复用了。

以首页为例(pages/content/index/index.vue)

import baseInstall from '@/baseInstall' export default { ... async onLoad (options) { options = await baseInstall.init(options) ... } }

用async/await是因为baseInstall.init中部分逻辑用到了异步请求

因为主程序不会读取main.js,所以,所有的分包页面路径,都要统一在主程序中注册

注:每新增一个页面,都要在主程序中注册。也就是新增一个页面,就要通知主程序那边,在他们的文件里统一注册

页面路径

在分包中,所有页面路径访问要加入前缀

如:原来访问/pages/content/index/main就可以了

但是分包的访问路径为:/subPages/enjoy_given/pages/content/index/main

解决方案:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwfyd.html