guoxmin
guoxmin
  • 发布:2020-09-09 18:53
  • 更新:2022-04-24 11:03
  • 阅读:6352

uni-app如何支持npm分包

分类:uni-app

一、背景

我们美家移动端业务使用uni-app实现一码多端,目前上线了APP(包括Android和ios),微信小程序、百度小程序和H5。

从去年6月份以来,随着业务的快速发展,从最初单一产品线,不断孵化出包括逛逛美家、美家工作台APP、美家旺铺、美家直播Live、智能名片多个比较庞大的产品体系。之间存在大量可复用的模块、组件和页面,于是搭建npm私有仓库,目前接近50个包,接近400个版本,周下载量接近140次,接下来会加快节奏,将更多公共资源整合进来。

uni-app项目引入npm包(即使是分包页面引入),打包微信小程序后,都会统一编译到小程序根目录的 node-modules 文件夹。其中,我们有个自主开发的直播模块,打包后,接近1M大小,多个项目引入后,导致主包过大,如果粗暴将node-modules设为分包,会影响主包的其他页面。咨询uni-app相关开发人员,得到的回复是:确实不支持npm分包,处理起来会比较复杂,暂时也没有支持计划。为了满足业务需要,只能自力更生!

二、思路

将需要分包的npm包复制一份到分包目录,改成相对路径引入,这样打包之后,引入的npm包就会在分包里面。很明显,这种事情不能靠手工去处理。uni-app底层是通过webpack打包,可以通过开发插件解决问题。想到两种方案:

  1. 添加JSON配置文件,手动维护需要分包的npm包和引用文件路径的映射关系,分包页面通过相对路径引入npm包,在webpack解析模块前,比如 beforeRun阶段,根据配置,将npm包自动copy到引用文件所在的目录。

  2. DSL阶段:约定一种引入分包的import语法。AST阶段:添加Babel模块解析器解析分包语法,再将解析的npm包copy到引用文件所在目录,同时模块路径改成相对路径。

三、对比

  • 方案1,配置繁琐,而且引用和配置存在松散耦合关系,随着项目的不断迭代,容易导致JSON配置文件越来越臃肿和冗余,不好维护。
  • 方案2,语法层控制,不存在松散耦合,是否需要分包,切换语法就好,添加删除引入,不需要修改配置,不会出现历史包袱问题。

四、实现

本着约定大于配置的原则,最终我们采用方案2。

约定

分包import语法:

import module from "subpack:module"

模块解析器

基于babel-plugin-module-resolver模块解析插件进行扩展。

1.安装依赖

npm install babel-plugin-module-resolver --save-dev 

2.配置babel.config.js

1、通过cli构建的项目:在项目根目录下。
2、通过HBuilderX创建的项目:安装目录下HBuilderX/plugins/uniapp-cli/babel.config.js

const fs = require('fs-extra');  
const path = require("path");  
const plugins = [  
  ["module-resolver", {  
    "root": ["./"],  
    resolvePath(sourcePath, currentFile, opts) {  
      // 解析模块路径  
      const [scope,pakageName] = sourcePath.split(":");  
      // 判断是否为分包模块  
      if(scope == "subpack"){  
        // 如果是,将npm包copy到当前引入文件所在目录  
        fs.copySync(`./node_modules/${pakageName}/`, `${path.dirname(currentFile)}/${pakageName}`);  
        // 改成相对路径引用  
        sourcePath = `./${pakageName}`  

      }  
      return sourcePath;  
    }  

  }]  
]  
...

五、写在最后

通过上述方案,暂时可以满足我们目前的业务需求。还存在两个问题:

  1. 通过HBuilderX创建的项目,根目录配置 babel.config.js无效,需要去安装目录下手动配置,版本升级,会被覆盖。
  2. 约定分包引入的npm包,其引入的npm包,是否需要一起做分包处理,目前我们是没做的,还在权衡。

如果大家有其他思路,欢迎一起沟通讨论。最后感谢一下优秀的Dcloud团队

原文地址

0 关注 分享

要回复文章请先登录注册

梨涡浅笑

梨涡浅笑

非常感谢提供思路,现在我也遇到这样的问题了。但是目前项目里使用easycom进行自动引入,请问这个情况有类似的处理办法吗?
2022-04-24 11:03
9***@qq.com

9***@qq.com

方案可行,但是会污染源码(会将node_modules/package复制到源码的指定目录中)
2020-10-18 15:53