如何创建 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导入包:

“依赖”:{
"@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;
}
}结果:

我们的教程到此结束。 如果有任何令人困惑的部分,请随时向我们提出任何问题,如果您认为本教程有帮助,请不要忘记将其评为有帮助!
此外,如果您想尝试 Magento PWA Studio 扩展,我们提供免费和开源的附加模块,您可以将其安装在 Magento PWA Studio 网站之上。
阅读更多:
Magento PWA Studio:有用的链接和资源
