Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single-file configuration emits JS assets in its own chunk group #85

Closed
notpeelz opened this issue Apr 3, 2018 · 37 comments
Closed

Single-file configuration emits JS assets in its own chunk group #85

notpeelz opened this issue Apr 3, 2018 · 37 comments

Comments

@notpeelz
Copy link

notpeelz commented Apr 3, 2018

Webpack issue here webpack/webpack#7300


I tried using the "Extracting all CSS in a single file" configuration from the README.
It works fine for the most part, except that the className mappings (created by css-loader ) are now loaded in a new js file.

image

I'm not sure if this is a limitation of MCEP or a side-effect of the new webpack splitChunks feature.
Is there any way to have the css mapping modules merged into their parent chunks?

Possibly related to #41

@notpeelz notpeelz changed the title Single-file configuration emits JS assets in their own chunk group Single-file configuration emits JS assets in its own chunk group Apr 3, 2018
@sokra
Copy link
Member

sokra commented Apr 4, 2018

limitation of the splitChunks feature. It may need a type filter.

You should be able to workaround it by passing a function to test:

test: module => module.nameForCondition &&
  /\.css$/.test(module.nameForCondition()) &&
  !/^javascript/.test(module.type)

@notpeelz
Copy link
Author

notpeelz commented Apr 5, 2018

That test rule doesn't get rid of the js file but it shrinks it to 61 bytes:

(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);

Any idea why it doesn't get rid of the JS file entirely?

@yyx990803
Copy link

I also ran into this same problem - the 61 byte chunk is small but html-webpack-plugin will attempt to inject it into the HTML.

@notpeelz
Copy link
Author

notpeelz commented Apr 7, 2018

@yyx990803 that's expected. You can exclude the file by manually handling the asset injection (and filtering out JS style assets), but then the SPA doesn't load and fails silently (at least for me it does).

@yyx990803
Copy link

@louistakepillz yeah, I ended up with a temporary hack: prepending the content of the chunk to the main entry file.

@fmal
Copy link

fmal commented Apr 8, 2018

@louistakepillz i noticed that removing enforce: true results in no extra chunks being generated for css mappings, not sure if it has any negative impact though and why it's needed in the first place 😃

@notpeelz
Copy link
Author

notpeelz commented Apr 8, 2018

@fmal doesn't work for me. Can you share your config?

@ericcirone
Copy link

@fmal taking out enforce: true fixes everything for me as well.

@thecrypticace
Copy link

thecrypticace commented Apr 28, 2018

Removing enforce: true doesn't work for me because, while everything gets put into one CSS file:

  1. It is based on the bundle name not the split chunk name.
  2. None of the defined CSS chunks get split into separate files. They're all fed into the CSS file named after the entry.

@thecrypticace
Copy link

I'm looking at writing a plugin (as a proof-of-concept) that taps into compilation.hooks.beforeChunkAssets to attempt to remove the extra javascript chunks.

Would that be the right approach or would there be a better one?

@thecrypticace
Copy link

Sorry, to be clearer I'm doing that to get access to the chunk template to tap into template.hooks.renderManifest because that's where it appears the javascript file is being added.

Though I guess ideally there'd be a way to not even populate the file at all.

@alexander-akait
Copy link
Member

/cc @sokra

@thecrypticace
Copy link

I got a bit further with this. I was able to figure out how to remove the generated assets but unfortunately they still get added to the deferredModules list in the entry. I'm think it is because chunks exist for them and they get generated into multiple assets (one .css and one .js). I very well could be misunderstanding how that works, though.

I'm not sure how to go about fixing that.

Example of what I have done here: https://github.com/thecrypticace/webpack-css-chunks-test/blob/plugins/build/RemoveStyleScriptChunksPlugin.js

@adamscybot
Copy link

adamscybot commented May 8, 2018

For me, the app loads even without the tiny chunk included in the page. I'm not sure why though. It could be that I'm using runtimeChunk: 'single' but this is a guess.

@cottom
Copy link

cottom commented May 10, 2018

I just add npm script

"postbuild": "echo $'\n (window.webpackJsonp = window.webpackJsonp || []).push([[0], []]);' >> 'dist/index.js'" 

@lili21
Copy link

lili21 commented May 17, 2018

I'm using script-ext-html-webpack-plugin inline the style.js file. another temporary fix.

 new ScriptExtHtmlWebpackPlugin({
    inline: /styles.*\.js$/,
    defaultAttribute: 'defer',
})

@track0x1
Copy link

I'm also seeing this issue. Does anyone have a solution? This seems unsolved.

@lukepolo
Copy link

lukepolo commented May 23, 2018

It is unsolved, but I believe webpack/webpack#7300 is the real culprit. It is in the webpack 4.x milestone.

@jimblue
Copy link

jimblue commented Dec 5, 2018

Any update about this?

@lili21
Copy link

lili21 commented Jan 4, 2019

@louistakepillz yeah, I ended up with a temporary hack: prepending the content of the chunk to the main entry file.

@yyx990803 how did you exclude it from html-webpack-plugin ?

@nevace
Copy link

nevace commented Jan 7, 2019

Really hope this can be fixed soon. Meanwhile, here's another horrible postbuild script that may help someone:

const fs = require('fs');
const path = require('path');
const distDir = path.resolve(`DIST_DIR_HERE`);
let mainJs;
let stylesJs;

try {
	fs.readdirSync(distDir)
		.filter(file => file.startsWith('main') || file.startsWith('styles'))
		.forEach(file => {
			if (file.startsWith('main')) {
				mainJs = path.resolve(`${distDir}/${file}`);
			} else {
                stylesJs = fs.readFileSync(`${distDir}/${file}`);
			}
		});

	if (mainJs && stylesJs) {
		fs.appendFileSync(mainJs, stylesJs);
	}
} catch (e) {
	throw e;
}

@jimblue
Copy link

jimblue commented Jun 9, 2019

Any idea how to solve this? Can we try something...?

@ovaldi
Copy link

ovaldi commented Sep 25, 2019

I also ran into this same problem - the 61 byte chunk is small but html-webpack-plugin will attempt to inject it into the HTML.

+1

@lili21
Copy link

lili21 commented Sep 25, 2019

@jimblue You can try to inline it.

@kirschem
Copy link

Removing enforce: true also did the trick for me.

@garygreen
Copy link

I find it personally frustrating even after holding off upgrading to v4 for almost 2 years this issue still hasn't been fixed. It appears fixed now in v5, but there is no release date for that yet.

I can appreciate Webpack is a very complex beast, however splitting css from the bundle is not a unique scenario or edge case - it's a basic requirement for build tools. It does make you question given how complex Webpack has become even with basic requirements the maintainers are struggling to efficiently maintain it anymore. I'm sure I'm not the only one pondering on whether alternative build tools have the same fundamental problems.

In any case, many developers rely on webpack as a build tool in their applications so it would be great if there could be more transparency and assistance from the maintainers in finding solutions to these long-oustanding issues that many developers experience with Webpack rather than letting them drag on for years.

image

@alexander-akait
Copy link
Member

alexander-akait commented Feb 6, 2020

Already solved for webpack@5, we really have a lot of problems and little help from other developers, this does not mean that we do not see problems, it means that we do not have enough time, so we are happy for any help

@danieliser
Copy link

@evilebottnawi - Completely understand, but is that change something we can either put into a quick custom plugin for v4 or back fill to v4? I highly doubt that since v5 isn't even officially out yet that many of the plugins we are all using would be updated to be compatible out of the box currently.

That said I posted what I thought was a solution last night but couldn't work out how to prevent all the css modules from being added to deferredModules and loading the webpack JSONP async loading chunk in our bundle. That breaks our JS even though our CSS builds correctly.

Setting enforce: true on the splitChunks for our CSS files causes that to occur, setting it to false causes all CSS to be bundled into a single file named the same as you main bundle.

I'd like to enforce and prevent the async modules.

Where in the compilation could I clear out that list of deferredModules and I'd be able to code around this for now.

@duanbaosheng
Copy link

I also ran into this same problem - the 61 byte chunk is small but html-webpack-plugin will attempt to inject it into the HTML.

can you show the method ? thank you

@Mister-Hope
Copy link

emmm, 2 years passed 😅

@alexander-akait
Copy link
Member

Partial fixed webpack/webpack#7300 (comment) (for webpack@5), but need to be improved more on webpack side, closed here, nothing to do more

@danieliser
Copy link

@evilebottnawi technically not true, those of us who can't upgrade until our dependencies have done so are still stuck without a solution.

At least answer the question I last posed on how to complete the workarounds

I posted what I thought was a solution last night but couldn't work out how to prevent all the css modules from being added to deferredModules and loading the webpack JSONP async loading chunk in our bundle. That breaks our JS even though our CSS builds correctly.

Setting enforce: true on the splitChunks for our CSS files causes that to occur, setting it to false causes all CSS to be bundled into a single file named the same as you main bundle.

I'd like to enforce and prevent the async modules.

Where in the compilation could I clear out that list of deferredModules and I'd be able to code around this for now.

At least with that I could probably make a webpack4 compatible plugin to fix the issues until we can safely migrate to v5.

@moti-maestro
Copy link

I don't know if it helps, but when I remove the extension from the output - the file seems to compile as it should.

filename: 'format/[name]'

Then, once I configure it to be ".js", it's getting compiled empty.

filename: 'format/[name].js'

@MichaelDurfey
Copy link

I created a plugin that worked for us until the webpack 5 upgrade. If you can't upgrade to webpack 5, give this a shot: https://github.com/michaeldurfey/fix-style-emits-webpack-plugin

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

No branches or pull requests