Vue-loader: css in reverse ordrer though App component is before router

Created on 24 Jun 2017  路  10Comments  路  Source: vuejs/vue-loader

Version

12.2.1

Steps to reproduce

create a laravel project, and in the main.js file just add

import App from './App' // add global scss like bulma in this App.vue
import './config/router' // add 2 or 3 components with scss to a router instance
// then just render App

What is expected?

I'm expecting bulma css to load first
then to have the components css

What is actually happening?

the opposite, bulma is loaded last and the css of components imported in the router loads first

wontfix investigating

All 10 comments

Please provide a run able reproduction, as was explained on new-issue.vuejs.org

i'm using : extractVueStyles: true in the laravel-mix options, so webpack extracts the css from vue to a file

as this is a vue-loader problem (so a problem on compilation) i can't really fiddle or plunkr this, what i'm saying is just that the css is inverted.

My App.vue css is loaded after the css of the components in the router, while it's supposed to be the opposite since i imported App.vue before importing the others.

But let me show some images

main.js

image

router.js

image

as you can see i import App.vue first, but App.vue's css comme after in the css file

Quoting from the explanation about "minimal ewpeoduction from new-issue.vuejs.org

If your bug involves a build setup, you can create a project using vue-cli and provide the link to a GitHub repository.

Code screenshots (which we can't even copy/paste to reproduce the problem) are not that.

okay, i'll do that in the week, in the mean time i had to import vue-router and it's components first, before importing my App.vue and the css now works correctly (which doens't make any sense)

@LinusBorg here you go, just installed a fresh new laravel installation using laravel-mix (because this is my env right now)

As you can see here
https://github.com/darkylmnx/vuetest/blob/master/public/vue-styles.css

The css of my components added in the router shows first in the file
And the css of my App.vue component shows next, while it's supposed to be the opposite as said above.

This is the mix config
https://github.com/darkylmnx/vuetest/blob/master/webpack.mix.js

The main file
https://github.com/darkylmnx/vuetest/blob/master/resources/assets/js/main.js

You can download the repo, then just yarn run watch ou npm run watch and then open the index.html file in the public directory.

Thank you, we will take a look as soon as possible!

Here is an even smaller reproduction example, that does not depend on laravel+sass: https://github.com/ptolstoi/vue-css-order-bug

If you build it, you can see that the app.css is included twice; before and after chunk-vendors.css.

The issues does not happen if you use yarn serve.

Hey @ptolstoi ,
your issue seems to be something different (the order of included .css files, while OPs problem is about the order of CSS rules within one file), and seems to be an issue with vue-cli (most likely this forked webpack plugin we use to add "preload" resources).

Please open an issue in the vue-cli repository. Thanks!

Thank you for the quick answer!

I just updated the example to include bulma+sass, the order in a single file is wrong as well. Hope this one helps you!

Thanks! That was indeed helpful to understand the issue we talk about here.

But I don't think this order is wrong. it may not be what OP expected, but it does make sense if you think about the mechanism of loading modules (see below), and has some other benefits: parents can actually overwrite children's CSS - so a wrapper component can overwrite CSS from its child.

Why is that order "correct"?

The flow goes like this:

  1. main.js imports App.vue
  2. so webpack first parses the <template>, then the <script> - and in the latter, it finds an import of HelloWorld.vue.
  3. So it "pauses" parsing that script block and starts the import process for that new module
    3.1 Here, it parses <template>, <script> and finally <style>
    3.2 Which means, the first CSS to be extracted is from HelloWorld.vue
  4. Then is resumes parsing the <script> in App.vue
  5. and finally, the <style> in App.vue, which means now that CSS is being extracted (including bulma)

So what's the solution

The simple solution would be to import glbal CSS in main.js (before App.vue) instead of in App.vue - the latter should only contain CSS directly related to its template.

Couldn'we we change the parsing order of vue-loader?

We could, but then people who want to overwrite child styles from a parent component won't be happy.

So I think there's not really a wrong and right answer, instead I think that relying on the order of rules of components is a bad practice, so it doesn't really matter which way we choose here.

Why? Just imagine that you re-order your imports, or move a component somehwere else, or decide to lazy-load it (inlcuding its css) - and boom suddenly all your CSS seems to be broken in random places, because you changed the order of CSS blocks from components with this, as well.

Was this page helpful?
0 / 5 - 0 ratings