mpvue 如何对小程序进行分包?
Closed this issue · 7 comments
曾试过直接在main里面按照小程序的分包配置,然而貌似不行
修改相关源码
你可以修改一下 mpvue-loader
,打开 node_modules/mpvue-loader/lib/mp-compiler/index.js
,从第220行开始,添加如下代码
// 移除 app.json 中 pages 中包含的小程序分包页面
if (Array.isArray(configObj.subPackages)) {
for (let subPackages of configObj.subPackages) {
if (Array.isArray(subPackages.pages)) {
for (let page of subPackages.pages) {
const pageIndex = pages.findIndex(v => v === `${subPackages.root}/${page}`)
pageIndex > -1 && pages.splice(pageIndex, 1)
}
}
}
}
如果使用了 mpvue-entry
,则修改 node_modules/mpvue-entry/lib/utils/compiler.js
,第75行开始,添加如下代码
// app.pages = pages.map(page => page.path.replace(/^\//, ''));
const newPages = pages.map(page => page.path.replace(/^\//, ''));
// 移除 app.json 中 pages 中包含的小程序分包页面
if (Array.isArray(app.subPackages)) {
for (let subPackages of app.subPackages) {
if (Array.isArray(subPackages.pages)) {
for (let page of subPackages.pages) {
const pageIndex = newPages.findIndex(v => v === `${subPackages.root}/${page}`)
pageIndex > -1 && newPages.splice(pageIndex, 1)
}
}
}
}
app.pages = newPages
使用
src/main.js
export default {
...
subPackages: [
{
// 登录注册模块
root: 'pages/auth',
pages: [
'login/login',
'register/register'
]
},
{
// 购物车
root: 'pages/shopping',
pages: [
'checkout/checkout',
'confirmOrder/confirmOrder',
'store/store',
'store/storeInMap/storeInMap',
'store/storeInMap/calendar/calendar'
]
},
{
// 商品展示
root: 'pages/goods',
pages: [
'goods',
'goodsList/goodsList',
'brandGoodsList/brandGoodsList',
'hotGoodsList/hotGoodsList'
]
},
{
// 我的页面
root: 'pages/mine',
pages: [
'address/address',
'address/addressAdd/addressAdd',
'collect/collect',
'coupon/coupon',
'history/history'
]
},
{
// 我的个人资料
root: 'pages/mineInfo',
pages: [
'mineInfo',
'editPw/editPw',
'editUavatar/editUavatar',
'editUname/editUname',
'editUphone/editUphone'
]
},
{
// 订单相关
root: 'pages/order',
pages: [
'order',
'addComment/addComment',
'express/express',
'orderDetail/orderDetail',
'selfExDetail/selfExDetail'
]
},
{
// 设置
root: 'pages/setting',
pages: [
'setting',
'about/about',
'feedback/feedback'
]
}
]
...
}
按照上面配置,可以实现小程序分包,但是你会发现主包会很大。为什么呢?
来了解一下 mpvue 资源文件的打包机制
这就解释了为什么分包之后主包那么大,因为我那些 次包包含的js/wxml/wxss
并不在次包里面,而是被打包进主包了 。
那如果我们 把各个页面引用的资源文件打包进页面所在文件夹 呢,是不是可以解决这个问题了。我们来试一试。
尝试
修改 mpvue-loader
主要是为了处理将页面对应的 components/xxx.wxml
打包进页面所在的文件夹下。
node_modules/mpvue-loader/lib/mp-compiler/index.js
# 第26行添加
// 缓存组件对应的入口路径
const pagesCompMap = Object.create(null)
function cachePagesComp(componentName, src) {
pagesCompMap[componentName] = src
}
# 紧接着找到 createAppWxml 函数
function createAppWxml (emitFile, resourcePath, rootComponent) {
const { src } = getFileInfo(resourcePath) || {}
const componentName = getCompNameBySrc(rootComponent)
# 添加这一句
cachePagesComp(componentName, src)
const wxmlContent = genPageWxml(componentName, src)
const wxmlSrc = src
emitFile(`${wxmlSrc}.wxml`, wxmlContent)
}
# createWxml 函数
function createWxml (emitWarning, emitError, emitFile, resourcePath, rootComponent, compiled, html) {
cacheCreateWxmlFns[resourcePath] = arguments
const { pageType, moduleId, components } = getFileInfo(resourcePath) || {}
const name = getCompNameBySrc(resourcePath)
const options = { components, pageType, name, moduleId }
const wxmlContent = genComponentWxml(compiled, options, emitFile, emitError, emitWarning)
# 修改这里
const wxmlSrc = pagesCompMap[name] ? `${pagesCompMap[name]}/components/${name}` : `components/${name}`
emitFile(`${wxmlSrc}.wxml`, wxmlContent)
}
# resolveSrc 函数
function resolveSrc (originComponents, components, resolveFn, context) {
return Promise.all(Object.keys(originComponents).map(k => {
return new Promise((resolve, reject) => {
resolveFn(context, originComponents[k], (err, realSrc) => {
if (err) return reject(err)
const com = covertCCVar(k)
const comName = getCompNameBySrc(realSrc)
# 修改这里
components[com] = { src: `/components/${comName}`, name: comName }
resolve()
})
})
}))
}
node_modules/mpvue-loader/lib/mp-compiler/templates.js
,直接复制粘贴
const { getPathPrefix } = require('./util')
function genScript (name, isPage, src) {
const prefix = isPage ? getPathPrefix(src) : './'
return `
require('${prefix}manifest/js/main.js')
require('${prefix}vendor/js/main.js')
require('${prefix}${name}/js/main.js')
`
}
function genStyle (name, isPage, src) {
const prefix = isPage ? getPathPrefix(src) : './'
return `@import "/${name}/css/main.wxss";`
}
function genPageWxml (templateName, src) {
return `<import src="/${src}/components/${templateName}" /><template is="${templateName}" data="{{ ...$root['0'], $root }}"/>`
}
module.exports = { genScript, genStyle, genPageWxml }
修改项目打包配置
这里修改是为了处理将 js
和 wxss
打包到对应页面文件夹下。
/build/webpack.dev.conf.js
...
module.exports = merge(baseWebpackConfig, {
...
output: {
path: config.build.assetsRoot,
// filename: utils.assetsPath('js/[name].js'),
filename: path.posix.join('[name]/js/main.js'),
// chunkFilename: utils.assetsPath('js/[id].js')
chunkFilename: path.posix.join('[id]/js/main.js')
},
plugins: [
...
new ExtractTextPlugin({
// filename: utils.assetsPath('css/[name].wxss')
filename: path.posix.join('[name]/css/main.wxss')
}),
...
]
})
/build/webpack.prod.conf.js
...
const webpackConfig = merge(baseWebpackConfig, {
...
output: {
path: config.build.assetsRoot,
// filename: utils.assetsPath('js/[name].js'),
filename: path.posix.join('[name]/js/main.js'),
// chunkFilename: utils.assetsPath('js/[id].js')
chunkFilename: path.posix.join('[id]/js/main.js')
},
plugins: [
...
new ExtractTextPlugin({
// filename: utils.assetsPath('css/[name].wxss')
filename: path.posix.join('[name]/css/main.wxss')
}),
...
]
})
...
打包试一试
可以看到,主包大小由原来的 295k 变为 249k 。
mpvue-entry v1.4.0 起支持直接配置分包,因为会重写一次 app.json,所以不需要改动 mpvue-loader 中生成 app.json 相关的代码了
集成了一下上面分享的方法,可以直接使用这个模板建立项目 https://github.com/F-loat/mpvue-quickstart
@auven 问一下 是哪个版本的mpvue-loader
我按照楼主的那个方式分包,但是报错,configObj is not defined