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

Parcel 2: Bundled CSS is imported at the top of <head> instead of being last #4882

Open
Cristy94 opened this issue Jul 12, 2020 · 13 comments
Open

Comments

@Cristy94
Copy link

Cristy94 commented Jul 12, 2020

🐛 bug report

If you add a <style> tag in the head, the CSS bundle will be imported before everything instead of being added as a last child in <head>.

Previous discussion: #4820

🤔 Expected Behavior

Bundled CSS is always added as last child in <head>.

<head>
	<link rel="stylesheet" href="https://www.example.com/some.css" />
        <style>html,body {background: #e9eaed;}</style> 
        <link rel="stylesheet" href="/bundle.22506e2f.css">
</head>

😯 Current Behavior

Bundled CSS is imported as first child.
The bundled CSS is no longer at the end of the <head> tag, so some.css would overwrite it.

<head><link rel="stylesheet" href="/bundle.22506e2f.css">
	<link rel="stylesheet" href="https://www.example.com/some.css" />
        <style>html,body {background: #e9eaed;}</style>
</head>

💁 Possible Solution

Not sure why this happens, maybe it tries to add the bundle before the inline styles, which might be ok, but it shouldn't add it before all the other nodes in head.

🔦 Context

I can't overwrite library CSS as the bundled stylesheet is imported before those extenral CSS files.

💻 Code Sample

🌍 Your Environment

Software Version(s)
Parcel 2.0.0-nightly.286
@mischnic
Copy link
Member

What do the input HTML/JS file(s) look like?

@Cristy94
Copy link
Author

Cristy94 commented Jul 12, 2020

Actually, I think it's just having the index.js imported in the body instead of the head:

index.html:

<html>
<head>
    <link rel="stylesheet" href="https://www.example.com/some.css" />
</head>
<body>
    <h1>Hey</h1>
    <script src="index.js"></script>
</body>
</html>

index.js

import "/styles/test.css";

test.css

body {
    background: red;
}

Output:

<html>
<head><link rel="stylesheet" href="/index.22506e2f.css">
	<link rel="stylesheet" href="https://www.example.com/some.css">
</head>
<body>
    <h1>Hey</h1>
    <script src="/index.2c77b0be.js"></script>
</body>
</html>

Not sure why sometimes the <style> tag triggered this problem, but now it seems that having the JS entry point in body is the problem.

@Cristy94 Cristy94 changed the title Parcel 2: Adding an inline <style> tag moves the bundled CSS to the top of <head> Parcel 2: Bundled CSS is imported at the top of <head> instead of being last Jul 12, 2020
@Cristy94

This comment has been minimized.

@mischnic

This comment has been minimized.

@Cristy94
Copy link
Author

Can you confirm that the example above reproduces the issue on your machine?

@mischnic
Copy link
Member

Yes

Your example

<html>
	<head>
		<link rel="stylesheet" href="https://www.example.com/some.css" />
	</head>
	<body>
		<h1>Hey</h1>
		<script src="index.js"></script>
	</body>
</html>

shoud behave like

<html>
	<head>
		<link rel="stylesheet" href="https://www.example.com/some.css" />
		<script src="index.js"></script>
	</head>
	<body>
		<h1>Hey</h1>
	</body>
</html>

which already correctly inserts the link after the existing one:

<html>
	<head>
		<link rel="stylesheet" href="https://www.example.com/some.css" />
		<link rel="stylesheet" href="/index.2ccae8b1.css" />
		<script src="/index.b1eda6b3.js"></script>
	</head>
	<body>
		<h1>Hey</h1>
	</body>
</html>

@Cristy94
Copy link
Author

Any progress on this? The order of CSS imports is really important.

@euljr
Copy link

euljr commented Jun 28, 2021

I have the same issue and I think I found the reason for this to happen.

return doctypeIndex ? doctypeIndex + 1 : 0;

The function findBundleInsertIndex defaults to the first position when it can't find neither the doctype (which doesn't exists inside the head tag) nor a non-metadata tag.

By changing the line to fallback to the last position should fix the issue, something like:

  return doctypeIndex ? doctypeIndex + 1 : content.length;

What do you think? I can open a PR but I would need help to figure out if this can have a negative impact somewhere else.

@Cristy94
Copy link
Author

Cristy94 commented Jun 30, 2021

nor a non-metadata tag

Are you saying that I can somehow force the bundled CSS to be added after a specific tag (before the fix is implemented)?
A fix would be greatly appreciated as I still have the same issue for a year, I can't overwrite material-icons font size in my SASS files.

@euljr
Copy link

euljr commented Jun 30, 2021

Are you saying that I can somehow force the bundled CSS to be added after a specific tag (before the fix is implemented)?

It's not ideal but, right now if you add a <span></span> inside the <head> in your main html file, the link tag will be inserted before it.

The result will be something like:

<head>
	<link rel="stylesheet" href="https://www.example.com/some.css" />
        <style>html,body {background: #e9eaed;}</style> 
        <link rel="stylesheet" href="/bundle.22506e2f.css"> <!-- HERE -->
        <span></span>
</head>

Edit.: Not just span, but any tag other than base, link, meta, noscript, style, template and title

@Cristy94
Copy link
Author

Cristy94 commented Jul 2, 2021

So adding an empty <script> should be both valid and maintain the order. I will test it, thanks!

@euljr
Copy link

euljr commented Jul 2, 2021

So adding an empty <script> should be both valid and maintain the order.

Absolutely! I didn't notice that the <script> was commented when skimming.

I'll try to open a PR in the next few days, still haven't got the time just yet.

@mischnic
Copy link
Member

mischnic commented Jul 2, 2021

A PR would be great! Here are the related test cases we currently have. I remember adding the last two tests listed here when I added the doctypeIndex-related logic, so duplicating and modifying one of them should work.

it('should insert sibling bundles before body element if no HEAD', async function() {

it('should insert sibling bundles after doctype if no html', async function() {

it('should insert sibling bundles at correct location in tree when optional elements are absent', async function() {

it('inserts sibling bundles into html in the correct order (no head)', async function() {

it('inserts sibling bundles into html in the correct order (head)', async function() {

PSanetra added a commit to codecentric/single-page-application-server that referenced this issue Mar 1, 2024
This avoids issues with Parcel as Parcel places style sheet links always at the top of the head section. See parcel-bundler/parcel#4882

Fixes #11
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

3 participants