webpack icon indicating copy to clipboard operation
webpack copied to clipboard

experimental.css not support legacy browser?

Open hardfist opened this issue 3 years ago • 22 comments

Bug report

What is the current behavior? experimental.css may not supports legacy browser because it relys on css variable to load css chunk, I'm wondering whether it's by design

/******/ 		var loadCssChunkData = (target, link, chunkId) => {
/******/ 			var data, token = "", token2, exports = {}, exportsWithId = [], exportsWithDashes = [], i = 0, cc = 1;
/******/ 			try { if(!link) link = loadStylesheet(chunkId); data = link.sheet.cssRules; data = data[data.length - 1].style; } catch(e) { data = getComputedStyle(document.head); }
/******/ 			data = data.getPropertyValue("--webpack-" + uniqueName + "-" + chunkId);
/******/ 			if(!data) return [];
/******/ 			for(; cc; i++) {
/******/ 				cc = data.charCodeAt(i);
/******/ 				if(cc == 40) { token2 = token; token = ""; }
/******/ 				else if(cc == 41) { exports[token2.replace(/^_/, "")] = token.replace(/^_/, ""); token = ""; }
/******/ 				else if(cc == 47 || cc == 37) { token = token.replace(/^_/, ""); exports[token] = token; exportsWithId.push(token); if(cc == 37) exportsWithDashes.push(token); token = ""; }
/******/ 				else if(!cc || cc == 44) { token = token.replace(/^_/, ""); exportsWithId.forEach((x) => (exports[x] = uniqueName + "-" + token + "-" + exports[x])); exportsWithDashes.forEach((x) => (exports[x] = "--" + exports[x])); __webpack_require__.r(exports); target[token] = ((exports, module) => {
/******/ 					module.exports = exports;
/******/ 				}).bind(null, exports); token = ""; exports = {}; exportsWithId.length = 0; }
/******/ 				else if(cc == 92) { token += data[++i] }
/******/ 				else { token += data[i]; }
/******/ 			}
/******/ 			installedChunks[chunkId] = 0;
/******/ 		
/******/ 		}

If the current behavior is a bug, please provide the steps to reproduce.

What is the expected behavior?

Other relevant information: webpack version:
Node.js version: Operating System: Additional tools:

hardfist avatar Aug 15 '22 09:08 hardfist

Yes, do you need to support old browsers?

alexander-akait avatar Aug 15 '22 18:08 alexander-akait

yes, we still need to support old browsers like browser in android 4.4-

hardfist avatar Aug 16 '22 02:08 hardfist

oh, in thsi case css-loader can help here, new approach has better perf and logic, but requires new browsers

alexander-akait avatar Aug 16 '22 13:08 alexander-akait

This issue had no activity for at least three months.

It's subject to automatic issue closing if there is no activity in the next 15 days.

webpack-bot avatar Nov 16 '22 00:11 webpack-bot

bump

alexander-akait avatar Nov 16 '22 01:11 alexander-akait

Issue was closed because of inactivity.

If you think this is still a valid issue, please file a new issue with additional information.

webpack-bot avatar Mar 02 '23 18:03 webpack-bot

@TheLarkInn Maybe we should mark this in docs as non fixable and required modern browsers

alexander-akait avatar Mar 07 '23 17:03 alexander-akait

@TheLarkInn Maybe we should mark this in docs as non fixable and required modern browsers

I think this is very important, actually when I finish migrating my tools from css-loader to experiments.css and find the compatible problem I feel depressed

hardfist avatar Jun 08 '23 05:06 hardfist

@hardfist

I think this is very important, actually when I finish migrating my tools from css-loader to experiments.css and find the compatible problem I feel depressed

CSS will work on old browsers ("production"), only dev mode and HMR will not work on old browsers

alexander-akait avatar Jun 08 '23 16:06 alexander-akait

CSS will work on old browsers ("production"), only dev mode and HMR will not work on old browsers

glad to know this, because we do have lots of application users who need to use legacy browser(you know the old android machine), so rspack differs with webpack now in css implementation for sake of legacy browsers, so if webpack could support legacy browsers(even only in production), we can align to this webpack's behavior now.

hardfist avatar Jun 08 '23 22:06 hardfist

@hardfist I will add testcases to ensure it, but based on code it should work, let's look at our code, we try to use link.sheet.cssRules and if nothing we try to use getComputedStyle - https://developer.mozilla.org/ru/docs/Web/API/Window/getComputedStyle, but yeah it can be a problem for WebView Android v4.3, on theory we can try to use el.currentStyle and for ie8, there are two solutions

  • recommend to polyfill it
  • try to find another workaround, for very old browsers

But I think it is fine with recommend to polyfill it if workaround will be big or have a bad perf

alexander-akait avatar Jun 08 '23 23:06 alexander-akait

I did some research and fixes (I think we will fix it in multiple PRs, the first will be soon):

  • getComputedStyle works fine since IE 9 and on old androids https://caniuse.com/?search=getComputedStyle, I think we don't need to support IE8 :smile:
  • CSS custom variables has some problems - https://caniuse.com/css-variables, for IE and old android

So for the last we can:

  • Try to parse all links using cssText/currentScript and parse text on CSS variables using regexp, it will be slow
  • Use ajax and using regexp try to extract modules - will be very slow, I don't like it
  • Move some logic on HTML level, i.e. developer put <link rel="stylesheet" data-webpack="webpack:chunk-main" href="./main.css" data-webpack-modules="\.\/src\/foo\.css,\.\/src\/style\.css;"> (it can be done/automated using a plugin), webpack in runtime try to use getComputedStyle, if nothing was found we will try to get this meta tag and get the chunk name. But here is an limitation - it will work only for initial chunks... But we can use meta for async chunks. But it can bloat the source code of HTML page, especial for very big applications.

Our main problem is that we need to understand where and how to store modules which concated into chunk.

I am now downloading images of old systems to try different approaches. Maybe I can find some other approaches and solutions.

alexander-akait avatar Jun 19 '23 00:06 alexander-akait

Technically, of course, we can try to store all modules (for initial and async) inside JS runtime chunk, this will increase the size of runtime chunk. On the other hand, we can only do this when your don't have css variables support in your browserslist and run it as fallback if can't get value using getComputedStyle

alexander-akait avatar Jun 19 '23 00:06 alexander-akait

we can only do this when your don't have css variables support in your browserslist and run it as fallback if can't get value using getComputedStyle

I think this is reasonable.

Technically, of course, we can try to store all modules (for initial and async) inside JS runtime chunk

Do we really need to support legacy browser in this way?

I thought we just need to create facade .js files like this https://github.com/ICJR/rspack-repro/blob/525f0cb8c150307bda33f010adeda27d07b9303f/rspack-dist/something/else.js at https://github.com/web-infra-dev/rspack/issues/3608.

If I remember correctly, this is also how Webpack bundles CSS with targeting node.

hyf0 avatar Jun 28 '23 03:06 hyf0

we can only do this when your don't have css variables support in your browserslist

Let me try to describe the behaviors. @alexander-akait Please correct me if I'm wrong.

If the user set target: browserslist, the bundler would choose the correct way to bundle CSS based on .browserlistrc.

If the user set target: web, the bundler would choose the CSS variable way to bundle CSS.

hyf0 avatar Jun 28 '23 04:06 hyf0

bump

ScriptedAlchemy avatar Jul 19 '23 22:07 ScriptedAlchemy

@alexander-akait it seems it is not resolved can we reopen it

hardfist avatar Jan 13 '24 01:01 hardfist

@hardfist Yeah, can you describe which browsers do you want to support, or just any old browser?

alexander-akait avatar Jan 13 '24 12:01 alexander-akait

@hardfist Yeah, can you describe which browsers do you want to support, or just any old browser?

thanks, the lowest version we have to support is iOS 10 & android 5

hardfist avatar Jan 15 '24 08:01 hardfist

Can we store the css modules name mapping at JS chunk instead of css chunk, the downside is that it will increase the size of the JS chunk, use runtime module to register css modules after loading a chunk

JSerFeng avatar Apr 15 '24 03:04 JSerFeng

it will increase the size of the JS chunk

I think this is okay because the total size should be the same. Current strategy, when loading a chunk, total size is: js + (css + css meta) If put css meta in js chunk: total size: (js + css meta) + css

JSerFeng avatar Apr 15 '24 06:04 JSerFeng

We can try it and check it out

alexander-akait avatar Apr 16 '24 12:04 alexander-akait