Vue-cli: 多页面开发时的性能问题

Created on 18 Apr 2019  ·  7Comments  ·  Source: vuejs/vue-cli

Version

3.6.3

Environment info

  System:
    OS: macOS 10.14.4
    CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
  Binaries:
    Node: 10.15.3 - ~/.nvm/versions/node/v10.15.3/bin/node
    Yarn: 1.15.2 - ~/.nvm/versions/node/v10.15.3/bin/yarn
    npm: 6.9.0 - ~/.nvm/versions/node/v10.15.3/bin/npm
  Browsers:
    Chrome: 73.0.3683.103
    Firefox: Not Found
    Safari: 12.1
  npmPackages:
    @vue/babel-helper-vue-jsx-merge-props:  1.0.0-beta.3 
    @vue/babel-plugin-transform-vue-jsx:  1.0.0-beta.3 
    @vue/babel-preset-app:  3.5.5 
    @vue/babel-preset-jsx:  1.0.0-beta.3 
    @vue/babel-sugar-functional-vue:  1.0.0-beta.3 
    @vue/babel-sugar-inject-h:  1.0.0-beta.3 
    @vue/babel-sugar-v-model:  1.0.0-beta.3 
    @vue/babel-sugar-v-on:  1.0.0-beta.3 
    @vue/cli-overlay:  3.5.1 
    @vue/cli-plugin-babel: ^3.2.0 => 3.5.5 
    @vue/cli-plugin-eslint: ^3.2.0 => 3.5.1 
    @vue/cli-service: ^3.2.0 => 3.5.3 
    @vue/cli-shared-utils:  3.5.1 
    @vue/component-compiler-utils:  2.6.0 
    @vue/eslint-config-standard: ^4.0.0 => 4.0.0 
    @vue/preload-webpack-plugin:  1.1.0 
    @vue/web-component-wrapper:  1.2.0 
    babel-helper-vue-jsx-merge-props:  2.0.3 
    eslint-plugin-vue: ^5.0.0-0 => 5.1.0 
    vue: ^2.5.17 => 2.5.21 
    vue-eslint-parser:  4.0.3 
    vue-hot-reload-api:  2.3.3 
    vue-loader:  15.7.0 
    vue-router: ^3.0.1 => 3.0.2 
    vue-style-loader:  4.1.2 
    vue-template-compiler: ^2.5.17 => 2.5.21 
    vue-template-es2015-compiler:  1.9.1 
    vuex: ^3.0.1 => 3.0.1 
  npmGlobalPackages:
    @vue/cli: 3.6.2

Steps to reproduce

把一个单页面项目修改为多页面,即复制入口文件和模板文件,然后在vue.config.js中的pages字段添加模板和入口。根据项目大小的不同,会存在添加7个页面后,修改文件重新编译的时候node内存溢出,即webpack进程运行的内存超过node默认分配的内存大小导致进程结束。在单页面的时候也存在性能问题,特别是修改入口文件的时候,编译速度非常慢。

<--- Last few GCs --->
io[86760:0x10284b000]   331522 ms: Mark-sweep 1403.5 (1429.1) -> 1403.4 (1430.6) MB, 392.4 / 0.0 ms  (  16.8 ms in 16 steps since start of marking,
 biggest step 7.8 ms, walltime since start of marking 413 ms) (average mu = 0.146, current mu = 0.014) allocat[86760:0x10284b000]   331955 ms: Mark
-sweep 1404.5 (1430.6) -> 1404.3 (1431.1) MB, 412.1 / 0.0 ms  (  17.9 ms in 17 steps since start of marking, biggest step 6.2 ms, walltime since st
art of marking 433 ms) (average mu = 0.083, current mu = 0.009) allocat

<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 0x28fbee7cfc7d]
    1: StubFrame [pc: 0x28fbee7d0fea]
    2: StubFrame [pc: 0x28fbee7c69e2]
Security context: 0x02cce911d9d1 <JSObject>

What is expected?

经过我这边测试,导致以上问题的主要原因是在开发的是后没有使用webpack的optimization.splitChunks配置来分包,每个入口都是完整编译所有文件,不能共享node_modules下的编译文件,所以导致内存不足。单页面的时候,修改入口文件也会重新编译node_modules下面的文件,所以速度较慢。

What is actually happening?

在开发模式下添加webpack的optimization.splitChunks配置

enhancement intend to implement cli-service serve

Most helpful comment

非常感谢如此详细的复现和分析。
这个确实可以优化。我看了一下提交记录,当初默认在 dev 环境下不开启 splitChunks 应该是从 webpack 2 时期迁移过来的旧的配置逻辑,并且以前 splitChunks 曾经引发过 hot module replacement 相关的 bug,所以出于维护方便的考虑就一直留着这个逻辑了。
现在看来相关 bug 应该都修复了,可以考虑默认开启。不过因为这样一来目录结构变动较大,应该不会在 v3 中加入,会放到 v4 中实现(首个 beta 版预计在未来两周内发布)。

All 7 comments

请给出重现仓库地址。

仓库地址:https://github.com/nashaofu/vue-cli-issue

Windows、Mac、Linux都可复现问题

复现步骤

  1. 克隆仓库,切换到master分支
  2. 运行npm run dev启动项目
  3. 打开活动监视器,找到 webpack 的 node 进程,记录下 node 进程内存使用值

    • 启动项目后
      1
  4. 找到src/main.js或者其他的文件,编辑然后保存,目的是触发 webpack 编译,记录下编译时长(friendly-errors-webpack-plugin 会打印出时间),如果连续快速保存文件多次,webpack 会一直编译,同时 node 进程内存会快速增长,就有可能内存不足导致进程结束

    • 修改两次文件后进程崩溃
      2
  5. 切换到splitChunks分支,并运行npm run dev启动项目

  6. 在活动监视器中可以看到启动项目后内存占用比前面要低很多,并且连续保存文件,内存上升幅度较小,并且编译时间低了很多

    • 启动项目后
      3

    • 多次修改文件后内存使用情况
      4

master 分支与 splitChunks 分支区别

splitChunks 分支添加了optimization.splitChunks配置

module.exports = {
  // ...其他的配置
  chainWebpack: config => {
    config.optimization.splitChunks({
      cacheGroups: {
        vendors: {
          name: 'chunk-vendors',
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          chunks: 'initial'
        },
        common: {
          name: 'chunk-common',
          minChunks: 2,
          priority: -20,
          chunks: 'initial',
          reuseExistingChunk: true
        }
      }
    })
  }
}

原因分析

使用了splitChunks,使得多个入口共用一份chunk-vendorschunk-common,这样就不会每个入口都编译一次node_modules下面的文件和其他公共的文件,并且由于提取了公共chunk,所以文件保存触发webpack重新编译时,只要提取的chunk没改变就不会重新编译提取出来的chunk,重新编译的速度也会明显上升

非常感谢如此详细的复现和分析。
这个确实可以优化。我看了一下提交记录,当初默认在 dev 环境下不开启 splitChunks 应该是从 webpack 2 时期迁移过来的旧的配置逻辑,并且以前 splitChunks 曾经引发过 hot module replacement 相关的 bug,所以出于维护方便的考虑就一直留着这个逻辑了。
现在看来相关 bug 应该都修复了,可以考虑默认开启。不过因为这样一来目录结构变动较大,应该不会在 v3 中加入,会放到 v4 中实现(首个 beta 版预计在未来两周内发布)。

速度很快,点赞👍

diy一个webpack4多页面遇到过类似的状况,后来发现是html-webpack-plugin的问题,替换成beta版本就明显速度提升了,也未从发现内存泄露

👍👍👍

@wzc0x0 能贴出具体的代码吗,现在升级了版本,但是在vue.config.js配置中出现了BASE_URL没找到的问题

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wahidrahim picture wahidrahim  ·  3Comments

joshuajohnson814 picture joshuajohnson814  ·  3Comments

BusyHe picture BusyHe  ·  3Comments

miyamoto-san picture miyamoto-san  ·  3Comments

Gonzalo2683 picture Gonzalo2683  ·  3Comments