Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with vue.js and building for production #1294

Open
carbontwelve opened this issue May 4, 2018 · 19 comments

Comments

Projects
None yet
@carbontwelve
Copy link

commented May 4, 2018

This is a 馃悰 bug report.

When using parcel to build for production it breaks my vue.js application. This only happens when building for production, using parcel in development works with no issue.

馃帥 Configuration (.babelrc, package.json, cli command)

package.json:

{
  "dependencies": {
    "vue": "^2.5.16",
    "vue-hot-reload-api": "^2.3.0"
  },
  "devDependencies": {
    "@vue/component-compiler-utils": "^1.1.0",
    "parcel-bundler": "^1.8.1",
    "vue-template-compiler": "^2.5.16"
  }
}

.babelrc

{
  "presets": [
    "env"
  ]
}

馃 Expected Behavior

When building https://github.com/photogabble/vuejs-incremental-game-tutorial using the command parcel build index.html --public-url=./ --out-file=index.html and uploading to http://builds.photogabble.co.uk/parcel-js-vue-bug-report/ the app should work as expected (when it does work locally in dev mode.)

Below shows a screenshot of the expected behavior:

image

馃槸 Current Behavior

The app doesn't work as expected. Instead certain buttons are broken as shown in below screen shot (or if you visit that page):

image

In vue the component is loaded via <Resource name="Ore Reserves" units="tons" v-on:doBuy="buyOre" v-on:doSell="sellOre" v-bind:amount="ore" v-bind:buyPrice="oreBuy" v-bind:sellPrice="oreSell" v-bind:credits="credits" transactional></Resource> and the buy/sell prices are passed through from App.vue as not being the zero being displayed.

Given that this only happens when parcel bundles for production I feel that this is a bug with parcel and not with my code.

馃拋 Possible Solution

The only solution I have found is to run parcel index.html --public-url=./ --out-file=index.html and then upload the development files from the dist folder. This can be seen working at http://builds.photogabble.co.uk/vuejs-incremental-game-tutorial-p1/.

This tells me that there is something wonky going on with the build process for production.

馃敠 Context

I was just trying to get a demo of my project online to share and it wasn't working, which is odd to me because it does work when built for development.

馃捇 Code Sample

馃實 Your Environment

Software Version(s)
Parcel 1.8.1
Node 8.9.4
npm/Yarn 5.6.0/1.6.0
Operating System Windows 10
@luikore

This comment has been minimized.

Copy link
Contributor

commented May 9, 2018

I met this issue too.

I think it is related to uglify name mangling: parcel concats some prelude js with uglified code. But uglify-es changes variable / function names in compression without knowing what name has been used by outside code.

Adding a .uglifyrc with {mangle: false} should work around this problem.

@carbontwelve

This comment has been minimized.

Copy link
Author

commented May 14, 2018

I added a .uglifyrc as @luikore suggests but the result from parcel build is still broken. I do think its something to do with uglification changing variable names... possibly lower-casing my camel-cased variables.

edit:

After realizing this is indeed an issue with uglify mangling and after adding .uglifyrc, I have managed to fix things for the time being by disabling minification on build completely. parcel build --no-minify results in a working build.

This tells me that there is something wrong with parcels usage of uglify,

@houd1ni

This comment has been minimized.

Copy link

commented May 16, 2018

Affected me too. Looks like something tries to minify HTML/templates before they transpiled by vue-template transpiler.

<div v-for="(foo, key) in bar> ... </div>" => <div prop="[Object, Object]"> ... </div>

And half of my app is just blank. Without any errors!

@DeMoorJasper

This comment has been minimized.

Copy link
Member

commented May 16, 2018

Perhaps we can add a check to html and not minify the html if it's part of another asset

this:

if (this.options.minify) {
	await htmlnanoTransform(this);
}

to:

if (this.options.minify && !this.options.rendition) {
	await htmlnanoTransform(this);
}

This is the line that should change:
https://github.com/parcel-bundler/parcel/blob/master/src/assets/HTMLAsset.js#L158

@houd1ni

This comment has been minimized.

Copy link

commented May 17, 2018

@DeMoorJasper

Thank you! But the trick does work only if we do the same with pretransform simultaneously with transform method that you mentioned. Please, check that it's a good solution and add this to the project!

The solution is:

  async pretransform() {
    if(!this.options.rendition) {
      await posthtmlTransform(this);
    }
  }

  async transform() {
    if (this.options.minify && !this.options.rendition) {
      await htmlnanoTransform(this);
    }
  }

By the way, in a project with .ts, vue, .js, .json and assets there're nothing left unminified after applying the trick 馃憤

@SteffenL

This comment has been minimized.

Copy link
Contributor

commented May 17, 2018

The problem (in my case) is with posthtml and its lack of support for self-closing custom tags (I wrote some details in #1363).

I am not sure makes sense to transform the template multiple times as it will go through the Vue template compiler (or whatever compiler) anyway. As long as linked assets (images, etc) within the template are still bundled and linked in the output as expected, then it seems reasonable to me to skip the transformation.

If minification is enabled, then I think that the compiled template (I mean the final HTML) should be minified as well, just after compilation rather than before. Or maybe the minification should be done only on the "root" documents?

Related: #1103 #1316

@houd1ni

This comment has been minimized.

Copy link

commented May 17, 2018

@SteffenL

Thank you for the great investigation!

I believe, that "the final HTML" after vue-template-compiler should not be a HTML, but rather a render function, that is plain JS, so, it is the reason why I've got the minified bundle without html minification in my project without .html assets.

@DeMoorJasper

This comment has been minimized.

Copy link
Member

commented May 17, 2018

@houd1ni I think your solution looks good, the only concern I have regarding this fix is assets that get compiled down to html, if it's the final transform than it should be responsible for the minification. Which if I'm not mistaken won't happen in your solution

@SteffenL

This comment has been minimized.

Copy link
Contributor

commented May 17, 2018

@houd1ni You are right. I was having a dumb moment there thinking the template was included in the JS bundle! So when the template compiles to a render function/JSX, there is no point in minifying the template. It should still be possible for other asset types to compile to HTML and apply minification.

@houd1ni

This comment has been minimized.

Copy link

commented May 17, 2018

@DeMoorJasper

So, for instance, if one has included her own .html in a project, that IS NOT a .vue file, her bundle will have that unminified html in the output ? If not, could you, please, give an thought experiment, that can produce such faulty resaults? Thank you!

(In the case of .vue, the vue compiler itself will turn it to JS, that I've already mentioned, then uglify will minify that js).

@DeMoorJasper

This comment has been minimized.

Copy link
Member

commented May 17, 2018

I meant languages like pug and markdown that get transpiled down to html @houd1ni

@gorbypark

This comment has been minimized.

Copy link

commented May 23, 2018

I think this is also affecting me..parcel index.html works great, parcel build index.html results in a blank page, with no errors. I can see all the assets are loaded but haven't been able to track down the exact cause yet.

@muzafarova

This comment has been minimized.

Copy link

commented May 24, 2018

Noticed same issue recently. This only happens if there are a few self-closing vue tags.
All fine in dev, but part of contents is missing in build for production, no errors/warnings.

@jbrodriguez

This comment has been minimized.

Copy link

commented Jul 7, 2018

I've just installed 1.9.4 and this is still an issue.

Lost a morning trying to figure it out (drove me a bit insane).

It was compounded by the fact that I can't seem to get the bundler middleware to generate a non-minified build (minify: false doesn't work).

I'll open an issue about that.

EDIT:
Forgot to mention that this happens to me with Vuejs.

@Morgul

This comment has been minimized.

Copy link

commented Jul 7, 2018

Yeah, this issue keeps biting me on my projects. I love parcel, but this bug is intensely frustrating.

@fang0rnz

This comment has been minimized.

Copy link

commented Jul 23, 2018

Refactored all self-closing tags as @muzafarova said and it works fine now

@TiboC

This comment has been minimized.

Copy link

commented Jul 31, 2018

Hello,
I have the same issue. It doesn't work after the first self-closing tag.
This doesn't work:
<b-img :src="logo" class="mb-4" fluid alt="Logo" width="72" height="72" />

While this does:
<b-img :src="logo" class="mb-4" fluid alt="Logo" width="72" height="72" ></b-img>

Any chance to get this resolved?
Thanks

Thibaut

@Morgul

This comment has been minimized.

Copy link

commented Aug 28, 2018

To throw more fuel on the fire, I just encountered an example that isn't self closing tags where valid Vue code breaks because of this.

I have a project using BootstrapVue, and in it I'm popping some modals. I used the directive shorthand for that:

<b-btn variant="danger" class="float-right" v-b-modal.delModal>
    Delete
</b-btn>

That wasn't working in production builds and I couldn't figure out why. However, it works if I change it to the alternative syntax:

<b-btn variant="danger" class="float-right" v-b-modal="'delModal'">
    Delete
</b-btn>

Seems like another situation in which the HTML minification is building an incorrect AST and confusing Vue.

@nandlal-tjm

This comment has been minimized.

Copy link

commented Dec 2, 2018

I used packages name in v-for as below:
<tr v-for="package in packages>"
above breaks in the production. I use following instead
<tr v-for="share in shares>"
It works.
Is packages or package is the reserve keyword?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can鈥檛 perform that action at this time.