Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(mini-runner/mini-split-chunks): (主包大小最优方案)添加小程序提取公共模块插件,主包没有引用的,且分包内引用的mod… #8135

Merged
merged 35 commits into from
May 21, 2021

Conversation

huangcj99
Copy link
Contributor

@huangcj99 huangcj99 commented Nov 26, 2020

…ule提取到分包下vendors,跨分包引用的module提取到分包下,达到主包体积最优

这个 PR 做了什么? (简要描述所做更改)

一、插件公共模块提取逻辑
添加miniSplitChunksPlugin,打包时分析module与chunk的依赖关系,筛选出主包没有引用的module提取到分包内,达到主包体积最优的目的,下面是提取的两种类型的分包公共模块(该方案已支持css等文件)

1、分包根目录/sub-vendors
如果该module只被单个分包内的多个page引用,则提取到该分包根目录的sub-vendors文件中。

(之前使用vendors作为filename,会导致common.wxss会@import分包内的vendors.wxss文件,导致报错,所以改成sub-vendors)

2、分包根目录/sub-common/*
如果该module被多个分包内的page引用,则先提取到outputRoot的sub-common文件夹下,输出文件后根据之前记录的依赖关系,将sub-common源目录下的公共模块复制到对应的分包下的sub-common文件夹,并给分包内的page加上require语句,页面的wxss通过@import语句引入,复制完成后删除sub-common源目录

二、如何使用?

mini配置添加optimizeMainPackage配置,将enable属性设置为true则使用该公共模块提取插件(默认为false不开启该功能)。如果有module不想走分包提取的逻辑,可以添加exclude属性,支持字符串和函数的方式,这样匹配到的module会走原来提取到主包的逻辑

这个 PR 是什么类型? (至少选择一个)

  • 错误修复(Bugfix) issue id #
  • 新功能(Feature)
  • 代码重构(Refactor)
  • TypeScript 类型定义修改(Typings)
  • 文档修改(Docs)
  • 代码风格更新(Code style update)
  • 其他,请描述(Other, please describe):

这个 PR 满足以下需求:

  • 提交到 master 分支
  • Commit 信息遵循 Angular Style Commit Message Conventions
  • 所有测试用例已经通过
  • 代码遵循相关包中的 .eslintrc, .tslintrc, .stylelintrc 所规定的规范
  • 在本地测试可用,不会影响到其它功能

这个 PR 涉及以下平台:

  • 微信小程序
  • 支付宝小程序
  • 百度小程序
  • 头条小程序
  • QQ 轻应用
  • 快应用平台(QuickApp)
  • Web 平台(H5)
  • 移动端(React-Native)

其它需要 Reviewer 或社区知晓的内容:

@luckyadam
Copy link
Member

非常棒,我们研究下

…ule提取到分包下vendors,跨分包引用的module提取到分包下,达到主包体积最优
@wuchangming
Copy link
Contributor

@luckyadam ,这个 PR 有计划合入主分支不?

@Chen-jj Chen-jj added the V-3 Version - 3.x label Jan 28, 2021
@huangcj99
Copy link
Contributor Author

@heymie 能不能把这两行清除目录的代码去掉试试看,我这边试了下,有点难复现,感觉dev环境不做移除看起来也没什么问题

@heymie
Copy link

heymie commented Jun 15, 2021

@huangcj99 移除了不会出现这个报错,但是ide打包失败,提示主包size过大。

@aohanyao
Copy link

@huangcj99
还有一个问题就是在模拟调试的时候sub-common下的文件是累积的?
每修改一次,产生的文件就加一倍,导致要用真机调试的话每次都得重新编译。

@huangcj99
Copy link
Contributor Author

huangcj99 commented Jun 17, 2021 via email

@huangcj99
Copy link
Contributor Author

@huangcj99 移除了不会出现这个报错,但是ide打包失败,提示主包size过大。

那应该是移除文件后,ide有缓存读取不到原来的文件造成这个报错了,但是不清除又会积累,尴尬

@heymie
Copy link

heymie commented Jun 17, 2021

能否和微信那边沟通一起看看

@heymie
Copy link

heymie commented Jun 21, 2021

@huangcj99 最新taro版本,支付宝编译错误
image

@zeybar
Copy link

zeybar commented Jul 2, 2021

@huangcj99 这个功能能作为一个单独插件兼容2.x版本嘛

@linguoqiang001
Copy link

linguoqiang001 commented Jul 16, 2021

@huangcj99 移除了不会出现这个报错,但是ide打包失败,提示主包size过大。

那应该是移除文件后,ide有缓存读取不到原来的文件造成这个报错了,但是不清除又会积累,尴尬

可以把暂存的sub common提取到外层的目录,这样子ide就不会检测了,亲测可行。还有个问题,子包的sub-common是累积的,建议改成每次保存重新编译,清空一次子包的sub-common

@linguoqiang001
Copy link

linguoqiang001 commented Jul 16, 2021

@huangcj99 最新taro版本,支付宝编译错误
image

image
image
这个问题应该是在只有一个主包,没有分包的时候会报这个bug。因为作者在constructor时把options设为null(这里没理解为啥要设为null),只有一个主包的情况下导致导致分包chunks为0,走到了红框的位置,导致走不到下面的this.options重新赋值,导致this.options没有getCacheGroup方法。解决方法可以先加一个分包页面。

@SilentFlute
Copy link

@linguoqiang001 你好, 我这边用taro开发小程序真机调试包太大, 无法真机调试, 于是尝试优化, 期间也遇到了这个报错的问题, 后来发现最占空间的是图片, 目前将图片改小了就行了, 但始终是有些不妥, 毕竟牺牲了图片的清晰度, 以下是我的操作:
taro版本: 3.2.14
os: win10
配置文件设置如下:
config/dev.js:

  mini: {
    optimizeMainPackage: {
      enable: true
    }
  },

然后参照文档中的设置来修改config/index.js:
对-taro-项目的部分页面分包
接着yarn dev:weapp
但依旧报错...
文档里的意思我理解就是src/subPackages/foo.js src/subPackages/bar.js都引用了相同的依赖, 然后这个配置把这些依赖提成公共的subpackages/common, 然后再给src/subPackages/foo.js src/subPackages/bar.js使用, 但我想了一下, 我这项目里没有这样的情况, 我这项目的页面比如有5个, 是src/pages/a.jssrc/pages/e.js这个5个页面, 没有类似src/pages/a1.js src/pages/a2.js这样的情况, 所以才配置之后依旧报错吧
这样的话该如何处理呢?求指点

@linguoqiang001
Copy link

@linguoqiang001 你好, 我这边用taro开发小程序真机调试包太大, 无法真机调试, 于是尝试优化, 期间也遇到了这个报错的问题, 后来发现最占空间的是图片, 目前将图片改小了就行了, 但始终是有些不妥, 毕竟牺牲了图片的清晰度, 以下是我的操作:
taro版本: 3.2.14
os: win10
配置文件设置如下:
config/dev.js:

  mini: {
    optimizeMainPackage: {
      enable: true
    }
  },

然后参照文档中的设置来修改config/index.js:
对-taro-项目的部分页面分包
接着yarn dev:weapp
但依旧报错...
文档里的意思我理解就是src/subPackages/foo.js src/subPackages/bar.js都引用了相同的依赖, 然后这个配置把这些依赖提成公共的subpackages/common, 然后再给src/subPackages/foo.js src/subPackages/bar.js使用, 但我想了一下, 我这项目里没有这样的情况, 我这项目的页面比如有5个, 是src/pages/a.jssrc/pages/e.js这个5个页面, 没有类似src/pages/a1.js src/pages/a2.js这样的情况, 所以才配置之后依旧报错吧
这样的话该如何处理呢?求指点

报啥错,贴一下

@SilentFlute
Copy link

@linguoqiang001 刚回复你的时候打字没打全, 还是报同样的错:

Cannot read property 'getCacheGroups' of null

@linguoqiang001
Copy link

@linguoqiang001 刚回复你的时候打字没打全, 还是报同样的错:

Cannot read property 'getCacheGroups' of null

如果只有主包页面是会报这个错的,你可以添加一个无用的分包页面。
可以贴下app.config.ts文件看下。

@SilentFlute
Copy link

@linguoqiang001
config/dev.js:

module.exports = {
  env: {
    NODE_ENV: '"development"'
  },
  defineConstants: {
  },
  mini: {
    optimizeMainPackage: {
      enable: true
    }
  },
  h5: {}
}

src/app.config.js:

export default {
  pages: [
    'pages/newIndex/index',
    'pages/index/index',
    'pages/user/index',
    'pages/xuanjvren/index',
    'pages/toupiaolist/index',
    'pages/xuanjuother/index',
    'pages/articleInfo/index'

  ],
  window: {
    backgroundTextStyle: 'light',
    navigationBarBackgroundColor: '#fff',
    navigationBarTitleText: 'WeChat',
    navigationBarTextStyle: 'black'
  }
}

config/index.js:

import { resolve } from 'path'

const config = {
  projectName: 'myAppRedux',
  date: '2021-5-24',
  designWidth: 750,
  deviceRatio: {
    640: 2.34 / 2,
    750: 1,
    828: 1.81 / 2
  },
  sourceRoot: 'src',
  outputRoot: 'dist',
  plugins: [],
  defineConstants: {
  },
  alias: {
    '@': resolve(__dirname, '..', 'src')
  },
  copy: {
    patterns: [
    ],
    options: {
    }
  },
  framework: 'react',
  mini: {
    postcss: {
      pxtransform: {
        enable: true,
        config: {

        }
      },
      url: {
        enable: true,
        config: {
          limit: 1024 // 设定转换尺寸上限
        }
      },
      cssModules: {
        enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
        config: {
          namingPattern: 'module', // 转换模式,取值为 global/module
          generateScopedName: '[name]__[local]___[hash:base64:5]'
        }
      }
    },
    addChunkPages (pages) {
      pages.set('pages/user/index', ['subpackages/common']),
      pages.set('pages/xuanjvren/index', ['subpackages/common']),
      pages.set('pages/toupiaolist/index', ['subpackages/common']),
      pages.set('pages/xuanjuother/index', ['subpackages/common'])
    },
    webpackChain (chain) {
      chain.merge({
        optimization: {
          splitChunks: {
            cacheGroups: {
              subpackagesCommon: {
                name: 'subpackages/common',
                minChunks: 2,
                test: (module, chunks) => {
                  const isNoOnlySubpackRequired = chunks.find(chunk => !(/\bxuanjvren\b/.test(chunk.name)))
                  return !isNoOnlySubpackRequired
                },
                priority: 200
              }
            }
          }
        }
      })
    }
  },
  h5: {
    publicPath: '/',
    staticDirectory: 'static',
    postcss: {
      autoprefixer: {
        enable: true,
        config: {
        }
      },
      cssModules: {
        enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
        config: {
          namingPattern: 'module', // 转换模式,取值为 global/module
          generateScopedName: '[name]__[local]___[hash:base64:5]'
        }
      }
    }
  }
}

module.exports = function (merge) {
  if (process.env.NODE_ENV === 'development') {
    return merge({}, config, require('./dev'))
  }
  return merge({}, config, require('./prod'))
}

addChunkPageswebpackChain按照官网来配置的, 只是随便写了写, 为的就是让subChunks.length === 0不过看起来似乎是失败了(捂脸)

@SilentFlute
Copy link

为的是让subChunks.length !== 0, 打错了...

@linguoqiang001
Copy link

@SilentFlute 你这种就是只有主包,你加个分包试下。还有你都没有分包去配splitChunks好像没啥用吧,更何况你都用了optimizeMainPackage,为啥还去配置splitChunks呢。你说你图片太大了,建议尽量使用网络图片。

@SilentFlute
Copy link

@linguoqiang001 我刚开始用taro不久...
optimizeMainPackagesplitChunks不能一起用吗? 我一开始是只用了optimizeMainPackage, 但是就报错了:

Cannot read property 'getCacheGroups' of null

后来有人cue我你的这个评论, 然后我才尝试的splitChunks, 是姿势不对吗?
以及怎么加分包, 是按照文档分包里的subpackages来吗?那我这应该怎么配置呢?这样吗:

  "subpackages": [
    {
      "root": "pages",
      "pages": [
        "subpackages/common"
      ]
    }
  ]

还是这个

      "pages": [
        "subpackages/common"
      ]

需要一个真实的页面?
以及这个项目是zf项目, 我们来开发, 图片似乎不能使用cdn, 不然就直接用链接了...

@SilentFlute
Copy link

我试了下, 发现还是玩不转...
求指点

@SilentFlute
Copy link

感谢@linguoqiang001 提供的帮助, 问题解决了, 这里记录一下: NervJS/taro-docs#102

@longge0516
Copy link
Contributor

hello,遇到了一种不兼容的情况,想可以兼容下,谢谢!issues:9862

@huangcj99
Copy link
Contributor Author

@huangcj99 移除了不会出现这个报错,但是ide打包失败,提示主包size过大。

那应该是移除文件后,ide有缓存读取不到原来的文件造成这个报错了,但是不清除又会积累,尴尬

可以把暂存的sub common提取到外层的目录,这样子ide就不会检测了,亲测可行。还有个问题,子包的sub-common是累积的,建议改成每次保存重新编译,清空一次子包的sub-common

之前其实有考虑过放外层,但是怕会覆盖到别人项目的文件,后面想想感觉给个暂存路径配置项会不会好一点,让用的人自己填一个dist外的路径

@huangcj99
Copy link
Contributor Author

@huangcj99 最新taro版本,支付宝编译错误
image

这个问题应该是在只有一个主包,没有分包的时候会报这个bug。因为作者在constructor时把options设为null(这里没理解为啥要设为null),只有一个主包的情况下导致导致分包chunks为0,走到了红框的位置,导致走不到下面的this.options重新赋值,导致this.options没有getCacheGroup方法。解决方法可以先加一个分包页面。

刚提了pr解决了,#9881,之前没考虑到没分包配置的情况,确实不太友好

@huangcj99
Copy link
Contributor Author

开发者工具报的'no such of file or dir'这个错误 #9967 这个版本修复了,不再输出暂存的文件

@Chen-jj Chen-jj added the N-doc_needed 需要被在文档中进行记录 label Sep 7, 2021
@Seven777Z
Copy link

还是有这个问题 全量页面反复编译 总包还是会超20M sub-common里的文件不断的增加且无法覆盖

@aohanyao
Copy link

在这里找到关键代码注释掉 就行了
node_modules/@tarojs/mini-runner/dist/plugins/MiniSplitChunksPlugin.js

@aohanyao
Copy link

image

image

@jeasonnow
Copy link

jeasonnow commented Mar 9, 2022

@huangcj99 移除了不会出现这个报错,但是ide打包失败,提示主包size过大。

那应该是移除文件后,ide有缓存读取不到原来的文件造成这个报错了,但是不清除又会积累,尴尬

可以把暂存的sub common提取到外层的目录,这样子ide就不会检测了,亲测可行。还有个问题,子包的sub-common是累积的,建议改成每次保存重新编译,清空一次子包的sub-common

之前其实有考虑过放外层,但是怕会覆盖到别人项目的文件,后面想想感觉给个暂存路径配置项会不会好一点,让用的人自己填一个dist外的路径

@huangcj99 如果非要固定的话,是不是用 os.tmpdir() 获取系统临时目录然后固定一下会更好,也不会存在放到项目目录下导致的缓存问题,而且目前来说 this.isDevMode 导致的 depName 永远不同从而引发的子包 sub-common 大小无限累积问题还挺严重的,希望尽快优化一下

@panchanggang
Copy link

panchanggang commented Jul 10, 2022

image
@huangcj99 您好,我配置后,运行出现了这个问题,应该怎么解决呢?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
N-doc_needed 需要被在文档中进行记录 V-3 Version - 3.x
Projects
None yet
Development

Successfully merging this pull request may close these issues.