How to support old browsers in NodeBB 3-4?
-
Hello! It's that time of the year where my forum becomes my hyperfixation again after months of stasis...
While I quite like NodeBB after a few months of hosting it, I'm finding out compatibility issues with very old browsers (from the initial HTML5 era) and even just relatively old ones (~2018-2019), that while I'm not really required to solve now, I will probably need to tackle sooner or later.
I'm coming to NodeBB from another forum platform, which being a Web 1.0 one worked literally anywhere assuming a simple enough HTML+CSS theme, since there was no mandatory client-side JavaScript.
Now, on NodeBB, there's no escape; at least with the Persona theme, which is the one I'm currently using (since it's the only one currently supported and working well with a classic UI+UX).
I do in fact like that JavaScript is required on NodeBB to do a number of actions, from registering to posting, since it prevents (for me) 100% of spam, but I don't like that (almost) nothing of it works on old browsers.I said, I like the Persona theme, so I don't really want to spend days and weeks rewriting a theme/frontend from scratch so that it has good compatibility from the start and works as well as that; I'm looking for more of a way to make the Persona theme retro-compatible.
Especially because other platforms let the user choose the frontend theme, but it seems like NodeBB doesn't allow this (not to be confused with skins), meaning a theme has to be set for all users/browsers, which means I can't just write an half-hassed frontend that works well enough on old browsers if it does badly on current ones.The issues with this matter actually are of 2 types:
- HTML+CSS incompatibilities, which happen on very old browsers (eg. Firefox I think 20 or lower, the new Nintendo 3DS browser, I'd guess Internet Explorer but I don't care about that, and even older Opera-based mobile browsers which I too don't really care, and the Kindle e-reader web browser). They make the site almost unreadable, because the layout is broken.
- JavaScript incompatibilities, which happen on browsers as "recent" as Firefox 68, which FIY is the latest Firefox version to be supported on Android 4.4. (The latest Chromium version supported on that is a bit of a higher version number, but the featureset is the same.) (Edit: even the latest versions of less popular but still maintained browsers, like Palemoon or Seamonkey or MyPal, have the FF68 featureset.) They make it impossible to open menus, create posts, react to posts, and the like.
Below you can see an example of how bad my board looks on a very old browser (Firefox 9), which while HTML5-compliant (I'm too faint of heart to even think about supporting HTML4 or WAP now, don't worry), doesn't support a lot of the CSS features apparently used in the theme.
So, the forum on there is technically browsable and readable, but not easy on the eyes (or on the hand that moves the cursor). Things are obviously even worse on small viewports, such as those of mobiles.I guess I could just attempt to write my own custom, simpler CSS rules for the entire site's layout, that would be compatible with these old browsers, but I'm not sure how to do so without breaking everything on modern devices: old browsers will just fail to apply the standard CSS and so use my rules, but newer ones will partially apply both sets (because inevitably there will be rules of mine which will not be overridden by Persona's ones, since they will be written differently).
As for the JavaScript, that's a bigger issue. I've tried injecting the core-js standard library polyfill into every HTML page the site serves (with an nginx text replacement rule), and added the following line to the
webpack.common.js
file, which in theory should compile the JavaScript down to ES1 standards and in practice it seem to do it (by looking at the compiled frontend file/assets/nodebb.min.js
, but not too closely) down to at least ES5... but, strangely enough, ES5-era browsers (like Firefox 68) still don't work properly and throw infinite kinds of errors in the console:module.exports = { .... target: ['web', 'es5'], .... }
Obviously this isn't an all-or-nothing matter, so any improvement that can be made, even if little, is really welcome, and so I ask for the support of other retrocompatibility fanatics! Is what I'm asking realistically possible? For context, I'm on the NodeBB 4 preview branch, but this all applies to the latest stable NodeBB 3 too.
(I've actually created my own workaround already for posting to the board from old browsers, by using my own fork of the RSS plugin as a bridge, but reading is a still a problem, and in general I would like an integrated solution to the problem instead of external shenanigans.)
-
I may be talking out of my a$$ here, but maybe a roller coaster ride for a second. What if at the beginning of the template you have something like this:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Really Cool Website</title> <link id="theme" rel="stylesheet" href="modern-theme.css"> <script> // Function to detect browser version (This is the fun part) function detectBrowser() { const userAgent = navigator.userAgent; let browser = 'modern'; // Check for outdated browsers (e.g., Chrome < 70, Firefox < 60) if (/Chrome\/(\d+)/.test(userAgent)) { const version = parseInt(userAgent.match(/Chrome\/(\d+)/)[1], 10); if (version < 70) browser = 'old'; } else if (/Firefox\/(\d+)/.test(userAgent)) { const version = parseInt(userAgent.match(/Firefox\/(\d+)/)[1], 10); if (version < 60) browser = 'old'; } else if (/MSIE|Trident/.test(userAgent)) { browser = 'old'; // Treat IE as old } return browser; } // Apply theme based on browser detection document.addEventListener('DOMContentLoaded', () => { const browser = detectBrowser(); const themeLink = document.getElementById('theme'); if (browser === 'old') { themeLink.href = 'old-theme.css'; } }); </script> </head> <body> <h1>Welcome to the Really Cool Website!</h1> <p>This page changes its theme based on your browser version.</p> </body> </html>
Yes that is in HTML, and the browser would have to be able to use JavaScript, although there is an alternative by using NodeJS, or other Reactive JS from the server-side. Which wouldn't require the browser to need JavaScript. (Yes I am saying JavaScript can detect people who don't have JavaScript).
This is something I did about 5 years ago:
const express = require('express'); const app = express(); const path = require('path'); // Middleware to detect browser app.use((req, res, next) => { const userAgent = req.headers['user-agent']; // Detect outdated browsers (e.g., Chrome < 70, Firefox < 60, or IE) if (/Chrome\/[0-6][0-9]/.test(userAgent) || /Firefox\/[0-5][0-9]/.test(userAgent) || /MSIE|Trident/.test(userAgent)) { req.theme = 'old-theme.css'; } else { req.theme = 'modern-theme.css'; } next(); }); // Serve the index page app.get('/', (req, res) => { const theme = req.theme; res.send(` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Theme Selector</title> <link rel="stylesheet" href="/themes/${theme}"> </head> <body> <h1>Welcome to the Theme Selector</h1> <p>This page changes its theme based on your browser version.</p> </body> </html> `); }); // Serve CSS files app.use('/themes', express.static(path.join(__dirname, 'themes'))); // Start the server const PORT = 3000; app.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`); });
I think somewhere I did it in a library but I cannot find it. If it is something worth looking into I can try to dig it up.
This will allow you to have different versions of your Theme for different versions of browsers.
Ultimately wouldn't it be upon the User to build a Theme? (Although I do agree, there should be something someone could use for this built it)
-
@codenamejessica This does make sense... and doesn't seem particularly hard to implement, although I will need to do a bit of research to support stranger older browsers (like the Nintendo 3DS one, which has its own User Agent string). It's just CSS tweaks, but it's something, so I will at least try this approach if the CSS loading problems I fear about will come true. Thank you for the idea!
Now the problem will be writing the CSS, but after this last hour of research it looks like I might have actually already done part of it! With https://github.com/MadLittleMods/postcss-css-variables I was able to compile part of the CSS to avoid
--var
style variables, which are one of the pain points of retrocompatibility, and indeed the site is already looking much better on dinosaur navigators (new Nintendo 3DS in the pictures below).
Sadly this appears to completely eliminate some CSS rules, so there are quite definitely things to tweak (for example, the profile picture icons are too big in topic listings)... -
@bboctt NICE! I remember those days, I was developing when we needed separate CSS for Internet Explorer, Firefox, Safari, and NetScape. It was very trying times. Once HTML5 and CSS3 came out, things got way easier. I promise I do not envy your task at hand.
-
@codenamejessica yes, when Microsoft insisted that Internet Exploder was the future and had different CSS standards to every other browser that followed CSS3 and earlier.
I too as a developer had to suffer this for years, along with shim files...
-
@bboctt oh lord!!
The ever-lasting battle between compatibility and adoption of new features.
At the end of the day, supporting older browsers gives us enough developer friction as to become a no-go. That's not to mean that it isn't important, but unfortunately that the market share isn't there for us to spend a significant amount of time on it.
But let's say... if a big bank came to us and said "This forum needs to work on IE11!!", and was going to spend the dollars to get the software there, then that is a different story.
On the upside, though, there are a couple small things we can try to address. The site's client-side js shouldn't immediately crash... stuff should work. It may be worth investing some time into getting the baseline functionality working, if it isn't already.