Meituan-Dianping / mpvue

基于 Vue.js 的小程序开发框架,从底层支持 Vue.js 语法和构建工具体系。
http://mpvue.com
MIT License
20.42k stars 2.07k forks source link

MpVue打包vendor.js过大问题 #1757

Open Jane-blog opened 4 years ago

Jane-blog commented 4 years ago

npm run dev 开发时构建在已经精简代码and图片、分包处理后、无丑化代码打包后vendor.js过大,尝试给vendor.js做了分包处理,这里参考了MpVue打包vendor过大问题解决办法,但是没有成功,请问大家还有好的建议吗?

bojueWjt commented 4 years ago

npm run dev 开发时构建在已经精简代码and图片、分包处理后、无丑化代码打包后vendor.js过大,尝试给vendor.js做了分包处理,这里参考了MpVue打包vendor过大问题解决办法,但是没有成功,请问大家还有好的建议吗?

前阵子做过类似的,希望对你有帮助 http://ninico.top/2019/09/10/base-on-mpvue-minipro-package-size-opti.html

Jane-blog commented 4 years ago

npm run dev 开发时构建在已经精简代码and图片、分包处理后、无丑化代码打包后vendor.js过大,尝试给vendor.js做了分包处理,这里参考了MpVue打包vendor过大问题解决办法,但是没有成功,请问大家还有好的建议吗?

前阵子做过类似的,希望对你有帮助 http://ninico.top/2019/09/10/base-on-mpvue-minipro-package-size-opti.html

我这里遇到一些疑问需要您的帮助need && process.evn.common_chunk_report 其中 common_chunk_report 无法再项目中找到,请问这个是哪里的设置?

shrekuu commented 4 years ago

我有一个, 我推荐使用第三方扩展时也可以试试 umd 包

比如, 若要使用 lodash, 那试试官方的 lodash-es ES 模块版,

若要使用 rxjs, 推荐使用 umd 包, rxjs, 或直接用 rxjs6-wxRxWX

若要使用 moment, 推荐一定要去掉不要的语言包, 如下图:

image

然后在需要某语言时这样引入:

image

dayjs 就算了, 你写着写着有些功能就实在没有只能换回 moment 了.

或者, 也可以考虑放弃使用 lodash. 直接手动处理或许也不会太麻烦.

Jane-blog commented 4 years ago

我有一个, 我推荐使用第三方扩展时也可以试试 umd 包

比如, 若要使用 lodash, 那试试官方的 lodash-es ES 模块版,

若要使用 rxjs, 推荐使用 umd 包, rxjs, 或直接用 rxjs6-wxRxWX

若要使用 moment, 推荐一定要去掉不要的语言包, 如下图:

image

然后在需要某语言时这样引入:

image

dayjs 就算了, 你写着写着有些功能就实在没有只能换回 moment 了.

或者, 也可以考虑放弃使用 lodash. 直接手动处理或许也不会太麻烦.

你这发表错地方了吗

shrekuu commented 4 years ago

@CitrusHan 木有啊,桑心,vendor 过大大几率情况是第三方依赖过多或引用方式不合适,举了几个例子推荐了一下下引用依赖要注意的地方,不然开发过程 vendor 过大无法在手机微信里调试。真项目本身代码有那么大的话估计是项目需求问题,比如想在小程序里做太多事情,太复杂的需求,或公共组件过多。

要不你发下你们项目依赖列表我们来看看?比如 package.json 文件里的。

Jane-blog commented 4 years ago

加wx吧,你微信多少我加你

Jane-blog commented 4 years ago

我新建了一个干净的项目文件,对比了一下两个项目的依赖库除了dependencies的比新建的多几个,devDependencies中的基本差不多,不知道这会不是影响我vendor过大的原因? "dependencies": { "crypto": "^1.0.1", "md5": "^2.2.1", "mpvue": "^2.0.0", "mpvue-wxparse": "^0.6.5", "vuex": "^3.0.1", "wxbarcode": "^1.0.2" },

shrekuu commented 4 years ago

@CitrusHan 我试了你的这几个额外的包, vendor 并没有超过 300k, 可能不是第三方依赖的问题

iamkun commented 4 years ago

@shrekuu dayjs 还缺啥你需要的功能呢?

shrekuu commented 4 years ago

@iamkun 方便的时间段处理

iamkun commented 4 years ago

@shrekuu 能具体一点吗 或者 demo code 之类的

hereisfun commented 4 years ago

处理思路与@bojueWjt 类似,首先需要用BundleAnalyzerPlugin分析vendor体积的组成。如果是node_modules体积过大,可以参考bojueWjt的帖子进行优化。(mpvue 初始化的项目已集成BundleAnalyzerPlugin, npm run build的时候加上 --report 参数即可开启

我们遇到的情况是分包的公共代码被意外打包到主包里的vendor.js里了,改成分包公共代码仅提取到分包内解决。

首先vendor.js代码来自CommonsChunkPlugin, mpvue默认的配置如下:

    new webpack.optimize.CommonsChunkPlugin({
      name: 'common/vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf('node_modules') >= 0
        ) || count > 1
      }
    }),

可以看到只要是node_moduels里的js,或者引用次数>1的文件都会被提取进common/vendor。

查阅CommonsChunkPlugin文档, 发现有一个chunks参数,可以指定从哪些chunks提取公共代码,而mpvue里其实每个页面都是一个chunks,那么只要按照app.json里的分包规则加入多个CommonsChunkPlugin即可

参考代码:

const appJson = require('../src/app.json')
let subpackages = {}
if (appJson.subpackages) {
  appJson.subpackages.forEach(package => {
    subpackages[package.root] = []
    package.pages.forEach(subPage => subpackages[package.root].push(path.join(package.root, subPage)))
  })
}

const subPackageCommonChunks = Object.keys(subpackages).map(sub =>
  new webpack.optimize.CommonsChunkPlugin({
    name: path.join(sub, 'common'),
    chunks: subpackages[sub],
    minChunks: 2,
  })
)

最后加在原本的commonsChunksPlugin前即可:

var webpackConfig = merge(baseWebpackConfig, {
    // 省略中间代码
    ...subPackageCommonChunks,
    new webpack.optimize.CommonsChunkPlugin({
      name: 'common/vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf('node_modules') >= 0
        ) || count > 1
      }
    }),
})
shrekuu commented 4 years ago

@shrekuu 能具体一点吗 或者 demo code 之类的

好吧, 我举个栗子

const fromDate = moment('2019-01-01 00:00:00')
const toDate = moment('2019-01-12 00:12:00')

// 时间段 10 天 21 小时 12 分钟
const duration = moment.duration(toDate.diff(fromDate))

// 时间段的天部分
const dayPart = duration.days() // 10

小时部分
const hourPart = duration.hours()  // 21

// 分钟部分
const minutePart = duration.minutes() // 12

// 共多少小时
const asHours = duration.duration.asHours() // 261.2

以上处理在 dayjs 里就木有, 参考这里 https://github.com/iamkun/dayjs/issues/122 relativeTime 也实现不了上面的操作

iamkun commented 4 years ago

@shrekuu https://github.com/iamkun/dayjs/issues/564 谢谢 请关注这里的进度 很快就会有了 😁

mack-wang commented 3 years ago

npm run dev 开发时构建在已经精简代码and图片、分包处理后、无丑化代码打包后vendor.js过大,尝试给vendor.js做了分包处理,这里参考了MpVue打包vendor过大问题解决办法,但是没有成功,请问大家还有好的建议吗?

前阵子做过类似的,希望对你有帮助 http://ninico.top/2019/09/10/base-on-mpvue-minipro-package-size-opti.html

这个有效,推荐大家

doglex commented 10 months ago

处理思路与@bojueWjt 类似,首先需要用BundleAnalyzerPlugin分析vendor体积的组成。如果是node_modules体积过大,可以参考bojueWjt的帖子进行优化。(mpvue 初始化的项目已集成BundleAnalyzerPlugin, npm run build的时候加上 --report 参数即可开启

我们遇到的情况是分包的公共代码被意外打包到主包里的vendor.js里了,改成分包公共代码仅提取到分包内解决。

首先vendor.js代码来自CommonsChunkPlugin, mpvue默认的配置如下:

    new webpack.optimize.CommonsChunkPlugin({
      name: 'common/vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf('node_modules') >= 0
        ) || count > 1
      }
    }),

可以看到只要是node_moduels里的js,或者引用次数>1的文件都会被提取进common/vendor。

查阅CommonsChunkPlugin文档, 发现有一个chunks参数,可以指定从哪些chunks提取公共代码,而mpvue里其实每个页面都是一个chunks,那么只要按照app.json里的分包规则加入多个CommonsChunkPlugin即可

参考代码:

const appJson = require('../src/app.json')
let subpackages = {}
if (appJson.subpackages) {
  appJson.subpackages.forEach(package => {
    subpackages[package.root] = []
    package.pages.forEach(subPage => subpackages[package.root].push(path.join(package.root, subPage)))
  })
}

const subPackageCommonChunks = Object.keys(subpackages).map(sub =>
  new webpack.optimize.CommonsChunkPlugin({
    name: path.join(sub, 'common'),
    chunks: subpackages[sub],
    minChunks: 2,
  })
)

最后加在原本的commonsChunksPlugin前即可:

var webpackConfig = merge(baseWebpackConfig, {
    // 省略中间代码
    ...subPackageCommonChunks,
    new webpack.optimize.CommonsChunkPlugin({
      name: 'common/vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf('node_modules') >= 0
        ) || count > 1
      }
    }),
})

是有效的,在windows下需要把 package.pages.forEach(subPage => subpackages[package.root].push(path.join(package.root, subPage))) 这行替换为 package.pages.forEach(subPage => subpackages[package.root].push(package.root +'/'+ subPage)) 因为windows的path.join的分隔符是 // 而不是 \

ANT-CYJ commented 10 months ago

放心吧,我已经收到啦。