如何創建 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:有用的鏈接和資源
