corejs-upgrade-webpack-plugin
Version:
a webpack plugin that transforms core-js v2 paths to core-js v3 paths
138 lines (109 loc) • 4.2 kB
text/typescript
import { NormalModuleReplacementPlugin } from 'webpack';
import resolveFrom from 'resolve-from';
const rewriteAndPreservePrefix = (originalRequest: string, newPath: string, newModuleName = 'core-js') => {
const result = originalRequest.match(/(.*\/)core-js\/.*/);
const requestPrefix = result ? result[1] : '';
return `${requestPrefix}${newModuleName}/${newPath}`;
};
const rewriteRenamedModules = (path: string) => {
if (path === 'web.dom.iterable') {
return path.replace('web.dom.', 'web.dom-collections.')
}
return path;
}
export const rewriteCoreJsRequest = (originalRequest: string, lowerVersion = false) => {
if (!originalRequest) {
throw new Error('no originalRequest')
}
if (/core-js\/modules\/es(6|7)\.(.*)/.test(originalRequest)) {
const [,matchedVersion, matchedPath] = originalRequest.match(/core-js\/modules\/es(6|7)\.(.*)/);
const version = matchedVersion;
const path = rewriteRenamedModules(matchedPath);
if (version === '6' || lowerVersion) {
return rewriteAndPreservePrefix(originalRequest, `modules/es.${path}`);
}
if (version === '7') {
return rewriteAndPreservePrefix(originalRequest, `modules/esnext.${path}`);
}
}
if (/core-js(?:\/library)?\/fn\/(.*)/.test(originalRequest)) {
const [,matchedPath] = originalRequest.match(/core-js(?:\/library)?\/fn\/(.*)/);
const path = rewriteRenamedModules(matchedPath);
return rewriteAndPreservePrefix(originalRequest, `features/${path}`, 'core-js-pure');
}
if (/core-js\/es(5|6|7)(.*)/.test(originalRequest)) {
const [,matchedVersion, matchedPath] = originalRequest.match(/core-js\/es(5|6|7)(.*)?/);
const version = matchedVersion;
if (version === '5') {
return null;
}
if (version === '6' || lowerVersion) {
const asAModule = matchedPath.replace('.js', '');
const path = rewriteRenamedModules(asAModule);
return rewriteAndPreservePrefix(originalRequest, `es${path}`);
}
if (version === '7') {
return null;
}
}
if (/core-js\/(object)\/(.*)/.test(originalRequest)) {
const [,matchedPath] = originalRequest.match(/core-js\/(.*)?/);
const path = rewriteRenamedModules(matchedPath);
return rewriteAndPreservePrefix(originalRequest, `features/${path}`);
}
return originalRequest;
};
export interface Options {
resolveFrom: string | false | string[];
}
const defaultOptions = {
resolveFrom: false,
resolveBackup: false,
} as Options
export default function CoreJSUpgradeWebpackPlugin(options: Options) {
options = Object.assign({}, defaultOptions, options || {});
const resolvers = options.resolveFrom ? [].concat(options.resolveFrom).map(r => resolveFrom.bind(null, r)) : [];
return new NormalModuleReplacementPlugin(/core-js/, resource => {
const originalRequest = (resource.userRequest || resource.request) as string;
if (originalRequest.startsWith('./') || originalRequest.startsWith('../')) {
return;
}
if (originalRequest.match(/@babel\/runtime\/core-js/)) {
return;
}
try {
require.resolve(originalRequest, { paths: [resource.context] });
} catch (originalError) {
let error = true;
for (const resolve of resolvers) {
// attempt the core-js v2 from backup
if (error) {
try {
// eslint-disable-next-line no-param-reassign
resource.request = resolve(originalRequest);
error = false;
} catch (e) {}
}
// attempt to upgrade the path from core-js v2 to v3 from backup
if (error) {
try {
// eslint-disable-next-line no-param-reassign
resource.request = resolve(rewriteCoreJsRequest(originalRequest));
error = false;
} catch (e) {}
}
// attempt to downgrade the path from es7 to es6 from backup
if (error) {
try {
// eslint-disable-next-line no-param-reassign
resource.request = resolve(rewriteCoreJsRequest(originalRequest, true));
error = false;
} catch (e) {}
}
}
if (error) {
throw originalError;
}
}
});
};