feat(build)!: Introduce ESM entrypoints for chunks

Introduce an "import" conditional export for each of the chunk
entrypoints (blockly/core, blockly/blocks, blockly/javascript
etc.), and point these at wrappers created by build_tasks.js
that import the corresponding <chunk>_compressed.js file and
export its named exports.

BREAKING CHANGE:

Importing Blockly via

    import Blockly from 'blockly/core';

(and similarly for the other chunk entrypoints) has worked until
now because most build tools (including Webpack in particular)
fuilfil the request for the default export of a CJS module by
providing the module.exports object, rather than an
explicitly-named default export as they would for an ES module.

Since core/blockly.ts (the notional entrypoint for blockly/core)
does not provide a default export, the wrappers created by this
PR do not either.

Code of the above form will therefore break, and should be updated
to use a wildcard:

    import * as Blockly from 'blockly/core';
This commit is contained in:
Christopher Allen
2024-05-09 13:32:10 +01:00
parent 278006b5f8
commit 0b84d310c0
2 changed files with 28 additions and 3 deletions

View File

@@ -63,30 +63,37 @@
"./core": {
"types": "./core.d.ts",
"node": "./core-node.js",
"import": "./blockly.mjs",
"default": "./blockly_compressed.js"
},
"./blocks": {
"types": "./blocks.d.ts",
"import": "./blocks.mjs",
"default": "./blocks_compressed.js"
},
"./dart": {
"types": "./dart.d.ts",
"import": "./dart.mjs",
"default": "./dart_compressed.js"
},
"./lua": {
"types": "./lua.d.ts",
"import": "./lua.mjs",
"default": "./lua_compressed.js"
},
"./javascript": {
"types": "./javascript.d.ts",
"import": "./javascript.mjs",
"default": "./javascript_compressed.js"
},
"./php": {
"types": "./php.d.ts",
"import": "./php.mjs",
"default": "./php_compressed.js"
},
"./python": {
"types": "./python.d.ts",
"import": "./python.mjs",
"default": "./python_compressed.js"
},
"./msg/*": {

View File

@@ -565,7 +565,10 @@ function buildCompiled() {
}
/**
* This task builds the shims used by the playgrounds and tests to
* This task builds the ESM wrappers used by the chunk "import"
* entrypoints declared in package.json.
*
* Also builds the shims used by the playgrounds and tests to
* load Blockly in either compressed or uncompressed mode, creating
* build/blockly.loader.mjs, blocks.loader.mjs, javascript.loader.mjs,
* etc.
@@ -583,7 +586,23 @@ async function buildShims() {
// a shim to load the chunk either by importing the entrypoint
// module or by loading the compiled script.
await Promise.all(chunks.map(async (chunk) => {
// Get names of exports for chunk.
const entryPath = path.posix.join(TSC_OUTPUT_DIR_POSIX, chunk.entry);
const exportedNames = Object.keys(await import(`../../${entryPath}`));
// Write ESM wrapper.
const cjsPath = `./${chunk.name}${COMPILED_SUFFIX}.js`;
const wrapperPath = path.join(RELEASE_DIR, `${chunk.name}.mjs`);
const importName = chunk.scriptExport.replace(/.*\./, '');
await fsPromises.writeFile(wrapperPath,
`import ${importName} from '${cjsPath}';
export const {
${exportedNames.map((name) => ` ${name},`).join('\n')}
} = ${importName};
`);
// Write loading shim.
const scriptPath =
path.posix.join(RELEASE_DIR, `${chunk.name}${COMPILED_SUFFIX}.js`);
const shimPath = path.join(BUILD_DIR, `${chunk.name}.loader.mjs`);
@@ -591,14 +610,13 @@ async function buildShims() {
chunk.parent ?
`import ${quote(`./${chunk.parent.name}.loader.mjs`)};` :
'';
const exports = await import(`../../${entryPath}`);
await fsPromises.writeFile(shimPath,
`import {loadChunk} from '../tests/scripts/load.mjs';
${parentImport}
export const {
${Object.keys(exports).map((name) => ` ${name},`).join('\n')}
${exportedNames.map((name) => ` ${name},`).join('\n')}
} = await loadChunk(
${quote(entryPath)},
${quote(scriptPath)},