-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Support browserslist #121
Comments
It looks like that API combined with perhaps something like mdn-browser-compat-data could be useful. That would let you use browserslist to get a list of browsers and then you could use browser compatibility data to pick the corresponding value for the I think something like this is better done as another package outside of esbuild core. That way people that don't need this don't have to pay the cost of it (the feature database is rather large). |
I was curious about this so I gave it a shot. Here's what I came up with:
Given an esbuild language target (i.e. the esbuild Caveats:
Here is the code to generate this table (click to expand)const mdn = require('mdn-browser-compat-data')
const features = {
// Required features
class: [mdn.javascript.statements.class.__compat, -Infinity],
spread_in_arrays: [mdn.javascript.operators.spread.spread_in_arrays.__compat, -Infinity],
arrow_functions: [mdn.javascript.functions.arrow_functions.__compat, -Infinity],
default_parameters: [mdn.javascript.functions.default_parameters.__compat, -Infinity],
method_definitions: [mdn.javascript.functions.method_definitions.__compat, -Infinity],
rest_parameters: [mdn.javascript.functions.rest_parameters.__compat, -Infinity],
get: [mdn.javascript.functions.get.__compat, -Infinity],
set: [mdn.javascript.functions.set.__compat, -Infinity],
yield: [mdn.javascript.operators.yield.__compat, -Infinity],
yield_star: [mdn.javascript.operators.yield_star.__compat, -Infinity],
template_literals: [mdn.javascript.grammar.template_literals.__compat, -Infinity],
// Features that can be transformed
optional_catch_binding: [mdn.javascript.statements.try_catch.optional_catch_binding.__compat, 2018],
public_class_fields: [mdn.javascript.classes.public_class_fields.__compat, 2020],
static_class_fields: [mdn.javascript.classes.static_class_fields.__compat, 2020],
exponentiation: [mdn.javascript.operators.exponentiation.__compat, 2015],
exponentiation_assignment: [mdn.javascript.operators.exponentiation_assignment.__compat, 2015],
object_spread: [mdn.javascript.operators.spread.spread_in_object_literals.__compat, 2017],
nullish_coalescing: [mdn.javascript.operators.nullish_coalescing.__compat, 2019],
// Features that can't be transformed
async_function: [mdn.javascript.statements.async_function.__compat, 2016],
private_class_fields: [mdn.javascript.classes.private_class_fields.__compat, 2020],
}
function queryTargetForBrowsers(browsers) {
let target = 2020 // Always need to transform unreleased Stage 3 features
for (const feature in features) {
const [__compat, lowerTarget] = features[feature]
for (const browser in browsers) {
const info = __compat.support[browser]
const versionAdded = (info[0] || info).version_added
const requestedVersion = browsers[browser]
if (+requestedVersion < +versionAdded && lowerTarget < target)
target = lowerTarget
}
}
return target
}
function queryBrowsersForTarget(target) {
const browsers = {}
for (const browser of ['chrome', 'safari', 'firefox', 'edge'])
for (const version of Object.keys(mdn.browsers[browser].releases).sort((a, b) => +a - +b))
if (queryTargetForBrowsers({ [browser]: version }) >= target) {
browsers[browser] = version
break
}
return browsers
}
const table = {}
for (let target = 2015; target <= 2020; target++) {
table[`es${target}`] = queryBrowsersForTarget(target)
}
console.table(table) |
I have an update on this. I just added the ability to add additional targets to the |
I'm going to close this since the target option is the intended way to configure this in esbuild. As I said above, actually including the browserslist database inside esbuild itself is outside the scope of the project and is best done in another package instead. |
The nice thing about |
I wrote a small plugin here: https://github.com/nihalgonsalves/esbuild-plugin-browserslist |
I have Creaetd a Simple library getTarget.js ---> FIle 'use strict'
const browserslist = require('browserslist')
function getBuildTargets(targ) {
const SUPPORTED_BUILD_TARGETS = targ !== 'default' ?
targ :
[
'es',
'chrome',
'edge',
'firefox',
'ios',
'node',
'safari'
]
const getEveryTar = browserslist().reverse()
const sep = ' '
const targets = []
let singleTar = ''
let i = 0
for (const tar of getEveryTar) {
for (const selTar of SUPPORTED_BUILD_TARGETS) {
if (tar.startsWith(selTar + sep) && !singleTar.startsWith(selTar)) {
i++
singleTar = tar.replace(sep, '')
targets[i] = singleTar
}
}
}
return targets.filter(Boolean)
}
module.exports.getTarget = targ => {
return getBuildTargets(targ)
} esbuild.config.js ---> File 'use strict'
const esbuild = require('esbuild')
const { getTarget } = require('./getTarget')
esbuild.build({
entryPoints: ['build/ts/AdminLTE.ts'],
bundle: true,
sourcemap: true,
target: getTarget(['es', 'chrome', 'edge', 'firefox', 'ios', 'safari']), // another option as `getTarget('default')`
outfile: 'dist/js/adminlte.js'
}).catch(error => console.error(error)) |
I've put https://github.com/marcofugaro/browserslist-to-esbuild |
Here’s a “poor man’s”/lightweight way to support ~3 years of old browsers that I’m experimenting with, that does not rely on browserslist. Sharing in case it helps someone. // When this was written, the idea here was to support ~3 years of old browsers.
// If you don’t use the `target` option, esbuild will basically assume all the
// latest features are supported, and might even “upgrade” your code to newer
// syntax if it’s shorter as a form of minification. So it’s important to lock
// this down somewhat, so that we don’t update esbuild and accidentally make
// many customers unable to use the site.
const thisYear = new Date().getFullYear();
const maxYearsToSupport = 3;
// Safari for iOS 13 was released in September 2019. Since then, Apple has released
// a new major version in the middle of September every year. However, it’s
// reasonable that it takes a few months for people to upgrade, so we remove 1
// to not count the new version until January.
// https://en.wikipedia.org/wiki/Safari_version_history
const latestIosVersion = thisYear - 2019 + 13 - 1;
const TARGET = [
// For JavaScript you can specify an ECMAScript standard. A new standard is
// usually set during spring, and becomes official around June. Removing 1
// gives a year for browsers to implement the new features (but some are
// already supported before the specification comes out).
`es${thisYear - maxYearsToSupport - 1}`,
// For CSS one has to specify browser versions. Note that this affects JS too.
// Safari has the slowest release cycle so it felt the easiest to use that.
`ios${latestIosVersion - maxYearsToSupport}`,
// If the assumptions made in the above calculations don’t hold in the future,
// feel free to change this to whatever makes sense then.
];
esbuild.build({
// ...
target: TARGET,
}) |
process.env.NODE_ENV will be automatically set already based on minify https://esbuild.github.io/api/#platform and browserslist is ignored by esbuild evanw/esbuild#121
process.env.NODE_ENV will be automatically set already based on minify https://esbuild.github.io/api/#platform and browserslist is ignored by esbuild evanw/esbuild#121
process.env.NODE_ENV will be automatically set already based on minify https://esbuild.github.io/api/#platform and browserslist is ignored by esbuild evanw/esbuild#121
* Task: remove uneeded configs process.env.NODE_ENV will be automatically set already based on minify https://esbuild.github.io/api/#platform and browserslist is ignored by esbuild evanw/esbuild#121 * Task: remove postcss-hexrgba and its few usages * Task: remove unneded postcss import plugin as esbuild does it itself * Task: remove postcss autoprefixer * Revert "Revert "Task: remove unused babel.rc and jsconfig.json"" This reverts commit 3605abb. * Task: Fix css linting * Task: Fix js linting by using @typescript-eslint/parser instead of babel * Task: Fix omit prop
I think this lib will benefit a lot if It has support of industry standard way of detecting target JavaScript version, the browserslist. If you don't support tools like that I don't think your lib will draw enough attention.
Yes, esbuild can be used as intermediary step, but still I'll have to run Babel.
And you know, if project is small then compile speed is not the issue. So new projects don't have real reasons to prefer esbuild or esbuild-loader over webpack or rollup with Babel.
Compile speed is the issue for large codebases. But large codebases usually have to address wide audiences and need tooling to deliver code that will work everywhere. Their audience often includes people that use older browsers. Browserslist helps to address that a lot.
The text was updated successfully, but these errors were encountered: