如何创建 Magento PWA Studio 扩展

已发表: 2021-01-06

目录

通常,您希望直接在pwa-studio项目上进行更改,但是如果您想构建扩展,这种方法远非理想。 对于扩展,您希望能够轻松禁用它们,或者能够轻松地将多个扩展导入到项目中。

为此,我们可以在创建的项目中创建一个包,然后从JSON文件中导入回来。 幸运的是,在 Magento 维护者 Lars Roettig 发布的npm包的帮助下,这个过程为我们简化了:https://www.npmjs.com/package/@larsroettig/create-pwa-extension

在本教程中,我们将尝试使用这个包来创建 PWA Studio 扩展。

1. 安装 Magento PWA Studio

首先我们需要安装一个 PWA Studio 项目。 如果您在此处遵循我们的指南,这将相当容易:如何设置 Magento 2 PWA Studio

*注意:在问题步骤中,对于这个问题“在创建项目后使用 yarn 安装包依赖项”,您需要像我们的设置教程一样选择而不是是。

2.创建新路线

cd进入你的项目目录。

运行此命令:

 纱线创建@larsroettig/pwa-extension

它将询问有关扩展的更多信息:

同样,请记住在“创建项目后使用纱线安装包依赖项”的问题中选择

打开创建的目录。

打开创建的目录

我们现在可以看到intercept.js文件已经创建,它已经包含了overridemapping

现在让我们尝试在testextension/src/intercept.js中创建一个新路由

 /**
 * 扩展的自定义拦截文件
 * 默认情况下,您只能使用@magento/pwa-buildpack 的目标。
 *
 * 如果确实想扩展 @magento/peregrine 或 @magento/venia-ui
 * 你应该将它们添加到你的 package.json 的 peerDependencies
 *
 * 如果你想为 @magento/venia-ui 组件添加覆盖,你可以使用
 * moduleOverrideWebpackPlugin 和 componentOverrideMapping
 **/
module.exports = 目标 => {
    target.of('@magento/pwa-buildpack').specialFeatures.tap(flags => {
        /**
         * 我们需要激活 esModules 和 cssModules 以允许构建包加载我们的扩展
         * {@link https://magento.github.io/pwa-studio/pwa-buildpack/reference/configure-webpack/#special-flags}。
         */
        flags[targets.name] = { esModules: true, cssModules: true };
    });
    target.of('@magento/venia-ui').routes.tap(
        路线数组 => {
            routesArray.push({
                name: 'SimiCart 页面',
                模式:'/simicart',
                路径:'@simicart/testextension/src/components/page1'
            });

            返回路由数组;
        });
};

testextension/src/components/page1/index.js中为新路由创建组件:

 从“反应”导入反应;
从'@magento/venia-ui/lib/classify'导入{mergeClasses};
从'prop-types'导入{shape, string};
 
从'./index.css'导入defaultClasses;
 
常量 Page1 = 道具 => {
    常量类 = mergeClasses(defaultClasses, props.classes);
    返回 (<div className={classes.root}>SimiCart</div>);
}

Page1.propTypes = {
    类:形状({根:字符串})
};
Page1.defaultProps = {};
导出默认Page1;

修改package.json导入包:

修改 package.json 导入包
 “依赖”:{
    "@magento/pwa-buildpack": "~7.0.0",
    "@simicart/testextension": "链接:./@simicart/testextension"
  },

之后,安装并观察以检查新路由是否有效。

 纱线安装
纱表

3. 覆盖组件

在上一部分之后,这一部分将是关于覆盖项目的现有视图。

从上一步创建的项目中,我们在testextension/src/componentOverrideMapping.js中添加我们的覆盖:

 /**
 * 覆盖映射
 * 示例:[`@magento/venia-ui/lib/components/Main/main.js`]: './lib/components/Main/main.js'
 */
module.exports = componentOverride = {
    [`@magento/venia-ui/lib/components/Header/header.js`]: '@simicart/testextension/src/override/header.js'
};

然后将此覆盖代码放入require testextension/src/intercept.js

 /**
 * 扩展的自定义拦截文件
 * 默认情况下,您只能使用@magento/pwa-buildpack 的目标。
 *
 * 如果确实想扩展 @magento/peregrine 或 @magento/venia-ui
 * 你应该将它们添加到你的 package.json 的 peerDependencies
 *
 * 如果你想为 @magento/venia-ui 组件添加覆盖,你可以使用
 * moduleOverrideWebpackPlugin 和 componentOverrideMapping
 */
const moduleOverrideWebpackPlugin = require('./moduleOverrideWebpackPlugin');
const componentOverrideMapping = require('./componentOverrideMapping')

module.exports = 目标 => {
    target.of('@magento/pwa-buildpack').specialFeatures.tap(flags => {
        /**
         * 我们需要激活 esModules 和 cssModules 以允许构建包加载我们的扩展
         * {@link https://magento.github.io/pwa-studio/pwa-buildpack/reference/configure-webpack/#special-flags}。
         */
        flags[targets.name] = { esModules: true, cssModules: true };
    });

    console.log(targets.of('@magento/pwa-buildpack'));
    target.of('@magento/venia-ui').routes.tap(
        路线数组 => {
            routesArray.push({
                名称:'SimiCartPage',
                模式:'/simicart',
                路径:'@simicart/testextension/src/components/page1'
            });

            返回路由数组;
        });
    target.of('@magento/pwa-buildpack').webpackCompiler.tap(compiler => {
        new moduleOverrideWebpackPlugin(componentOverrideMapping).apply(compiler);
    })
};

然后,从venia-ui文件夹中,将header组件复制到我们将覆盖的新组件中。 然后在我们刚刚复制的标题中再添加一个视图:

 从'./simicartIcon'导入SimiCartIcon;
.
.
.
<SimiCartIcon />

testextension/src/override/header.js中的完整代码:

 从“反应”中导入反应,{悬念};
从'prop-types'导入{形状,字符串};

从'@magento/venia-ui/lib/components/Logo'导入徽标;
从'@magento/peregrine/lib/util/makeUrl'导入resourceUrl;
从'react-router-dom'导入{链接,路由};

从'@magento/venia-ui/lib/components/Header/accountTrigger'导入AccountTrigger;
从'@magento/venia-ui/lib/components/Header/cartTrigger'导入 CartTrigger;
从“@magento/venia-ui/lib/components/Header/navTrigger”导入 NavTrigger;
从“@magento/venia-ui/lib/components/Header/searchTrigger”导入 SearchTrigger;
从'@magento/venia-ui/lib/components/Header/onlineIndicator'导入 OnlineIndicator;
从'@magento/peregrine/lib/talons/Header/useHeader'导入 { useHeader };

从'@magento/venia-ui/lib/classify'导入{mergeClasses};
从'@magento/venia-ui/lib/components/Header/header.css'导入defaultClasses;
从'@magento/venia-ui/lib/components/PageLoadingIndicator'导入PageLoadingIndicator;
从'./simicartIcon'导入SimiCartIcon;

const SearchBar = React.lazy(() => import('@magento/venia-ui/lib/components/SearchBar'));

常量头 = 道具 => {
    常量 {
        处理搜索触发点击,
        已离线,
        在线,
        搜索打开,
        isPageLoading
    } = useHeader();

    常量类 = mergeClasses(defaultClasses, props.classes);
    常量 rootClass = searchOpen ? classes.open:classes.close;
     常量 searchBarFallback = (
        <div className={classes.searchFallback}>
            <div className={classes.input}>
                <div className={classes.loader} />
            </div>
        </div>
    );
    常量搜索栏 = 搜索打开? (
        <Suspense fallback={searchBarFallback}>
            <路线>
                <SearchBar isOpen={searchOpen} />
            </路线>
        </悬念>
    ) : 无效的;
    常量 pageLoadingIndicator = isPageLoading ? (
        <PageLoadingIndicator />
    ) : 无效的;
 
    返回 (
        <header className={rootClass}>
            <div className={classes.toolbar}>
                <div className={classes.primaryActions}>
                    <导航触发器 />
                </div>
                {pageLoadingIndicator}
                <在线指标
                    hasBeenOffline={hasBeenOffline}
                    isOnline={isOnline}
                />
                <链接到={resourceUrl('/')}>
                    <Logo classes={{ logo: classes.logo }} />
                </链接>
                <div className={classes.secondaryActions}>
                    <搜索触发器
                        主动={搜索打开}
                        onClick={handleSearchTriggerClick}
                    />
                    <帐户触发器 />
                    <SimiCartIcon />
                    <购物车触发器 />
                </div>
            </div>
            {搜索栏}
        </标题>
    );
};

Header.propTypes = {
    类:形状({
        关闭:字符串,
        标志:字符串,
        打开:字符串,
        主要操作:字符串,
        次要动作:字符串,
        工具栏:字符串
    })
};
 
导出默认标题;

让我们在testextension/src/override/SimiCartIcon.js中创建这个视图:

 从“反应”导入反应;
从'@magento/venia-ui/lib/components/Icon'导入图标;
从 'react-feather' 导入 { FastForward };
从'@magento/peregrine/lib/util/makeUrl'导入resourceUrl;
从 'react-router-dom' 导入 { useHistory };
从'prop-types'导入{形状,字符串};

从'./SimiCartIcon.css'导入defaultClasses;
导入 { FormattedMessage, useIntl } from 'react-intl';

常量 SimiCartIcon = 道具 => {
    常量类 = 默认类;
    常量 { formatMessage } = useIntl();
    常量历史 = useHistory();

    返回 (
        <按钮
            咏叹调标签={格式信息({
                id: `blog.bloglabel`,
                默认消息:'博客'
            })}
            类名={classes.root}
            onClick={() => history.push(resourceUrl('/simicart'))}
        >
            <图标 src={FastForward} />
            <span className={classes.label}>
                <FormattedMessage id={`博​​客`} />
            </span>
        </按钮>
    );
}
 
SimiCartIcon.propTypes = {
    类:形状({根:字符串})
};
SimiCartIcon.defaultProps = {};
导出默认 SimiCartIcon;

然后样式它:

 。根 {
    对齐项目:居中;
    光标:指针;
    显示:inline-flex;
    证明内容:中心;
    行高:1;
    指针事件:自动;
    文本对齐:居中;
    空白:nowrap;
    过渡属性:颜色;
    过渡持续时间:224ms;
    过渡时间函数:cubic-bezier(0, 0, 0.2, 1);
    高度:3rem;
    宽度:3rem;
}

。标签 {
    显示:无;;
}

@media(最小宽度:641px){
    。根 {
        宽度:自动;
    }
    。标签 {
        显示:初始;
        边距内联开始:0.25rem;
    }
}

结果:

PWA Studio 自定义扩展演示

我们的教程到此结束。 如果有任何令人困惑的部分,请随时向我们提出任何问题,如果您认为本教程有帮助,请不要忘记将其评为有帮助!

此外,如果您想尝试 Magento PWA Studio 扩展,我们提供免费和开源的附加模块,您可以将其安装在 Magento PWA Studio 网站之上。

Magento PWA Studio 页面构建器

阅读更多:

Magento PWA Studio:有用的链接和资源