62 lines
2.6 KiB
JavaScript
62 lines
2.6 KiB
JavaScript
/**
|
|
* Webpack loader that rewrites the `keyedReducer` named import of
|
|
* `@wordpress/data` to a local copy bundled with the polyfill.
|
|
*
|
|
* `@wordpress/notices` >= 5.45.0 imports `keyedReducer` from `@wordpress/data`
|
|
* (consolidated upstream in `@wordpress/data` 10.45.0; see
|
|
* WordPress/gutenberg#77364). The polyfill externalizes `@wordpress/data` to
|
|
* the runtime `window.wp.data` global so the notices store registers in the
|
|
* shared registry. On sites that still ship an older `@wordpress/data`
|
|
* (current WordPress Core), `window.wp.data.keyedReducer` is `undefined` and
|
|
* the bundle throws at load time.
|
|
*
|
|
* This loader leaves every other `@wordpress/data` named import untouched so
|
|
* those continue to be resolved against the runtime global. The DEP plugin's
|
|
* `externals` callback runs before module resolution, which means a
|
|
* `Rule.resolve.alias` mapping for `@wordpress/data` is bypassed for the
|
|
* externalized request. Rewriting the import in source — before webpack sees
|
|
* the request — is the only path that survives the externals pipeline.
|
|
*/
|
|
|
|
/* global __dirname */
|
|
|
|
const path = require( 'path' );
|
|
|
|
const LOCAL_PATH = path.resolve( __dirname, 'src/internal/keyed-reducer.js' );
|
|
|
|
/**
|
|
* Rewrites `import { keyedReducer } from '@wordpress/data'` (alone or
|
|
* combined with other named imports) so `keyedReducer` resolves to the local
|
|
* shim while every other name continues to resolve to `@wordpress/data`.
|
|
*
|
|
* Bails out without changes when the import does not include `keyedReducer`
|
|
* or when the import shape isn't a simple named-imports list (we don't try to
|
|
* be clever about renames or namespace imports — there are none in the
|
|
* affected upstream files, and a loud miss is preferable to a quiet rewrite).
|
|
*
|
|
* @param {string} source - Source code of the matched module.
|
|
* @return {string} Rewritten source.
|
|
*/
|
|
module.exports = function wpDataKeyedReducerLoader( source ) {
|
|
const importRegex = /import\s*\{\s*([^}]+?)\s*\}\s*from\s*(['"])@wordpress\/data\2\s*;?/g;
|
|
const localImport = `import { keyedReducer } from ${ JSON.stringify( LOCAL_PATH ) };`;
|
|
|
|
return source.replace( importRegex, ( match, namedList, quote ) => {
|
|
const names = namedList
|
|
.split( ',' )
|
|
.map( n => n.trim() )
|
|
.filter( Boolean );
|
|
if ( ! names.includes( 'keyedReducer' ) ) {
|
|
return match;
|
|
}
|
|
const remaining = names.filter( n => n !== 'keyedReducer' );
|
|
if ( remaining.length === 0 ) {
|
|
return localImport;
|
|
}
|
|
const remainingImport = `import { ${ remaining.join(
|
|
', '
|
|
) } } from ${ quote }@wordpress/data${ quote };`;
|
|
return `${ remainingImport } ${ localImport }`;
|
|
} );
|
|
};
|