-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Publish Blockly as ES modules #7449
Comments
Are there plans for this to be solved in the next months? |
We anticipate publishing a public beta of Blocky v11 that will include ESM entry points early in 2024 Q1, probably in January. Caveats: not a promise, not necessarily in the first v11 beta, and no guarantees about when v11 (non-beta) will be published (though probably before the end of Q1, possibly as early as mid February.) |
Realized on Friday that this might be blocked by some monkey patches we did to get around circular dependencies. See original context doc [edit: this is internal and cannot be shared to non-googlers :/ ] as well. @cpcallen could you take a look and see whether this is a blocker or not? |
No, that's fine. Monkey patching like this is kind of gross, but |
I've created a new issue: #8170 cause this ESM modules are not usable in the browser |
This issue was closed prematurely. PR #8091 introduced ESM entrypoints, but we do not yet publish Blockly as (browser-ingestible) ES modules. State of Blockly packaging as of v11.0.0:
Options for further modernisation of the Blockly package:Status quo: UMD with node.js- and bundler-compatible ESM wrappersThis is the do-nothing option, sacrificing the possibility of
Separate CJS and ESM buildsWe could provide separate CJS and ESM builds of each of the entrypoints. The simplest approach would be to modify our build pipeline to (e.g.) create both This has the advantage that the The significant drawbacks of this approach are:
Make the ESM wrappers browser-compatible…via
|
Marked triage so remaining work can be prioritised appropriately. |
I would vote for the complete ESM switch. If someone needs CJS or old Code, it's part of the application to transpile, not of the library. |
Somewhat tangential to this bug, but as I'm not familiar with Monaco: can you explain what it is doing ("detection if it should load global fails") and how Blockly being published as ESM would fix that? |
Sure: here is a sample wich loads monaco and blockly. https://github.com/jogibear9988/blocklyEsmTest/blob/main/monaco.html |
I could fix this, if I wait until monaco is loaded, then delete the "require" and than start to load blockly.... But it's bad, sure also monaco should provide ESM modules. But it is bad that the modules do different thinks, depending on wich globals variables are set It this part wich breaks:
I prefer real ESM. There I know always what it does. It does not pollute any global namespace. |
Oh yes, I see what's going on. Deleting I'm going to describe this behaviour as "working as intended", though certainly Blockly being ESM-only would also fix your issue. (We've also discussed removing support for AMD in particular, even if we kept script + CJS support, since we have the impression no one uses it any more; it seems however that your example provides at least a partial counterexample.) |
Check for duplicates
Problem
At the moment much of our documentation and examples (including most of the code in the blockly-samples repository) load Blockly by doing
as if Blockly were published as ES modules—but in fact the
blockly
NPM package contains only UMD modules which are (in practice) eitherrequire()
ed as CJS modules or simply loaded as<script>
s.Certain JavaScript runtimes—notably node.js—can deal with this, allowing developers to load UMD modules (as CJS modules) using the
import
keyword, but no browser supports this. This means that none of the examples we publish can be run without some kind of bundler, such as webpack or the Closure Compiler, or other build step, to combine and/or convert the developer code and Blockly modules into a compatible form.Request
import
Blockly in a browser without needing a build step, by publishing Blockly as an ES module (or, more accurately, as one ES module for each chunk:blockly
,blocks
,javascript
etc.) Althoughimport … from 'blockly'
cannot work in a browser without an import map, it should be possible toimport * as Blockly from './path/to/blockly.js'
;` (or '…/blockly.mjs', depending on choices discussed below).<script>
and/or as a CJS module viarequire()
.Alternatives considered
The NPM format allows publication of hybrid ESM+CJS modules. This is done by having separate
"main":
and"module":
entries in the package'spackage.json
file, pointing at the CJS and MJS entry points for the package respectively. For subpackages such asblockly/blocks
there is an"exports":
directive supported by node.js and by webpack, but this is not part of the official NPMpackage.json
format.There are at least two possible approaches to how such hybrid packages work, however:
exports
its exports. This is roughly akin to what the loading shims introduced in PR refactor(tests): Introduce loading shims, use in playgrounds #7380 do when loading Blockly in compressed mode. This article explains why this approach might be preferred and details about how to implement it (along with much additional background information about the ESM vs. CJS situation).Additional context
Although the UMD format allows one to publish a single file that can be treated as a plain script, as an AMD module or as a CJS module, there is no way for a file to be simultaneously both a UMD module and also an ES module—at least, not if it has any exports, because the
export
keyword is only legal in an ES module, and it is not possible to export anything from an ESM without using theexport
keyword. This means that there must be at least two entry point files present (one for ESM and one for UMD) in any package if it is to support being loaded both withimport
andrequire()
.This 2ality article provides some additional (though partially outdated) information about different ways to structure a hybrid ESM+CJS NPM package.
Although we should continue to support loading Blockly as a CJS module for the time being—at minimum to provide a substantial transition period in which developers can move to using the ESM version—we may well wish to ultimately ship the
blockly
NPM as ESM-only. There may be some value in continuing to support CJS in the long term, but UMD's abilito to allow one to load Blockly via<script>
is largely unnecessary when all current browsers now support<script type="module"> import * as Blockly from './path/to/blockly.js';
.The text was updated successfully, but these errors were encountered: