黑客与画家
黑客与画家
  • 发布:2022-02-07 18:43
  • 更新:2024-01-23 16:36
  • 阅读:6843

uniapp使用微信小程序分包异步化能力临时方案

分类:uni-app

背景

参考问题:uniapp开发微信小程序如何使用分包异步化特性,目前(2022/02/07)uniapp中的pages.json配置不支持分包异步化的特性(按照微信官方文档配置,构建后并不会在app.json文件生成对应的配置,猜测是因为分包异步化中的pages为空,构建代码过滤了,有空查看构建源码确认一下)。

这里应该由uniapp官方支持一下这个功能,目前项目需要,先用下面的临时方案

解决方案

思路:在uniapp构建完成后,添加自己的构建脚本,做以下的事情

  1. 读取pages.json
  2. 判断pages.json中是否有配置分包异步化
  3. 把分包异步化相关配置写入app.json
  4. 寻找用到分包组件的地方(小程序的页面 or 组件json配置文件),注入组件占位(不注入的话小程序会报错导致分包内组件无法使用)

构建脚本源码

/* eslint-disable @typescript-eslint/no-require-imports */  
const fs = require('fs');  
const path = require('path');  

console.log('开始处理异步化分包...');  

// 读取pages.json  
const pagesConfig = (() => {  
  const configPath = path.resolve(__dirname, '../../../pages.json'); // @NOTE 这里要根据脚本执行的路径改一下  
  const pages = fs.readFileSync(configPath, 'utf8');  
  // @NOTE 移除注释  
  let pagesJson = pages.replace(/\/\*.*\*\//g, '');  
  pagesJson = pagesJson.replace(/\/\/.*/g, '');  
  return JSON.parse(pagesJson);  
})();  

// 读取page.json中的异步分包(没有配置pages)  
const asyncPackages = (pagesConfig.subPackages || []).filter(package => !package.pages || package.pages.length === 0);  
// console.log(pagesConfig, asyncPackages);  

// 写入app.json  
const distPath = path.resolve(__dirname, '../../../../dist/build/mp-weixin'); // @NOTE 这里要根据脚本执行的路径改一下  
const appJsonPath = path.resolve(distPath, 'app.json');  
const appJson = JSON.parse(fs.readFileSync(appJsonPath, 'utf8'));  
if (!appJson.subPackages) {  
  appJson.subPackages = [];  
}  
asyncPackages.forEach((package) => {  
  const hasInject = appJson.subPackages.find(pack => pack.root === package.root);  
  if (hasInject) {  
    return;  
  }  
  appJson.subPackages.push({  
    root: package.root,  
    pages: [],  
  });  
});  
fs.writeFileSync(appJsonPath, JSON.stringify(appJson));  

// 寻找用到分包组件的地方,注入组件占位(不注入的话小程序会报错导致分包内组件无法使用)  
const ignorePaths = [];  
ignorePaths.push(appJsonPath); // 过滤app.json  
asyncPackages.forEach((package) => {  
  ignorePaths.push(path.join(distPath, package.root)); // 过滤分包的内容  
});  
const injectPlaceholder = (filepath) => {  
  // 判断是否用到了分包的组件  
  const jsonConfig = require(filepath);  
  if (!jsonConfig.usingComponents) {  
    return;  
  }  
  const subPackageComponents = [];  
  // @TODO 可以考虑使用map来加快查找速度  
  Object.keys(jsonConfig.usingComponents).forEach((componentName) => {  
    const componentPath = jsonConfig.usingComponents[componentName];  
    const targetSubPackage = asyncPackages.find(package => componentPath.startsWith(`/${package.root}`));  
    if (targetSubPackage) {  
      // 防止重复添加  
      // eslint-disable-next-line @typescript-eslint/prefer-optional-chain  
      if (jsonConfig.componentPlaceholder && jsonConfig.componentPlaceholder[componentName]) {  
        return;  
      }  
      subPackageComponents.push(componentName);  
    }  
  });  
  if (subPackageComponents.length === 0) {  
    return;  
  }  
  console.log('开始处理: ', filepath);  
  if (!jsonConfig.componentPlaceholder) {  
    jsonConfig.componentPlaceholder = {};  
  }  
  subPackageComponents.forEach((name) => {  
    jsonConfig.componentPlaceholder[name] = 'view'; // 占位符全用view组件  
  });  
  fs.writeFileSync(filepath, JSON.stringify(jsonConfig));  
  console.log('处理完成: ', filepath);  
};  
findJSON(distPath, ignorePaths, injectPlaceholder);  
console.log('异步化分包处理完成');  

function findJSON(folder, ignorePaths, cb) {  
  fs.readdirSync(folder).forEach((filename) => {  
    const filepath = path.join(folder, filename);  
    const isIgnore = ignorePaths.some(ignorePath => filepath.startsWith(ignorePath));  
    if (isIgnore) {  
      return;  
    }  
    const stat = fs.statSync(filepath);  
    if (filename.endsWith('.json')) {  
      cb(filepath);  
      return;  
    }  
    if (stat.isDirectory()) {  
      findJSON(filepath, ignorePaths, cb);  
    }  
  });  
}  

最后

目前用这个方式解决了分包异步化中使用分包内的组件问题,至于分包内的js使用,大家可以验证一下,我暂时没有这个场景,所以没有验证。

上面的代码编写没有review,但测试过单个分包配置的场景,项目使用的时候请谨慎。

最后还是希望官方大佬支持一下分包异步化这个特性。

11 关注 分享
L***@163.com 2***@qq.com 1***@qq.com 1***@qq.com dashuai 1***@qq.com z***@163.com DDante 1***@qq.com 1***@qq.com DCloud_UNI_HRK

要回复文章请先登录注册

L***@163.com

L***@163.com

希望官方支持一下,这个异步分包有时真的需要
2022-02-23 11:15