vue.js - 使用 vue-cli 构建深度嵌套的 html 需要永远

标签 vue.js vuejs2 vue-cli

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

比如我刚刚加了一些div s 至 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>

然后 build 过程需要很长时间,我相信这种深度的巢穴并不少见。

我该如何处理这个问题?

编辑(详细信息)

看来问题可能是特定于环境的,所以这里是详细信息。

至少可以在这些环境中重现此问题:

  • Mac mini 上的 macOS High Sierra(2014 年末)
  • 戴尔 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 

如果我放手,需要... 1155409ms!!!!

 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 })
// }

这样问题就解决了。谢谢前端,谢谢。

最佳答案

我可以重现您描述的性能问题(macOS High Sierra 10.13.4、Node 8.9.4 和 9.11.1)。新创建的 vue-cli 也会出现此问题3.x 项目。

挂起实际发生在 prettier 中, 从 vue-loader 's template compiler 调用.嵌套<div> s 被 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 秒。该错误的原因是创建 div 的深层嵌套函数调用。秒。我已在 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
            })
      }
    }
    

关于vue.js - 使用 vue-cli 构建深度嵌套的 html 需要永远,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50752427/

相关文章:

javascript - 使用 VueJS 的 WebRTC : Why the remote video is not playing?

javascript - 如何告诉 Vue 应用使用 Firebase 模拟器?

vue.js - Vue 3 和组合 API : template refs in v-for loop error : only get proxies

javascript - 为什么所有值都不能使用 Vue JS 在 Html 中动态传递?

vue.js - 如何删除vue表中的整列?

vue.js - 如何推迟表单输入绑定(bind),直到用户单击提交按钮?

javascript - 无法使用vuejs和electronicjs创建简单的文件资源管理器

javascript - 如果字符超过 Vue.js 中的限制,则仅显示名称的一部分

node.js - 使用 vue-cli 遇到 "couldn' t infer parser"错误

javascript - 在模板中时无法访问 Vue 商店中的 getter