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

fix: split async CSS correctly #546

Closed
wants to merge 28 commits into from

Conversation

BowlingX
Copy link

This is a work-in-progress pull-request to address issue #120.
I added a test case to demonstrate the issue, use-case and my expectations.

@jsf-clabot
Copy link

jsf-clabot commented Jun 17, 2017

CLA assistant check
All committers have signed the CLA.

@BowlingX
Copy link
Author

I adjusted the extraction logic, the result is now as expected, however another test (splitted-multiple-entries) fails now. I'm not sure if I'm heading in the right direction or if we may should make this configurable.

@BowlingX
Copy link
Author

ok, ignore the last commit, does not make any sense and is not working at all.

@codecov
Copy link

codecov bot commented Jun 18, 2017

Codecov Report

❗ No coverage uploaded for pull request base (master@b254e96). Click here to learn what that means.
The diff coverage is 96.87%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master     #546   +/-   ##
=========================================
  Coverage          ?   88.37%           
=========================================
  Files             ?        7           
  Lines             ?      327           
  Branches          ?       71           
=========================================
  Hits              ?      289           
  Misses            ?       36           
  Partials          ?        2
Impacted Files Coverage Δ
src/lib/helpers.js 90.24% <100%> (ø)
src/index.js 91.13% <96.66%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b254e96...edd39a1. Read the comment docs.

@BowlingX
Copy link
Author

I think I finally found the correct way to do it. It was a little hard to get my head around it without much docs about the webpack internals, but I think it's a proper solution.

I will now actually keep the fallback loader in place for the async bundles and only rebuild it without replacing it in the async chunks. That means all css is correctly async loaded and only the css for the initial chunk is written down (if allChunks: false).

The initial chunks is freed from all dependencies and replaced with the generated module (that may contain the css-module informations).

BowlingX added a commit to BowlingX/extract-css-chunks-webpack-plugin that referenced this pull request Jun 19, 2017
@michael-ciniawsky
Copy link
Member

Fixes #120

@michael-ciniawsky
Copy link
Member

@BowlingX WoW..😧 😛 . I'm not 💯 skilled to answer if this is suitable or not, but it looks very good

@michael-ciniawsky michael-ciniawsky added this to the 2.2.0 milestone Jun 20, 2017
Copy link
Contributor

@bebraw bebraw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's too complex for me to review properly. Better get Tobias on this.

@alexander-akait
Copy link
Member

@BowlingX please squash all commits in one for easy review, thanks

@michael-ciniawsky
Copy link
Member

An additional 'problem' is the webpack 3 release, which requires a breaking change here #540 #543 (#542), so we need to fix this first (as quickly as possible). So maybe you need to rework a few parts because of this in any case 🙏

commit e2631af
Author: David Heidrich <me@bowlingx.com>
Date:   Mon Jun 19 19:08:13 2017 +0200

    removed dead code, cleanup

commit d8943d7
Author: David Heidrich <me@bowlingx.com>
Date:   Mon Jun 19 15:48:51 2017 +0200

    restored console log

commit 0d7c94a
Author: David Heidrich <me@bowlingx.com>
Date:   Mon Jun 19 00:30:34 2017 +0200

    fixed async loading (keep original style loader in async chunks)

commit 950d7ef
Author: David Heidrich <me@bowlingx.com>
Date:   Sun Jun 18 15:52:41 2017 +0200

    fixed exporting module informations

commit 8b97ee5
Author: David Heidrich <me@bowlingx.com>
Date:   Sun Jun 18 14:27:51 2017 +0200

    fixed line length

commit 6898aa4
Author: David Heidrich <me@bowlingx.com>
Date:   Sun Jun 18 14:26:34 2017 +0200

    respect all chunks

commit bbc93ab
Author: David Heidrich <me@bowlingx.com>
Date:   Sun Jun 18 12:33:09 2017 +0200

    adjusted test to be env agnostic

commit 3eba627
Author: David Heidrich <me@bowlingx.com>
Date:   Sun Jun 18 12:25:16 2017 +0200

    adjusted tests to use css-loader, added tests for allChunks, remove module from initial chunk

commit 09ac8cb
Author: David Heidrich <me@bowlingx.com>
Date:   Sat Jun 17 22:36:09 2017 +0200

    adjusted tests, remove module from base if extracted

commit 1791796
Author: David Heidrich <me@bowlingx.com>
Date:   Sat Jun 17 21:23:58 2017 +0200

    added testcase for issue webpack-contrib#120
Copy link
Member

@joshwiens joshwiens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be targeting master with this or the feature/webpack3. This PR is wasted putting it in the current version range as it's only applicable to Webpack v2

@joshwiens
Copy link
Member

We can always back port it to the 2.x version range after the fact.

@BowlingX
Copy link
Author

Seems like vue is handling async css loading on it's own. I think this get's in the way how extrac-text-webpack-plugin and my changes are doing this right now. So I would not expect that to be working together.

@nkonev
Copy link

nkonev commented Jul 26, 2017

@BowlingX
Thank you for response

@michael-ciniawsky @sokra @d3viant0ne @BowlingX
I also found that I can fix it by disable webpack's cache (introduced in 3.0.0)

Unfortunately there isn't activity in https://github.com/vuejs/vue-style-loader, ok, I'll try to create issue there (vue-style-loader repo).

@michael-ciniawsky @sokra @d3viant0ne
But before it I want to ensure that trouble is exactly in vue-style-loader =) (Disabling Webpack cache solves it)

@BowlingX
Copy link
Author

BowlingX commented Aug 4, 2017

What is the status for this pull-request? Is there any more work needed?

@BowlingX
Copy link
Author

I was able to reproduce the issue that @nikit-cpp had. Something is not right here, I will investigate

@nkonev
Copy link

nkonev commented Aug 16, 2017

@BowlingX I can check if need

@michael-ciniawsky
Copy link
Member

The approach looks fine so far (from what i can tell :)) but as mentioned before I can't fully approve the changes. @sokra needs to review this PR to ensure this doesn't break the plugin

src/index.js Outdated
@@ -26,7 +27,7 @@ class ExtractTextPlugin {
if (isString(options)) {
options = { filename: options };
} else {
validateOptions(path.resolve(__dirname, '../schema/plugin.json'), options, 'Extract Text Plugin');
validateOptions(path.resolve(__dirname, './schema/plugin.json'), options, 'Extract Text Plugin');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

./schema is not resolved correctly when I build the branch from source. Not sure how the build process is, but without changing the path it does not compile.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be reverted and the schema folder moved back to where it was.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally move schema/Plugin.json && schema/loader.json from /schema to /src/Plugin.json && /src/loader.json and add --copy-files to the build script in package.json please.

- schema
src
||– index.js 
||– Plugin.json
||- loader.js
||- loader.json
|
|-package.json

src/index.js Outdated
@@ -40,6 +41,17 @@ class ExtractTextPlugin {
return { loader: require.resolve('./loader'), options };
}

static cloneModule(module) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

src/index.js Outdated
@@ -145,25 +159,38 @@ class ExtractTextPlugin {
const extractedChunk = extractedChunks[chunks.indexOf(chunk)];
const shouldExtract = !!(options.allChunks || isInitialOrHasNoParents(chunk));
chunk.sortModules();
async.forEach(chunk.mapModules(c => c), (module, callback) => { // eslint-disable-line no-shadow
async.forEach(chunk.mapModules((c) => { return c; }), (module, callback) => { // eslint-disable-line no-shadow, arrow-body-style
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be changed to c => c, properly a missed merge

@oviava
Copy link

oviava commented Oct 19, 2017

does this have any more traction ? run some local tests with the forked branch and seems ok

@FlorianH
Copy link

+1

Copy link

@danez danez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had to use this here at my company because of the issue this is solving. Works fine so far.
The PR lgtm only the schema folder should be moved back to where it was imho and the stuff that was mentioned by others.

src/index.js Outdated
@@ -26,7 +27,7 @@ class ExtractTextPlugin {
if (isString(options)) {
options = { filename: options };
} else {
validateOptions(path.resolve(__dirname, '../schema/plugin.json'), options, 'Extract Text Plugin');
validateOptions(path.resolve(__dirname, './schema/plugin.json'), options, 'Extract Text Plugin');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be reverted and the schema folder moved back to where it was.

src/index.js Outdated
@@ -88,7 +100,7 @@ class ExtractTextPlugin {
if (Array.isArray(options) || isString(options) || typeof options.options === 'object' || typeof options.query === 'object') {
options = { use: options };
} else {
validateOptions(path.resolve(__dirname, '../schema/loader.json'), options, 'Extract Text Plugin (Loader)');
validateOptions(path.resolve(__dirname, './schema/loader.json'), options, 'Extract Text Plugin (Loader)');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also be reverted.

Copy link
Author

@BowlingX BowlingX Nov 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I run the tests with ../schema I get:

ENOENT: no such file or directory, open '/home/david/Projekte/extract-text-webpack-plugin/schema/loader.json'

Copy link

@danez danez Nov 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because you moved the schema folder into the src folder, but @michael-ciniawsky wants to have them in a different location anyway, see other comment.

@BowlingX
Copy link
Author

I will do the suggested changes and solve the conflicts today.

Copy link
Member

@michael-ciniawsky michael-ciniawsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only whitespace nits. Could you also move the various eslint-disable-line comments to the top please ?

/* eslint-disable
  ...,
  ...,
*/

src/index.js Outdated
@@ -26,7 +27,7 @@ class ExtractTextPlugin {
if (isString(options)) {
options = { filename: options };
} else {
validateOptions(path.resolve(__dirname, '../schema/plugin.json'), options, 'Extract Text Plugin');
validateOptions(path.resolve(__dirname, './schema/plugin.json'), options, 'Extract Text Plugin');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally move schema/Plugin.json && schema/loader.json from /schema to /src/Plugin.json && /src/loader.json and add --copy-files to the build script in package.json please.

- schema
src
||– index.js 
||– Plugin.json
||- loader.js
||- loader.json
|
|-package.json

@@ -126,8 +127,10 @@ class ExtractTextPlugin {
const filename = this.filename;
const id = this.id;
let extractedChunks;
let toRemoveModules;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\n

src/index.js Outdated
compilation.plugin('optimize-tree', (chunks, modules, callback) => {
extractedChunks = chunks.map(() => new Chunk());
toRemoveModules = [];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\n

src/index.js Outdated
let meta = module[NS];
if (meta && (!meta.options.id || meta.options.id === id)) {
const wasExtracted = Array.isArray(meta.content);
// A stricter `shouldExtract !== wasExtracted` check to guard against cases where a previously extracted
// module would be extracted twice. Happens when a module is a dependency of an initial and a non-initial
// chunk. See issue #604
if (shouldExtract && !wasExtracted) {
module[`${NS}/extract`] = shouldExtract; // eslint-disable-line no-path-concat
compilation.rebuildModule(module, (err) => {
const newModule = cloneModule(module);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\n

src/index.js Outdated
module[`${NS}/extract`] = shouldExtract; // eslint-disable-line no-path-concat
compilation.rebuildModule(module, (err) => {
const newModule = cloneModule(module);
newModule[`${NS}/extract`] = shouldExtract; // eslint-disable-line no-path-concat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\n

src/index.js Outdated
const data = toRemoveModules[module.identifier()];
if (data) {
const oldModuleId = module.id;
const newModule = cloneModule(module);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\n

const oldModuleId = module.id;
const newModule = cloneModule(module);
newModule.id = oldModuleId;
newModule._source = data.module._source; // eslint-disable-line no-underscore-dangle
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\n

newModule.id = oldModuleId;
newModule._source = data.module._source; // eslint-disable-line no-underscore-dangle
data.chunks.forEach((chunk) => {
chunk.removeModule(data.moduleToRemove);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\n

newModule._source = data.module._source; // eslint-disable-line no-underscore-dangle
data.chunks.forEach((chunk) => {
chunk.removeModule(data.moduleToRemove);
const deps = data.moduleToRemove.dependencies;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\n

if (d.module && d.module.loaders.length > 0) {
chunk.removeModule(d.module);
}
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\n

Copy link
Member

@alexander-akait alexander-akait left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good see @michael-ciniawsky note

@BowlingX
Copy link
Author

BowlingX commented Mar 18, 2018

I made the requested adjustments, Is there anything more needed here? The request is quite old, I'm wondering how to proceed here.

@alexander-akait
Copy link
Member

@BowlingX Looks like we can close this PR, don't use ETWP for extract css, for this please use https://github.com/webpack-contrib/mini-css-extract-plugin. ETWP only for extract assets.

@BowlingX
Copy link
Author

BowlingX commented Apr 5, 2018

@evilebottnawi I guess yes. I tested the new plugin and it works well for me. Also with the last changes (#604) my approach does not work anymore and I would have to refactor a bit. But properly it's unecessary because of the new plugin.

@BowlingX BowlingX closed this Apr 5, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet