PWA Studio Override Modules using Webpack compiler path mapping
![PWA Studio Override Modules using Webpack compiler path mapping](https://don-udugala.com/wp-content/uploads/2022/07/webpack-react-e1658014683466.png)
Last time I explained how to override PWA Studio modules using Official PWA Studio documentation.
Checkout my last video to find out another method to override modules.
You can find the original article about the webpack override plugin from here.
First let’s create a plugins folder in ./src and create moduleOverrideWebPack.js file and call it in the local-intercept.js
local-intercept.js
const moduleOverridePlugin = require('./src/plugins/moduleOverrideWebPack');
function localIntercept(targets) {
const componentOverrideMapping = {
'@magento/venia-ui/lib/components/Footer/footer.js': './src/components/Footer/footer.js',
'@magento/venia-ui/lib/components/Header/header.js': './src/components/Header/header.js',
'@magento/venia-ui/lib/components/Header/header.js': './src/components/Header/header.js',
'@magento/peregrine/lib/talons/MegaMenu/useMegaMenu.js': './src/lib/talons/MegaMenu/useMegaMenu.js',
};
targets.of('@magento/pwa-buildpack').transformUpward.tap(def => {
def.staticFromRoot.inline.body.file.template.inline =
'./public/{{ filename }}';
});
targets.of('@magento/pwa-buildpack').webpackCompiler.tap(compiler => {
new moduleOverridePlugin(componentOverrideMapping).apply(compiler);
});
}
module.exports = (targets) = localIntercept;
in local-intercept.js we are calling pwa-buildpack webpackCompiler hook.
You can find out more about webpack compiler hooks in webpack compiler-hooks document.
moduleOverrideWebPack plugin will map old path with new modified files.
moduleOverrideWebPack.js
const path = require('path');
const glob = require('glob');
module.exports = class NormalModuleOverridePlugin {
constructor(moduleOverrideMap) {
this.name = 'NormalModuleOverridePlugin';
this.moduleOverrideMap = moduleOverrideMap;
}
requireResolveIfCan(id, options = undefined) {
try {
return require.resolve(id, options);
} catch (e) {
return undefined;
}
}
resolveModulePath(context, request) {
const filePathWithoutExtension = path.resolve(context, request);
const files = glob.sync(`${filePathWithoutExtension}@(|.*)`);
if (files.length === 0) {
throw new Error(`There is no file '${filePathWithoutExtension}'`);
}
if (files.length > 1) {
throw new Error(
`There is more than one file '${filePathWithoutExtension}'`
);
}
return require.resolve(files[0]);
}
resolveModuleOverrideMap(context, map) {
return Object.keys(map).reduce(
(result, x) => ({
...result,
[require.resolve(x)]:
this.requireResolveIfCan(map[x]) ||
this.resolveModulePath(context, map[x]),
}),
{}
);
}
apply(compiler) {
if (Object.keys(this.moduleOverrideMap).length === 0) {
return;
}
const moduleMap = this.resolveModuleOverrideMap(
compiler.context,
this.moduleOverrideMap
);
compiler.hooks.normalModuleFactory.tap(this.name, (nmf) => {
nmf.hooks.beforeResolve.tap(this.name, (resolve) => {
if (!resolve) {
return;
}
const moduleToReplace = this.requireResolveIfCan(resolve.request, {
paths: [resolve.context],
});
if (moduleToReplace && moduleMap[moduleToReplace]) {
resolve.request = moduleMap[moduleToReplace];
}
return resolve;
});
});
}
};
const componentOverrideMapping = { '@magento/venia-ui/lib/components/Footer/footer.js': './src/components/Footer/footer.js', '@magento/venia-ui/lib/components/Header/header.js': './src/components/Header/header.js', '@magento/venia-ui/lib/components/Header/header.js': './src/components/Header/header.js', '@magento/peregrine/lib/talons/MegaMenu/useMegaMenu.js': './src/lib/talons/MegaMenu/useMegaMenu.js', };
Next make sure you will modify the path of the imports inside the new file.
For example in my src/components/Footer/footer.js, I have changed the path to footer.module.css since we don’t have footer.module.css file in our new Footer directory.
import defaultClasses from '@magento/venia-ui/lib/components/Footer/footer.module.css';
I have add the link to code base in github and youtube video explaining the process below.
To access code base :
github.com/theiconnz/pwastudio-override