Problem/Motivation

Internet Explorer is currently the only browser supported by Drupal which doesn't ship with scripting engine that conforms (at least for the most part) with ECMAScript 6. Drupal 10 will drop support for Internet Explorer 11: #3155358: [policy, no patch] Drop IE11 support from Drupal 10.0.x.

The current build tooling requires us to depend on handful of 3rd party dependencies, increasing the cost of maintenance. Requiring a build step, duplicates all JavaScript code, and also makes the contributor experience more complicated, requiring contributors to use additional tooling when working on issues modifying JavaScript.

There could be some reasons to keep the tooling because the way the build tool is set up at the moment, would allow us to utilize features from newer versions of the ECMAScript standard. The tooling reduces the likelihood of accidentally using syntax that isn't supported by all of the supported browsers.

Goals

  1. Remove a large number of JS dependencies by not needing most of babel toolchain
  2. Remove code duplication in the source
  3. Keep naming relevant, in D10 we have a .es6.js file that contains ES6 and a .js file that also contains ES6 code.
  4. Leave the parts that can be automated to the CI and do not require contributors to compile the resulting JS/CSS code

Proposed resolution

The es6 trick allowed us to use new features for old browsers, now the supported browsers caught up and we don't need this workaround anymore. We can rename all the .es6 files to .js and update all the toolchain we have to remove all the compile/checks steps for JS code.

Use tool like es-check to see if we are using any features not included in ES6 standard, and check browser support for the features not part of ES6 standard manually.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Comments

lauriii created an issue. See original summary.

lauriii’s picture

Version: 9.3.x-dev » 10.0.x-dev

Moving to the Drupal 10 queue.

chi’s picture

would allow us to utilize features from newer versions of the ECMAScript standard

Are there any vital features in the newer ES standards that we need right now?

nod_’s picture

It's more about enabling than needing at this point.

What it would allow us is to clean up a few things and reduce our dependency on a build step/build tools for core development like outlined in the IS.

droplet’s picture

A better bundler "strategy" is needed.

Technically, we never needing ES6 also. We've spent time rewriting the scripts instead of only using ES6 in new code. If we remove it now, I think we make a very stupid decision before.

I write everything freely and bundler takes care of the syntax, this is "needing".

and simplify the contributor experience by removing the additional step of compiling JavaScript.

I disagreed above. The whole contribution process is below 4 commands:

"build": "yarn build:css & yarn build:js & yarn build:jqueryui & yarn build:ckeditor5",
    "prettier": "prettier --write \"./**/*.es6.js\" \"./tests/Drupal/Nightwatch/**/*.js\" \"./modules/ckeditor5/js/ckeditor5_plugins/**/*.js\"",
    "spellcheck": "cspell",
   "lint:core-js": "node ./node_modules/eslint/bin/eslint.js .",

You need to run all 4 or more if you prepare a 100% good patch before testbot.

increasing the cost of maintenance

I only see the active maintained @babel project is used in CORE (or what I think that's essential), is it really increasing the cost of maintenance? And is the COST increased by 3rd dependencies or Drupal Policy, I think we need to evaluate it. eg. Should we build CKEDITOR5 or other 3rd parties in CORE.

Is it make sense if removing build process also remove "CKEDITOR5 build process in CORE"? It sounds odd to me.

Also, we need to foresee what we do in the future, not only based on the current state. At some point, we will chop code into small files and use import, like below:
https://github.com/twbs/bootstrap/blob/main/js/src/button.js#L8

Are you sure you wanna load 100 or 200 or even more scripts in the browser? What is the cost of import? (the cost is about loading time of multiple files & loading size, no treeshakes) We need to evaluate it now.

Furthermore, what if the 3rd parties we used don't provide an ESM version..etc?

xjm’s picture

Adding tags for the relevant signoffs for this decision.

I haven't checked with @catch specifically, but anything that means fewer dependencies to manage generally will make the release managers happier. ;)

catch’s picture

How does this fit in with #2258313: Add license information to aggregated assets, and the potential follow-up to that issue (which I can't find, but is probably around somewhere) to commit minified versions of core JavaScript?

nod_’s picture

I'm very much +1 for not doing compiling and limiting ourselves to features available in our supported browser list so we can send the source as-is (and possibly adding the type=module attribute to have older browser stay with the no-js version, contrib could implement the compilation and add a bunch of type=nomodule files for older browsers).

tl;dr: step 1: +1 for modern syntax without babel at the cost of filesize. step 2: smarter aggregator that does the minification (for core files first, then all files after the js label issue is solved).

Currently we do need 4 commands to prepare a good patch (or just 2 if we use ./core/scripts/dev/commit-code-check.sh) and removing the compiling will not remove the lint/spellcheck/prettier steps BUT it would be nice to not have 2 version of the same script in the source, and it is more straightforward for people who are not so familiar with core code.

One issue to solve is the aggregation, there are several problems:

  1. We're currently sending files without comments to the browsers, they're not quite minified but they are smaller than the source. For example drupal.es6.js is about 20kb and drupal.js is 8kb, many files in core are twice the size with comments.
  2. If we're using JS modules in core, modules are defined by a file, one file == one module, and there is no native option for declaring multiple modules within the same file. So the naive aggregation (only concatenation) we have will break down. We'll need to have a smarter aggregator if we are to use ES modules natively.

I've been thinking about how to do all this without adding a runtime dependency on nodejs for Drupal, and I think we could make a basic PHP version of an es6 bundler (it will not be fancy, no tree shaking, etc.) and basic minification based on https://github.com/mck89/peast (it's looks pretty well maintained, keeping up to date with js syntax and works on php 8.1). Not sure about the overhead, it'll probably need #1014086: Stampedes and cold cache performance issues with css/js aggregation for this to work properly.

At some point we might want to have a CSS parser too to solve things like #2936067: CSS aggregation fails on many variations of @import in a more robust way than putting 3 different regex together, or the still open #646246: Only move non-resolved @import rules to top of aggregate stylesheet when also at top in own stylesheet.

catch’s picture

On-the-fly minification definitely needs #1014086: Stampedes and cold cache performance issues with css/js aggregation, this is one of the reasons I worked on it in the first place. But had also given up on it because things were moving away from PHP minification (even ten years ago), but if https://github.com/mck89/peast is promising, that could be great!

nod_’s picture

Issue summary: View changes

updated the IS.

for #5 about bundler stategy I agree we need to think about it, and it is a different topic than babel and the build step for me, so should be in a followup I think.

I'd like to refocus a bit so for the build step we can rename all .es6.js files to .js and we're pretty much done as far as the build step is concerned. I don't think it means we made a stupid decision before, it just mean we implemented the workaround to use ES6 with legacy browsers in a very basic way and built tooling to support that. All of this is not necessary anymore since we can ship es6 code directly.

This issue could simply be named "rename all .es6.js files to .js"

nod_’s picture

StatusFileSize
new86.87 KB
new284.72 KB
new22.11 KB

Spent some time to get a bit more info about our packages. The various commands and tool available work on the whole node_modules directory, not just the stuff we declare in the package.json so spent some time writing some code to do just that.

In the file yarn.tree.txt, for each dependency declared in package.json there is the list of all dependencies (recursively, as declared in the yarn.lock file).

In the file yarn.shared.txt, there is a list of all the packages that are reused, which declared dependency it comes from, which version is installed and which version was required.

In the file yarn.unique.txt, there is a list of all the packages that are required by only one parent dependency.

It's a bit clearer the impact removing a dependency will have with this hopefully.

nod_’s picture

Title: Consider removing JavaScript build step » What to do with assets build step?
Category: Task » Plan
Issue summary: View changes
nod_’s picture

We just had a call with @lauriii, @justafish, and myself to talk about this topic, essentially we could have a solution for D10+ only, which is to rename all .es6.js files to .js and send them as-is. For postCss we would need to ensure that it's needed in D10+ and hopefully remove it since browsers can do a lot nowdays (similar to #8 step 1).

We talked about going ahead with the svelte version of the project browser in #3263443: Consider removing SvelteJS in favor of vanilla JavaScript which would put the topic back on the table, but for now we don't have a good solution.

xjm’s picture

Issue tags: +Drupal 10 beta blocker
catch’s picture

Given #3278415: Remove usages of the JavaScript ES6 build step, the build step itself, and associated dev dependencies can this be closed? Seems like the resolution is to remove the build step, and we have a viable approach for #3302755: On-the-fly JavaScript minification which was my only concern about removing it.

longwave’s picture

The IS suggests using es-check to ensure that we only use ES6 compatible code, should we add that as a postponed followup to #3278415: Remove usages of the JavaScript ES6 build step, the build step itself, and associated dev dependencies and then be done with this?

nod_’s picture

+1

catch’s picture

wim leers’s picture

wim leers’s picture

#3278415 is RTBC: #3278415-57: Remove usages of the JavaScript ES6 build step, the build step itself, and associated dev dependencies.

Per #15 … I think we can close this?

I think this only still needs the postponed follow-up that @longwave mentioned in #16?

nod_’s picture

yeah need the followup and we can close this

catch’s picture

longwave’s picture

Status: Active » Needs review
Issue tags: -Needs follow-up
wim leers’s picture

Status: Needs review » Fixed

Thanks! Linked relevant issues to that new issue.

This is done :)

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.