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.
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"
]
}
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:
The app doesn't work as expected. Instead certain buttons are broken as shown in below screen shot (or if you visit that page):
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.
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.
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.
| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.8.1
| Node | 8.9.4
| npm/Yarn | 5.6.0/1.6.0
| Operating System | Windows 10
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.
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,
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!
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
@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 :+1:
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
@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.
@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
@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.
@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).
I meant languages like pug and markdown that get transpiled down to html @houd1ni
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.
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.
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.
Yeah, this issue keeps biting me on my projects. I love parcel, but this bug is intensely frustrating.
Refactored all self-closing tags as @muzafarova said and it works fine now
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
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.
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?
There is still an issue with Parcel and the build command when using Vue. Here is a reproducible repo. I have detailed what I have already tried in the readme.md.
Any help on this would be great. I've even tried using the latest alpha 2.0.0-alpha.1.1 and that won't even allow the build to happen :(
@devongovett, @mischnic any chance of getting word from someone on the team about this issue please?
I've read #2924 and even with closing the tags there is still an issue. The repo linked here details the problem when using the build
command, where as, running serve
results in the dist
folder having working code (albeit unoptimised).
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.
Hello! I'm interested in championing the use of Parcel.js for Wikipedia for prototyping and development but I hit this bug recently which means that may not be viable. Keen to not see this issue go stale!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.
Most helpful comment
Yeah, this issue keeps biting me on my projects. I love parcel, but this bug is intensely frustrating.