Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

How can I keep the css order in the css file when I use extract-text-webpack-plugin? #200

Closed
cage1618 opened this issue Jun 24, 2016 · 31 comments

Comments

@cage1618
Copy link

How can I keep the css order in the css file when I use extract-text-webpack-plugin?

// app.js
import '../scss/index.scss';
import AnComponent from './components/AnComponent/index';
// ./components/AnComponent/index.js
import './src/scss/index.scss';

export default class AnComponent Component {
    render() {
        return (
            <div class="component">
               I am a example component
            </div>
        );
    }
}
// ../scss/index.scss
body{
    background-color:red;
}
// ./components/AnComponent/src/scss/index.scss
body{
    background-color:green;
}

How can ensure ./scss/index.scss is before ./components/AnComponent/src/scss/index.scss in the output css file when I use extract-text-webpack-plugin?

@FabioAntunes
Copy link

Same problem here, my sass file:

$icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/";
@import "~bootstrap-sass/assets/stylesheets/bootstrap";
@import "~angular-ui-grid/ui-grid.css";
@import "~angular-ui-select/select.css";
@import "~startbootstrap-sb-admin-2/dist/css/sb-admin-2.css";
@import "dashboard";
@import "editable-grid";
@import "flash-msgs";
@import "manual-link";
@import "popular";
@import "product-list";
@import "sidebar";
@import "slider";
@import "widgets";

My webpack config:

{
      test: /\.scss$/,
      loader: ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap!postcss-loader!sass?sourceMap')
}

And then on my browser:
screenshot from 2016-08-05 10 49 03

Note: _panels.scss is a bootstrap component

@Jessidhia
Copy link
Contributor

Try doing your order-dependent imports in JS, or adding the @imports inside the files that actually depend on those files happening before them. AFAIK, webpack doesn't care about the order dependencies appear in, since the ordering is enforced by the order require calls are encountered; but that has issues with CSS, as it doesn't have a "runtime" order.

Doing as many imports in JS as possible also should help with incremental build performance.

@louis-pvs
Copy link

I have a workaround but wasn't pretty...

const extractLibStyle = new ExtractTextPlugin("[name].lib.[hash].css");
const extractProjectStyle = new ExtractTextPlugin("[name].[hash].css");
module: {
        loaders: [ { ... }, {
            test: /\.(css|scss|sass)$/,
            loader: extractLibStyle.extract("style-loader", "css-loader!sass-loader?sourceMap"),
            include: [path.resolve(ROOT, "bower_components/"), path.resolve(ROOT, "node_modules/")],
            exclude: path.resolve(ROOT, "app/")
        }, {
            test: /\.(css|scss|sass)$/,
            loader: extractUserStyle.extract("style-loader", "css-loader?localIdentName=[folder]__[local]&modules&importLoaders=1!postcss-loader!sass-loader?sourceMap"),
            include: path.resolve(ROOT, "app/"),
            exclude: [path.resolve(ROOT, "bower_components/"), path.resolve(ROOT, "node_modules/"), path.resolve(ROOT, "build/")]
        }, { ... } ]
    }
}
plugins: [
        extractLibStyle,
        extractProjectStyle,
]

So library styling will come first before my project styling, by using this approach...
Pro

  • able to seperate out two styling into two file
  • absolute control of which stylesheet being extracted and insert into <head> tag, even if I purposely require the bower file after my project file like this
// app.js
require("../stylesheets/main.scss");
require("~/bower_components/mdi/scss/materialdesignicons.scss");

output:

<!-- index.html -->
<link href="/app.lib.6c157af1e450e9782aca.css" rel="stylesheet">
<link href="/app.6c157af1e450e9782aca.css" rel="stylesheet">

Con is

  • there is a lot of writing going on...
  • more http request, this might be a concern to some people...

Still, hope there is an option to control the order

@jhnns
Copy link
Member

jhnns commented Oct 4, 2016

The order of the extracted text is based on the order of require() calls inside the bundle. If you want to ensure that the output of index.scss is before all the other rules, you need to require("./index.scss") before requiring all the components.

@nlitwin
Copy link

nlitwin commented Nov 23, 2016

@jhnns I can get the ordering to work properly if I follow your instructions and put require('./index.scss') before requiring other components, but if I remove { "modules": false } from my .babelrc's es2015 preset, the ordering is wrong again. Any idea on why that would cause it to change?

@jhnns
Copy link
Member

jhnns commented Nov 23, 2016

require() and import() are very different constructs. require() is a regular function and will always execute in the given order. import() is not a function, but syntactic sugar for a native language feature. ES2015 will hoist all imports and resolve them before any code is executed. And babel emulates that behavior by first hoisting all imports and then turning them into require(). That's why your other components will be required first when you remove "modules": false.

@wen96
Copy link

wen96 commented Jan 10, 2017

Same issue as @FabioAntunes. It sames like, when you @import from .css and SASS files, it keep order between css and scss but not both together. For example:

// main.scss

// It works
@import "../../node_modules/bootstrap/dist/css/bootstrap.css";
@import "../../node_modules/admin-lte/dist/css/AdminLTE.css";

// Wrong order
@import "../../node_modules/bootstrap-sass/assets/stylesheets/bootstrap";
@import "../../node_modules/admin-lte/dist/css/AdminLTE.css";

@FabioAntunes have you find any solution to this?

@FabioAntunes
Copy link

@wen96 Not really, I had to re-write the rules on my scss, fortunately they were just a couple, which might not be your case.

@Gtosta96
Copy link

Gtosta96 commented Feb 7, 2017

someone have solutions for this one?

@secondstreetmedia
Copy link

secondstreetmedia commented Mar 10, 2017

It's difficult to tell from the code snippets posted above if this will help others, but my issue was that I only had some of my styling related loaders utilizing the extract-text-webpack-plugin rather than all of them. Once I ensured all of them utilized the plugin, my styles were loading consistently in the order I wanted them to, at least in development. (See my more detailed response here: webpack/webpack#215). Note: I used require statements.

config (original)

{
  test: /\.css$/,
  use: ['style-loader', 'css-loader']
},
{
  test: /\.*(sass|scss)$/,
  use: ExtractTextPlugin.extract({
    fallback: 'style-loader',
    use: ['css-loader', 'sass-loader']
  })
},

config (revised)

{
  test: /\.css$/,
  use: ExtractTextPlugin.extract({
    fallback: 'style-loader',
    use: ['css-loader']
  })
},
{
  test: /\.*(sass|scss)$/,
  use: ExtractTextPlugin.extract({
    fallback: 'style-loader',
    use: ['css-loader', 'sass-loader']
  })
},

@bebraw
Copy link
Contributor

bebraw commented May 6, 2017

Can someone provide a standalone example illustrating this issue? That would help a lot. Thanks.

@ben-yocum
Copy link

I had the same issue as @wen96: load order isn't respected with mixed css and scss.

@julkue
Copy link

julkue commented Sep 11, 2017

@bebraw You can reproduce it in my repository here. The normalize.css is generated after the other required components.

Relative issues I've found:

@felschr
Copy link

felschr commented Feb 22, 2018

I'm using @imports in my css files (without using CSS modules) and I'm experiencing this issue.
Moving the imports to js didn't change anything about that.

Is this really still and issue? Am I missing something?

@alexander-akait
Copy link
Member

@felschr bug exists, feel free to PR

@pbarbiero
Copy link

This started happening for me with webpack 3.11.0, 3.10.0 does NOT exhibit this issue.

@gtournie
Copy link

@vincent-louis I did the same but I used the file-merge-webpack-plugin to get only css file at the end (it messes up the source map tho...)

This is a real issue in my case. I import Bootstrap via css-modules (with reactstrap) and have also some custom stylesheets:

import bs from 'bootstrap'
import styles from './styles'
[...]
  <div styleName="bs.bg-primary styles.bg"></div>

For now there is no way to ensure that all bootstrap styles will be placed first. The only workaround is to use 2 ExtractTextWebpackPlugin instances and to generate 2 css files.

It would be nice to have a priority option, like:

{ test: ..., loader: ExtractTextPlugin.extract({ use: ..., priority: 1 }) }, // Bootstrap
{ test: ..., loader: ExtractTextPlugin.extract({ use: ..., priority: 2 }) }, // App

@sherlock1982
Copy link

Started to happen for me in Webpack 4.0.1.

@th3fallen
Copy link

im still getting this on 3.0.2 anyone know a fix for it, it is maddening

@pboos
Copy link

pboos commented Mar 21, 2018

Just upgraded to Webpack 4.1.1 and this is happening to me it seems.

Strange thing: It changes the order depending on the build. Sometimes it is ok. Sometimes it is wrong. So ordering seems random?

Changes:

-        "extract-text-webpack-plugin": "3.0.2",
+        "extract-text-webpack-plugin": "4.0.0-beta.0",

-        "css-loader": "0.28.9",
+        "css-loader": "0.28.11",

-        "sass-loader": "6.0.6",
+        "sass-loader": "6.0.7",

-        "webpack": "3.10.0",
+        "webpack": "4.1.1"

Not exactly know whose fault it is. But something is getting messed up. Wondering if I should switch back to webpack 3.10.0.

@sherlock1982
Copy link

I swtiched to mini-css-extract-plugin and the order is ok now. Looks like extract-text-webpack-plugin will be left for Webpack3

@pboos
Copy link

pboos commented Mar 21, 2018

As @sherlock1982 said, extract-text-webpack-plugin is for webpack3 and older (will not support webpack 4 it seems). They say to move to mini-css-extract-plugin.

For more information see here: #701 (comment)

@luojianet
Copy link

luojianet commented Apr 8, 2018

Here's a solution

@bebraw issue reproduce code
use extract-text-webpack-plugin webpack plugin.

  • write like this, can not keep css order.
import "../css/normalize.css";
import "../css/animate.css";
import "../css/style.css";

----------------------splite line----------------------

  • you can write like this.
import "../css/first.css";
/*first.css*/
@import url(normalize.css);
@import url(animate.css);
@import url(style.css);

montehurd added a commit to wikimedia/wikimedia-page-library that referenced this issue May 5, 2018
Use `mini-css-extract-plugin` instead of `extract-text-webpack-plugin`.

"How can I keep the css order in the css file when I use extract-text-webpack-plugin"
"TL;DR Use mini-css-extract-plugin instead"
webpack-contrib/extract-text-webpack-plugin#200
webpack-contrib/extract-text-webpack-plugin#200 (comment)
webpack-contrib/extract-text-webpack-plugin#701 (comment)
@ghost
Copy link

ghost commented Jun 21, 2018

I wasn't able to fix the issue with any suggestion until I moved to mini-css-extract-plugin and now it works like a charm. If anyone's having trouble you should give that plugin a try.

@julkue
Copy link

julkue commented Aug 2, 2018

Could fix it finally by switching to https://github.com/webpack-contrib/mini-css-extract-plugin

@alexander-akait
Copy link
Member

@julmot PR welcome

@x-yuri
Copy link
Contributor

x-yuri commented Sep 17, 2018

I can't reproduce it. See this post.

@zacherkkila
Copy link

zacherkkila commented Oct 11, 2018

It seems like there are multiple issues here but just for anyone out there that might have the same issue as me.. I get this problem anytime I have a "." in the file name. This seems to push it to the bottom of the import list

For example

@import "./bootstrap.min.css";
@import "./common.css"

Results in common.css above bootstrap.css

However,

@import "./bootstrap.css";
@import "./common.css"

Results in the correct order.

I can consistenly make this happen just by having a ".something" in the filename

@import "./test.awesome.css";
@import "./common.css"

and

@import "./test.css";
@import "./common.css"

Has the same result

I just renamed the files in my program but that would be a place to look

@x-yuri
Copy link
Contributor

x-yuri commented Oct 11, 2018

@zacherkkila I tried to reproduce it but failed (branch double-extension). Can you help us figure out how to reproduce it? Like, an archive or repository with an example (preferably simple) that reproduces the issue?

@zacherkkila
Copy link

zacherkkila commented Oct 12, 2018

@x-yuri I am realizing after looking at your example that the project I am on is using an old version of the extract text plugin and I should be switching over to the mini-css-extract-plugin as mentioned in a few earlier comments. I haven't tested yet but I am guessing that will solve the issue. If for some reason I still have problems I will try to get something reproducible. Sorry for the time waste but thanks for pointing me in the right direction on that

@alexander-akait
Copy link
Member

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests