加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 资源网站 > 资源 > 正文

如果将老项目的小程序快速改为分包模式

发布时间:2020-12-14 19:18:28 所属栏目:资源 来源:网络整理
导读:在最开始准备制作小程序的时候,为了求开发的快速,所使用了直接page的引入方式,每次小程序加载都是全包下载。3月份之前小程序页面稳定在35个,下载耗时在1800ms左右,4月份初上线了新业务页面膨胀到52个页面时,下载耗时基本稳定在2300ms左右,随着用户反

在最开始准备制作小程序的时候,为了求开发的快速,所使用了直接page的引入方式,每次小程序加载都是全包下载。3月份之前小程序页面稳定在35个,下载耗时在1800ms左右,4月份初上线了新业务页面膨胀到52个页面时,下载耗时基本稳定在2300ms左右,随着用户反馈越来越多,所以开始准备小程序采用分包加载,来解决这个问题。5月份在分包加载之后,页面依旧稳定在52个,但是下载耗时稳定800ms左右,缩短了将近1500ms。基本做到了0业务入侵、加入npm script 来实现新建页面,同时兼容分包加载,page加载。

操作流程

执行命令

npm run new
复制代码

弹出单选,并且输入路径

[Info] 帮助你快速创建page文件
[Info] 只局限于新目录创建
[Info] 请输入文件路径,已帮你省略pages/
[Info] 例子:address/addressList
? 请输入文件路径:
复制代码

输入路径之后创建文件的提示

选择包,是主包、还是分包,并且提示,如果是tabBar中使用,只能选择主包,并且手动配置app.json的tabBar

? 你想生成什么样的包: (Use arrow keys)
? 主包,在pages中写入,如果是tabBar中使用,只能选择主包,并且手动配置app.json的tabBar
  分包,在subpackages中写入
复制代码

单选完成之后提示新建成功

第一次分包

首先我们对未分包和分包的app.json代码进行对比

// 未分包
"pages": [
  "pages/a/index","pages/b/index",0);">"pages/b/list",]
复制代码
// 实现分包
"subpackages": [
  {
    "root": "pages/a",0);">"pages": [
      "index",]
  },{
    "pages/b",0);">"list"
    ]
  }
]
复制代码

接下来看目录结构

pages
  |---- a
        |---- index.js
  |---- b
        |---- index.js
        |---- list.js
app.json
复制代码

简单分一下,第一次分包的核心业务是,将pages这个普通列表,变成名为subpackages的二叉树状态结构,左子节点是root,右子节点是pages,并且右子节点是string类型,左子节点是array类型。好吧,我可以定下规则,首先我可以将?pages/a/index?这个字符串变为数组以?/?为分界的?['pages','a','index']?数组,然后我将前两项作为root节点的参数,用slice操作截取出来,转为字符串类型,赋值给root。之后的所有参数,我都赋值或者push给pages参数,最后我就得到了这样一个符合要求的树,最后push进subpackages即可。至于数据源,我只需要读出app.json这个文件的pages参数,并且通过我的方法写入subpackages参数即可。

要点

  • 去重,因为subpackages内,root节点是唯一的,但是在pages里面可能我会截取初重复的值

解决

  • 使用Map结构,把截取出的root值作为key,剩下的作为value,Map数据这种数据结构的特点就是key值唯一。
let list = [
  "pages/a/list",0);">"pages/a/detail/index",0);">"pages/c/list",];

let m = new Map();
let packages = [];
list.forEach(v=>{
  let arr = v.split('/');
  let root = arr.splice(0,2).join(let pages = arr.'/');

  if(m.get(root)){
    let s = m.get(root);
    m.set(root,[...s,pages]);
  }else{
    m.for(let [key,value] of m){
  packages.push({
    root: key,pages: value,})
}

console.log(packages);
复制代码
// log 出的结构
[
  { root: 'pages/a',pages: [ 'index',0);">'list',0);">'detail/index' ] },{ roo'pages/c',0);">'list' ] },0);">'pages/b',0);">'index' ] }
]
复制代码

我已经在不入侵业务的情况下实现了小程序的第一次分包,节约了我手动去改的劳动力,我个人认为,解决问题,上策用数据结构,中策写兼容代码,下策手动去改。至于,读出写入文件,我就不赘述了,google即可。

创建pages的指令编写

好吧,我实现了第一次的分包。然后我要思考,如果我每次要加页面的话,是不是就要去查看subpackages,找到对应的root,并且添加pages。这么重复劳动力的操作,我为什么不用脚本替代呢,是吧。

核心需求

  • 编写交互式的命令输入
  • 检测输入的page是否存在
  • 不存在创建page目录,复制template
  • 根据用户选择,选择写入pages,或者写入subpackages
  • 在page文件加中预留componet文件夹,用做业务拆分,不加检测page是否存在的方法
  • 引入静态文件,保存pages级别的目录,也不被检测

设计npm script

{
  "subcontract": "node ./config/subcontract",0);">"new": "node ./config/new"
}  
复制代码

添加的package.json参数

需求已经明确,我就要去找我需要用到的npm包了

colors        命令行颜色
inquirer      交互式命令行
glob          全局搜索文件
fs-extra      文件写入写出
path          路径
shelljs       执行shell命令
复制代码

分析?new.js?文件

);
const inquirer = 'inquirer');
const glob = 'glob');
const fs = 'fs-extra');
const path = 'path');
const shell = 'shelljs');
const PKG = '../package.json');
const ROOT = path.resolve(__dirname,0);">'../');

let appJson = '../app.json');
const promps = [{
  type: 'input',name: 'pagePath',message: '请输入文件路径:',},{
  'type',0);">'你想生成什么样的包:',choices: [
    {
      name: '主包,在pages中写入,如果是tabBar中使用,只能选择主包,并且手动配置app.json的tabBar',value: '1',{
      name: '分包,在subpackages中写入',0);">'2',}];
const logger = {
  info(msg) {
    console.log(`[Info] ${colors.green(msg)}`);
  },warn(msg) {
    `[Warn] ${colors.yellow(msg)}`);
  },error(msg) {
    `[Error] ${colors.red(msg)}(/‵Д′)/~ ╧╧`);
  },};

logger.info('帮助你快速创建page文件');
logger.info('只局限于新目录创建');
logger.info('请输入文件路径,已帮你省略pages/');
logger.info('例子:xxxxx/xxxx');
复制代码

这是代码中的常量部分和默认提示部分,我写了logeer对象来作为提示输出的默认颜色,promps作为我交互命令行的基础配置。引入package.json我的主要目的是因为我屏蔽了一些文件?ignore-files?和?pages?,想这两个参数的文件夹我是不会检测的。

function checkFile(name) {
  const options = {
    ignore: [
      '**/*.js',0);">'**/*.wxss',0);">'**/*.wxml',0);">'**/*.json',cwd: 'pages/',};
  const files = glob.sync('**',options);
  if (files.some((v) => v === name)) {
    logger.error('输入的目录已经存在,已终止!!!!');
    return false;
  };
  return name;
};
复制代码

检查文件夹是否存在这是检测文件是否存在的方法,我只需要得到路径,即可检测这个路径是否在目录中存在。

,0);">`**`,options);

  files.forEach((v)=>{
    const file = v.split('.tp')[0];
    fs.copy(`${ROOT}/template/page/${v}`,68);">${ROOT}/pages/${name}/${file}`,(err) => {
      if (err) {
        console.error(err);
        false;
      }
    });
    logger.info(`已创建${file}`);
  });
  logger.info('创建完成!!!!');
  true;
};
复制代码

这是复制文件夹并且复制模版文件的方法,我准备了tempalte这个文件夹,用来存储我写的模版文件,创建完成之后,我直接复制进去即可

) {
      PKG['ignore-files'].push(${res}/**`);
      PKG['pages'].push(${res}/index`);
      appJson[`pages/${res}/index`);
      fs.writeFileSync(${ROOT}/app.json`,JSON.stringify(appJson,null,0);">2));
      fs.writeFileSync(${ROOT}/package.json`,0);">JSON.stringify(PKG,0);">2));
      logger.info('写入成功');
    };
    '2') shell.exec('npm run subcontract');
  });
};
复制代码

这是选择pages还是subcontract的方法,选择了subcontract,我直接执行我上面写的小程序分包方法?subcontract.js?即可。如果选择pages,我会将它加入package.json中的?ignore-files对象,这个对象表式这些文件名不被subcontract脚本检测。

);

  if (!path) {
    logger.error('输入有失误,已终止!!!!');
    if (/.*[u4e00-u9fa5]+.*$/.test(path)) {
    logger.error('请不要输入中文符号,已终止!!!!');
    false;
  };

  return path;
};
复制代码

检测输入值是否合法,并且去除空格

( function() {
  const inquirerRes = await inquirers();
  const checkFileRes = inquirerRes && checkFile(inquirerRes);
  const buildFileRes = checkFileRes && buildFile(checkFileRes);
  buildFileRes && subcontract(checkFileRes);
})();
复制代码

最后组装,inquirerRes变量负责判断输入值是否正确。然后进入checkFile,来检测文件夹是否重复。调用buildFile方法,创建文件夹,复制模版文件。最后调用subcontract来判断是分包还是主包。

subcontract.js 分析

);
'../');
const PAG = '../app.json');

const ignoreFiles = PAG['ignore-files'];
const pages = PAG['pages'];
const subcontract = () => {
  const options = {
    ignore: ignoreFiles,0);">'**/index.js',options);

  let subcontractMap = new Map();
  files.forEach((v)=>{
    '.')[0].split('/');
    let root = arr.shift();
    let page = arr.join('/');

    if (subcontractMap.has(root)) {
      let pages = subcontractMap.get(root);
      pages.push(page);
      subcontractMap.set(root,pages);
    } else {
      subcontractMap.set(root,[page]);
    }
  });

  let subcontractList = [];
  subcontractMap.forEach((v,k)=>{
    subcontractList.push({
      root: ${k}`,pages: v,});
  });

  return subcontractList;
};

appJson.subpackages = subcontract();
appJson.pages = pages;
fs.writeFileSync(2));
logger.info('写入成功');
复制代码

这个方法其实和小程序第一次分包的方法大同小异。只不过我修改了数据源的获取,第一次我是读取app.json的pages,这里我是根据目录来的,以及加入了ignoreFiles来做文件屏蔽。以及一些友好提示。

结尾

项目优化的道路还有很长这只是最最初步的方案。为什么我开始不直接选择分包呢?因为项目开始的时候还没有分包,而且如果有,我感觉分包机制可能会带给开发者出错的可能性,我为了将项目工期缩短,出错可能性降低,我也不会选择一开始就分包。当业务增长到一定量,以及业务逐渐趋向于稳定时候,我就可以根据业务的特性,去做相对应的事情。这种方式我称之为技术迭代。在何时的时候,选择何时的业务,坚决不过度设计。到此为止,其实我最想输出的是思路。我关于上中下,三策的理解,我对业务的理解。谢谢。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读