PWA Blog Add-On enables you to benefit from a blog on a rich PWA storefront. 

In this article, you'll learn how to install PWA Blog on PWA Studio.

Do you want us to install the PWA Blog Add-On for you?

Let our technical engineers do it – check out our Installation Service.

Note: your code might be slightly different than in provided examples, because of different versions of PWA Studio.

Take the following steps to install Magento 2 PWA Add-On for Blog:

1. Make sure that you installed the latest version of Magefan Blog Extension (Base, Plus or Extra) and Magefan Blog GraphQL Extension.

2. Upload the src folder from the archive to your PWA Studio root directory.

3. Navigate to your PWA Studio root directory.

4. Add blog static route.

  •  Update local-intercept.js. Replace this line
function localIntercept() {}

with

function localIntercept(targets) {
    targets.of("@magento/venia-ui").routes.tap(routes => {
        routes.push({
            name: "Blog",
            pattern: "/blog",
            path: require.resolve("./src/lib/magefan/pwa-studio-blog-ui/src/components/Routes")
        });
        return routes;
    });
}

See file example (samples/local-intercept.js).

5. Create component directories.

mkdir -p src/components
mkdir -p src/components/App
mkdir -p src/components/Main
mkdir -p src/components/Adapter

6. Copy the following components.

cp node_modules/@magento/venia-ui/lib/components/App/app.js src/components/App
cp node_modules/@magento/venia-ui/lib/components/App/container.js src/components/App
cp node_modules/@magento/venia-ui/lib/components/Main/main.js src/components/Main
cp node_modules/@magento/venia-ui/lib/components/Adapter/adapter.js src/components/Adapter

7. Add blog core styles.

  • Update the components/Main/main.js. Add this line at the end of imports:
import blogPageClasses from './../../lib/magefan/pwa-studio-blog-ui/src/index.module.css';

and replace this line

<div className={pageClass}>{children}</div>

with

<div className={`${pageClass} ${blogPageClasses.blogPage}`}>{children}</div>

See file example (samples/components/Main/main.js).
8. Update import statements.

  • Update the relative imports in components/Main/main.js.
import { mergeClasses } from '@magento/venia-ui/lib/classify';
import Footer from '@magento/venia-ui/lib/components/Footer';
import Header from '@magento/venia-ui/lib/components/Header';
import defaultClasses from '@magento/venia-ui/lib/components/Main/main.css';

See file example (samples/components/Main/main.js).

  • Update the relative imports in components/App/app.js.
import globalCSS from '@magento/venia-ui/lib/index.css';
import { HeadProvider, Title } from '@magento/venia-ui/lib/components/Head';
import Main from '../Main';
import Mask from '@magento/venia-ui/lib/components/Mask';
import Navigation from '@magento/venia-ui/lib/components/Navigation';
import Routes from '@magento/venia-ui/lib/components/Routes';
import ToastContainer from '@magento/venia-ui/lib/components/ToastContainer';
import Icon from '@magento/venia-ui/lib/components/Icon';

See file example (samples/components/App/app.js).

  • Update the relative imports in components/App/container.js.
import { useErrorBoundary } from '@magento/venia-ui/lib/components/App/useErrorBoundary';

See file example (samples/components/App/container.js).

  • Update the relative imports in components/Adapter/adapter.js.
import { AppContextProvider } from '@magento/venia-ui/lib/components/App';
import App from '../App';

See file example (samples/components/Adapter/adapter.js).

  • Open your project's src/index.js file and update the import for the Adapter component to use your custom Adapter component.
import Adapter from './components/Adapter';

See file example (samples/src/index.js).

9. Export components

  • Create src/components/App/index.js file with the following content
export { default } from './container'
  • Create src/components/Main/index.js file with the following content
export { default } from './main'
  • Create src/components/Adapter/index.js file with the following content
export { default } from './adapter'

10. Overwrite/Extend Main component

    • In PWA Studio root directory create overwrite webpack plugin moduleOverrideWebpackPlugin.js with following code:
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;
            });
        });
    }
};
    • In PWA Studio root directory create overwrite mapping file componentOverrideMapping.js with following code:
module.exports = componentOverride = {
    [`@magento/venia-ui/lib/components/Main`]: 'src/components/Main',
};

11. Go to the src/lib/magefan/pwa-studio-blog-ui/ folder and run the following command using CLI:

npm install

12. Navigate to PWA Studio root directory then create a production build and run the server.

npm run build
npm start

Once you install the PWA blog, you can check the Blog Extension User Guide to start setting up your blog.