ECMAScript Module (ESM) support
Hi,
please add support for isomorphic-loader for module type projects (and hybrid variants).
We are currently facing two issues here:
(1) extendRequire does not work for ES modules. I played around writing our own ESM loader (only works on Node >=16.12):
import fs from 'fs'
import path from 'path'
import assert from 'assert'
const isomorphicLoaderConfig = JSON.parse(await fs.promises.readFile(path.join(process.cwd(), '.isomorphic-loader-config.json'), 'utf-8'))
assert.ok(isomorphicLoaderConfig?.assetsFile, 'please run "yarn build:staticResources" before running "yarn build:staticPages"')
const isomorphicAssets = JSON.parse(await fs.promises.readFile(isomorphicLoaderConfig.assetsFile, 'utf-8'))
const EXTENSIONS = ['.svg', '.jpg', '.png']
export async function resolve(specifier, context, defaultResolve) {
const { parentURL = null } = context
if (EXTENSIONS.some((ext) => specifier.endsWith(ext))) {
const url = parentURL ? new URL(specifier, parentURL).href : new URL(specifier).href
return { url }
}
return defaultResolve(specifier, context)
}
export async function load(url, context, defaultLoad) {
if (EXTENSIONS.some((ext) => url.endsWith(ext))) {
const assetPath = Object.keys(isomorphicAssets.marked).find((asset) => url.endsWith(asset))
if (assetPath) {
return {
format: 'json',
source: `"/our-prefix/${isomorphicAssets.marked[assetPath]}"`,
}
}
throw new Error(`Did not find asset ${url} in isomorphic-assets.json`)
}
return defaultLoad(url, context, defaultLoad)
}
A hybrid solution would mean to also support CJS dependencies which still use require.
(2) Maybe webpack 4 or TypeScript related, but the isomorphic-assets.json is missing the entries in marked that are direct dependencies of es module files. I checked the webpack-plugin.js and the top level modules list traversed by this snippet is not containing the relevant modules. Instead they can be found in nested modules:
const marked = stats.modules.reduce((acc, m) => {
sigIdx = m.identifier.indexOf(loaderSig);
if (sigIdx >= 0 && m.assets && m.assets.length > 0) {
const n = posixify(removeCwd(m.identifier.substr(sigIdx + loaderSig.length), true));
acc[n] = m.assets[m.assets.length - 1];
}
I do not know enough of the internals of webpack to propose a fix here - maybe it's already a bug in the ts-loader or file-loader...