用vue-cli构建深层嵌套的html需要永远

我发现,一旦模板的html变得相对较深,vue-cli(2.9.6,但3.0.0 beta *也有同样的问题)的构建过程将永远花费。

举例来说,我只是增加了一些divs到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上的macOS High Sierra(2014年末)
  • Dell XPS 13上的Ubuntu 18.04

节点和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>

(Since I used the default settings here, <router-view/> is included unlike the original post, but should not be the problem.)

And finally,

npm run dev

which takes forever - specifically, the process stops at this point:

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

In the case of

npm run build

, the process stops at this point:

> 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 

and if I let it go, it takes... 1155409ms!!!!

 DONE  Compiled successfully in 1155409ms                                                        13:35:34

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

MORE EDIT

As @tony19 pointed out, prettier is the likely suspect. Following the advice, I've tried some patterns with Ubuntu 18.04 (not Mac because Mac isn't here right now, sorry) and my results are:

  • vue-cli 2.9.6 + npm run dev - hang
  • vue-cli 2.9.6 + npm run build - 6 secs (This is so confusing. What was the 1 million seconds above!? Maybe reinstalling vue-cli owes the change?)
  • vue-cli 3.0.0-beta16 + vue serve - hang (as opposed to @tony19's report)
  • vue-cli 3.0.0-beta16 + vue build - 5 secs

EVEN MORE EDIT

So, it seems that this is definitely caused by prettier. https://github.com/prettier/prettier/issues/1250 is the original issue that addressed this problem and the dev team thought that https://github.com/prettier/prettier/pull/2259 fixed it, but the reality is that it couldn't handle my case, as @tony19 shows it on https://github.com/prettier/prettier/issues/4672 . Oh well.

"SOLUTION"

I ended up doing this - following @tony19's report, changing /node_modules/vue-loader/lib/template-compiler/index.js lines 78:81

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

to

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

thus the problem is solved. Thank you frontend, thank you.

2020/03/13 17:12:08

更新2019

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

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

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

注意:请确保您拥有最新的vue-loader版本

ㄏ囧囧ㄟ2020/03/13 17:12:08

我在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,所以我认为(也许不正确地),这个问题也引起这是启用的码prettifier serve但禁用build( TSLint不会在保存操作中调用,因此npm run serve在我的情况下不受影响)。