使用vue-cli构建深度嵌套的html需要很长时间。

20
我发现vue-cli(2.9.6,但3.0.0 beta *也有同样的问题)在模板的HTML相对较深时构建过程需要很长时间。
例如,我刚刚向预先包含的App.vue添加了一些
,如下所示:
<template>
  <div id="app">
    <img src="./assets/logo.png">
    <div><div><div><div></div></div></div></div>
    <HelloWorld/>
  </div>
</template>

希望这不需要太长时间。

但是一旦它得到了这个:

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div>
    <HelloWorld/>
  </div>
</template>

那么,构建过程需要很长时间,我认为这种深度的嵌套并不罕见。

我应该如何解决这个问题?

编辑(细节)

看起来问题可能是与环境有关的,所以这里提供详细信息。

这个问题至少可以在以下环境中复制:

  • Mac mini(2014 年底款)上的 macOS High Sierra
  • Dell XPS 13 上的 Ubuntu 18.04

node 和 npm 的版本为:

node --version
# prints
v8.9.4
# and
npm version
# prints
{ npm: '6.1.0',
  ares: '1.10.1-DEV',
  cldr: '31.0.1',
  http_parser: '2.7.0',
  icu: '59.1',
  modules: '57',
  nghttp2: '1.25.0',
  node: '8.9.4',
  openssl: '1.0.2n',
  tz: '2017b',
  unicode: '9.0',
  uv: '1.15.0',
  v8: '6.1.534.50',
  zlib: '1.2.11' }

我用这些东西在我的Mac上重新尝试了以下操作:

npm uninstall -g vue-cli
npm install -g vue-cli
vue init webpack divnest
# then some Enter keys - everything is default
cd divnest

接下来,打开 App.vue 文件并添加多个 div:

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div>
    <router-view/>
  </div>
</template>

由于我在这里使用了默认设置,因此包括<router-view/>,与原始帖子不同,但不应该是问题所在。

最后,

npm run dev

这个过程需要很长时间,特别是在这一点上停止:

 13% building modules 28/31 modules 3 active ...myname/Documents/divnest/src/App.vue

在这种情况下
npm run build

在这一点上,该进程停止:

> divnest@1.0.0 build /Users/myname/Documents/divnest
> node build/build.js

Hash: 483ebabc54d5aed79fd7
Version: webpack 3.12.0
Time: 13742ms
                                                  Asset       Size  Chunks             Chunk Names
               static/js/vendor.7fed9fa7b7ba482410b7.js     112 kB       0  [emitted]  vendor
                  static/js/app.f1ebca7a6e0ec0b7ebdf.js      12 kB       1  [emitted]  app
             static/js/manifest.2ae2e69a05c33dfc65f8.js  857 bytes       2  [emitted]  manifest
    static/css/app.30790115300ab27614ce176899523b62.css  432 bytes       1  [emitted]  app
static/css/app.30790115300ab27614ce176899523b62.css.map  828 bytes          [emitted]  
           static/js/vendor.7fed9fa7b7ba482410b7.js.map     553 kB       0  [emitted]  vendor
              static/js/app.f1ebca7a6e0ec0b7ebdf.js.map    23.3 kB       1  [emitted]  app
         static/js/manifest.2ae2e69a05c33dfc65f8.js.map    4.97 kB       2  [emitted]  manifest
                                             index.html  509 bytes          [emitted]  

  Build complete.

  Tip: built files are meant to be served over an HTTP server.
  Opening index.html over file:// won't work.

 94% asset optimization 

如果我不干预,它需要...1155409毫秒!!!

 DONE  Compiled successfully in 1155409ms                                                        13:35:34

 I  Your application is running here: http://localhost:8080

更多编辑

正如@tony19所指出的那样,prettier很可能是罪魁祸首。按照建议,我在Ubuntu 18.04上尝试了一些模式(不是Mac,因为现在没有Mac,抱歉),我的结果是:

  • vue-cli 2.9.6 + npm run dev - 卡住了
  • vue-cli 2.9.6 + npm run build - 6秒钟(这太令人困惑了。上面的100万秒是什么意思?也许重新安装vue-cli有所改变?)
  • vue-cli 3.0.0-beta16 + vue serve - 卡住了(与@tony19的报告相反)
  • vue-cli 3.0.0-beta16 + vue build - 5秒钟

更多编辑

因此,这显然是由prettier引起的。 https://github.com/prettier/prettier/issues/1250 是最初解决这个问题的问题,并且开发团队认为https://github.com/prettier/prettier/pull/2259修复了它,但事实上它无法处理我的情况,正如@tony19在https://github.com/prettier/prettier/issues/4672上所展示的那样。哦好吧。

"解决方案"

最终我做了这个-按照@tony19的报告,更改/node_modules/vue-loader/lib/template-compiler/index.js的第78:81行。

if (!isProduction) {
  code = prettier.format(code, { semi: false })
}

为了

// if (!isProduction) {
//   code = prettier.format(code, { semi: false })
// }

问题已经解决。感谢前端,谢谢您。

4个回答

25

我可以按照你描述的方式重现性能问题 (macOS High Sierra 10.13.4,Node 8.9.4 和 9.11.1)。这个问题也会在一个新创建的 vue-cli 3.x 项目中出现。

hang 实际上发生在 prettier 中,由 vue-loader 的模板编译器 调用。嵌套的 <div> 会被 vue-loader 转换为 JavaScript,并成为以下代码片段:

var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{attrs:{"id":"app"}},[_c('img',{attrs:{"src":require("./assets/logo.png")}}),_vm._v(" "),_c('router-view'),_vm._v(" "),_vm._m(0)],1)}
var staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div',[_c('div')])])])])])])])])])])])])])])])])])])])])])])])])}]

vue-loader将这个长字符串传递给prettier处理,需要大约159秒的时间。错误的原因是创建

的深度嵌套函数调用。我已经在prettier中报告了这个错误(Issue 4672)。

与此同时,我建议重新设计HTML以避免深层嵌套。如果你必须坚持使用旧模板,你可以通过在生产模式下构建来解决这个问题,因为vue-loader会跳过prettier的生产构建。

NODE_ENV=production npm run dev

更新 vue-loader v15.5.0 添加了 prettify 选项,允许禁用 prettier。(更新到最新版本的 @vue/cli 确保你的 vue-loader 使用了这个新选项)。你可以按以下方式使用此选项:

  1. 在项目根目录下添加vue.config.js文件(如果尚不存在)。

  2. 编辑此文件,包含以下内容:

    module.exports = {
      chainWebpack: config => {
        config.module
          .rule('vue')
          .use('vue-loader')
            .loader('vue-loader')
            .tap(options => {
              options.prettify = false
              return options
            })
      }
    }
    

2

更新 2019

最近,vue-loader 在其选项中添加了一个标志,以便在开发过程中禁用 prettier

只需将 prettify: false 添加到您的 vue-loader 选项中即可。

https://vue-loader.vuejs.org/options.html#prettify

注意:请确保您使用的是最新的 vue-loader 版本。

1

我曾经遇到过类似问题,使用的是vue-cli 3.1.1(TypeScript + SCSS)和Bootstrap(默认需要一些嵌套)。以下是示例结构:

<template>
    <div class="container">
        <div class="row">
            <div class="col-12">
                <div class="card-deck">
                    <div class="card">
                        <div class="card-body">
                            <div class="accordion">
                                <div class="card">
                                    <div class="card-header">
                                        ...
                                    </div>
                                    <div class="collapse">
                                        <div class="card-body">
                                            <div class="row">
                                                <div class="col-12 form-group">
                                                    <label>...</label>
                                                    <div class="dropdown">
                                                        <button class="custom-select" type="button" data-toggle="dropdown">{{someValue}}</button>
                                                        <div class="dropdown-menu">
                                                            <a class="dropdown-item" href="#" :data-key="somekey1" @click="onClickMethod">value1</a>
                                                            <a class="dropdown-item" href="#" :data-key="somekey2" @click="onClickMethod">value2</a>
                                                            ...

需要大约12秒时间编译超过400行的代码(包括模板、TypeScript和SCSS)。在移除之后:

:data-key="somekey1" @click="onClickMethod"
:data-key="somekey2" @click="onClickMethod"

这段代码需要约5-6秒钟来编译。将代码移动到自定义组件中后(以及将一些TypeScript代码从Vue组件移至Helper.ts文件):

<template>
    <div class="container">
        <div class="row">
            <div class="col-12">
                <div class="card-deck">
                    <div class="card">
                        <div class="card-body">
                            <div class="accordion">
                                <div class="card">
                                    <div class="card-header">
                                        ...
                                    </div>
                                    <div class="collapse">
                                        <div class="card-body">
                                            <SubComponent/>

编译需要约700毫秒(一个主组件和两个附加子组件,每个文件的代码行数不到100行+ Helper.ts恰好有97行代码)。

因此,如果您遭受npm run serve性能差的问题,请首先尝试子组件。我在调用npm run build时没有注意到编译时间的显着差异,因此我假设(可能不正确)这个问题也是由启用了serve但未启用build的代码美化程序引起的(在我的情况下,TSLint不会在保存操作时被调用,因此不会影响npm run serve)。


-1

我对你的25个嵌套的<div>没有任何特别的问题:(下面是使用Vue运行时编译器的示例,因此您可以直接在浏览器中轻松测试它)

new Vue({
  el: '#app',
  template: '#app-template',
});
#app div {
  border: 1px solid grey;
  padding: 1px;
}
<script src="https://unpkg.com/vue@2"></script>

<div id="app">
</div>

<template id="app-template">
<div id="app">
  <div>
    <div>
      <div>
        <div>
          <div>
            <div>
              <div>
                <div>
                  <div>
                    <div>
                      <div>
                        <div>
                          <div>
                            <div>
                              <div>
                                <div>
                                  <div>
                                    <div>
                                      <div>
                                        <div>
                                          <div>
                                            <div>
                                              <div>
                                                <div>
                                                  <div>25 nested <code>&lt;div&gt;</code>'s</div>
                                                </div>
                                              </div>
                                            </div>
                                          </div>
                                        </div>
                                      </div>
                                    </div>
                                  </div>
                                </div>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  </div>
</template>

这是一个使用Vue CLI项目在CodeSandbox上的演示,可能更接近您的示例:https://codesandbox.io/s/v3knpl447l (即它预编译模板,因此构建过程实际上发生在CodeSandbox服务器上)

我已经检查了沙盒,是的,它可以工作。但是一旦我将其复制粘贴到我的本地工作空间,它就无法工作... - akai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接