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

Extract Text plugin does not work with async required files #106

Closed
geekyme opened this issue Sep 6, 2015 · 25 comments
Closed

Extract Text plugin does not work with async required files #106

geekyme opened this issue Sep 6, 2015 · 25 comments

Comments

@geekyme
Copy link

geekyme commented Sep 6, 2015

Use case:

sell.js

require.ensure([], (require) => {
      SellForm = require("../../sell/sell-form");
});
.....

sell-form

import "child" from "./child"

child

require("cropper/dist/cropper.css");

Webpack:

...
module: {
    loaders: [
      { test: /\.js$/, exclude: /node_modules/, loaders: [strip.loader("debug"), "babel"] },
      { test: /\.css$/, loader: ExtractTextPlugin.extract("style", "css!autoprefixer?{browsers:['last 2 version', '> 1%']}") }
    ]
  },
  plugins: [
    // css files from the extract-text-plugin loader
    new ExtractTextPlugin("[name]-[chunkhash].css", {
      allChunks: true
    })
]

...

I expected a main bundle to be built main-xxxx.js, main-xxxx.css and then chunks sell-form-xxxx.js and sell-form-xxxx.css to be built. However I realized the cropper.css above is being inline-d as a <style> tag instead of being loaded as a <link> stylesheet

@Duan112358
Copy link

allChunks:true specify that ExtractTextWebpackPlugin will extract CSS from all chunks to one single CSS file, and it work for me

@satazor
Copy link

satazor commented Dec 20, 2015

I'm having the same problem here.. is this plugin not designed for this use-case?

@geekyme how do you got around this?

Thanks

@gbrassey
Copy link

+1 Wondering if it's possible for ExtractTextWebpackPlugin to generate CSS files for each of the split points.

@nuc
Copy link

nuc commented Feb 1, 2016

That would be awesome! @gbrassey Have you maybe found your way around it?

@stephenjwatkins
Copy link

+1

@jarvanxing
Copy link

+1 Wondering if it's possible for ExtractTextWebpackPlugin to generate CSS files for each of the split points.

I really need this.

@jackyon
Copy link

jackyon commented May 12, 2016

+1, any solution for this?

@ashsidhu
Copy link

+1

3 similar comments
@itsmepetrov
Copy link

+1

@maggiehe
Copy link

maggiehe commented Jul 5, 2016

+1

@OlegE90
Copy link

OlegE90 commented Jul 5, 2016

+1

@satazor
Copy link

satazor commented Dec 4, 2016

@sokra why was this issue closed? I think your commit didn't addressed this.

@dalimian
Copy link

dalimian commented Jan 2, 2017

@sokra, issue is not fixed, please reopen this ticket

@sokra sokra reopened this Jan 3, 2017
@dalimian
Copy link

dalimian commented Jan 4, 2017

thanks alot for reopening this ticket

there are two parts to what I think folks are asking for, could you plz clarify if both are in scope of this ticket

  1. ExtractTextWebpackPlugin to generate CSS file for each of the split points defined by required.ensure(...)
  2. If allChunks is set to false than the generated css file will be asynchronously included by require.ensure(...) similar to how the js split point is asynchronously included. Nice to have: async inclusion logic will be smart enough to NOT include it if the file was already statically included on the page.

@defaude
Copy link

defaude commented Feb 15, 2017

I still think this issue should not be closed.

tl;dr: Skip to the "So what do I want?" section if you're not interested in what I do not want :)

For a rather large application, I want the amount of chunks loaded at startup to be as minimal as possible while still being able to dynamically load another chunk at runtime (e.g. on route changes). I do not want to use the allChunks: true option of the ExtractTextWebpackPlugin for it would pull all the styles from all chunks into the single .css file loaded at startup - and that is quickly getting ridiculously huge which is impacting my load time dramatically.

At the same time, I do not want to have a "root" CSS (in my case LESS) file that knows about all other LESS files in that respective chunk. That would mean I'd have to to something like this:

/* file: chunk-root.js */
// import components
import './a';
import './b';
// import "root" style for the chunk
import './chunk-root.less';

/* file: a.js */
// import another component here, as well
import B from './b';
// note: NO style import
export default class A {
    constructor () {
        const b = new B();
        b.doStuff();
    }
}

/* file: b.js */
// no style import here, either
export default class B {
    doStuff() {}
}

/* file: chunk-root.less */
// ugh....
@import 'a.less';
@import 'b.less';

But I don't want to have two trees of files that someone needs to keep in sync - this kind of breaks the whole "bundler" idea, doesn't it? This also rules out loading the "root chunk" JS as well as the root chunk LESS manually, of course.

allChunks: false with split points defined by require.ensure is kind of working (at least some weird issues I had back in the day with Webpack 1 don't seem to be an issue anymore, e.g. webpack-contrib/style-loader#93). But I am not really happy with it. Sure, the initial entry chunk's CSS is pulled out but every additional chunk's CSS is part of the JS file resulting in longer (blocking) time for loading, parsing, etc. - even though the CSS is just a huge string for JS. Plus I've read several times that there's a maximum amount of <style> tags IE can handle (though I'm not sure what that cap is). That means the whole CSS-in-JS-thing via the style-loader falls apart at some point for apps that are bigger (and have lots of chunks).

So what do I want?

  • Potentially hundreds of entry chunks (don't worry, there's a single 'runtime' chunk with the runtime) - all of which have their CSS pulled out to a .css file with the ExtractTextWebpackPlugin:
config.entry= {
    app: _src('app/index.ts'),
    vendor: _src('app/vendor.ts'),
    'page-one': _src('app/ui/pages/page-one/page-one.ts',
    'page-two': _src('app/ui/pages/page-two/page-two.ts')
    // ... and so on
};
  • Most of these entry chunks, however, are excluded from the initial page:
new HtmlWebpackPlugin({
    template: _src('app/index.html'),
    excludeChunks: [
        'page-one', 'page-two' // ... and so on
    ]
})
  • Those chunks are dynamically loaded at runtime:
// e.g. in my router
require.ensure([], done, 'page-one');

Sadly, this will only download the .js file and I have no idea how to get the .css file.

Especially if there's a [hash] in the generated filename. The generated .css file's hash does not exist anywhere.

@fhqdgv
Copy link

fhqdgv commented Mar 21, 2017

I'm having the same problem!!!!!

@danielwalczak
Copy link

m2, do you have any solution ?

@kpaxqin
Copy link

kpaxqin commented Apr 2, 2017

@dalimian
I think point 1 is the most important thing I want for now.

@faceyspacey
Copy link

faceyspacey commented Apr 5, 2017

let's write this code--simple as that. This is the future of the extract text plugin. The code that needs to be edited is around here:

https://github.com/webpack-contrib/extract-text-webpack-plugin/blob/master/index.js#L267

One of these lines (possibly this one: module[NS + "/extract"] = shouldExtract) are indicating that all extracted "results" go to the "initial" non-dynamic entry chunk.

We need to write it so if allChunks === false and a new option inlineDynamicChunks === false (the default is true) , we extract the text to an output file per chunk.

The thinking behind inlineDynamicChunks is that unless you specify the option as false it will continue to do what it has always done, which is inline the CSS within the js files, that way old code doesn't break, ya digg. Maybe someone has a better name for it.

Anyway, we shouldn't be waiting around for the busy webpack people. Let's get this done. Anyone have any knowledge of how this all works?

@faceyspacey
Copy link

here's some additional notes on another issue regarding the same stuff:

#120 (comment)

@abhinavsingi
Copy link

Any update or workaround for this to happen?
Anyone tried https://www.npmjs.com/package/extract-css-chunks-webpack-plugin ?

@xiaoyu2er
Copy link

xiaoyu2er commented Jun 6, 2017

2 thoughts brought by @renaesop

  1. require("!!style!css!cropper/dist/cropper.css"); (You can add two exclamation to ignore loaders in the webpack config file)
  2. you can define another rule which doesn't use extractCssPlugin

@joaovieira
Copy link

https://www.npmjs.com/package/extract-css-chunks-webpack-plugin is working well for me using import() split points, creating CSS files per chunk and automatically/dynamically loading them via the required babel loaders (babel-dual-import or babel-universal-import) and flush-chunks. It's a combination of plugins but so far is doing what @defaude wants.

Though I'm having troubles now with automatically generated async chunks (common code for multiple async chunks via CommonsChunkPlugin) as webpack only loads the JS.

@ParadeTo
Copy link

+1

@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

Successfully merging a pull request may close this issue.