{foo.test}
-``` - -Browse to _/foo.html_ to see _"lorem ipsum"_ you have added to the redux store. - -### Update The Redux Store - -#### Created an Action - -To update the Redux store we first need to add a [redux action][]. - -Add the following files... - -_src/actions/foo/actions.js_ - -```javascript -import { createActions } from 'redux-actions'; - -const prefix = 'FOO'; -const actionTypes = [ - 'UPDATE_TEST' -]; - -export default createActions(...actionTypes, { prefix }); -``` - -_src/actions/foo/asyncActions.js_ - -```javascript -import actions from './actions'; - -export const updateTest = value => async dispatch => - dispatch(actions.updateTest(value)); -``` - -_src/actions/foo/index.js_ - -```javascript -export { default } from './actions'; -export * from './asyncActions'; -``` - -**NOTE:** PWA Studio uses: - -- [createActions][] to create multiple actions at once. -- [async actions][] which are useful when API responses update the redux store. - -#### Update the Reducer with the New Action - -Now that we have our redux action created add it to our reducer, -go to _src/reducers/foo.js_ and change the `import actions` statement to: - -```javascript -import actions from 'src/actions/foo'; -``` - -And in the `reducerMap` change `actions.toggleDrawer` to `actions.updateTest`. - -#### Create a component to update the Redux Store - -Next we'll create a new child component which will use the action above to update the redux store. - -_src/components/Foo/updateRedux.js_ - -```javascript -import React from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { PropTypes } from 'prop-types'; -import { updateTest } from 'src/actions/foo'; - -const updateRedux = props => { - const { test, updateTest } = props; - - return ( - - ); -} - -updateRedux.propTypes = { - test: PropTypes.string, - updateTest: PropTypes.func.isRequired -}; - -const mapDispatchToProps = dispatch => ({ - updateTest: (e) => dispatch(updateTest(e.target.value)) -}); - -export default compose( - connect( - null, - mapDispatchToProps - ) -)(updateRedux); -``` - -Import the above component to the _Foo.js_ Component. - -```javascript -import UpdateRedux from './updateRedux'; -``` - -And add it to the JSX: - -```jsx -The input below is interacting with Redux:
-{foo.test}
-``` - -Now test it by typing into the new input box while checking Redux dev tools to see the value in the Redux store update. - -![foo redux actions](./images/foo-redux-actions.gif) - -## Learn More - -- [Getting Started with Redux][] - -[Getting Started with Redux]: https://redux.js.org/introduction/getting-started -[Learn More]: #learn-more -[Redux DevTools]: https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd -[Venia storefront]: https://venia.magento.com/ -[handleActions]: https://redux-actions.js.org/api/handleaction -[switch statement]: https://redux.js.org/basics/reducers#handling-more-actions -[redux action]: https://redux.js.org/basics/actions -[createActions]: https://redux-actions.js.org/api/createaction -[async actions]: https://redux.js.org/advanced/async-actions#async-actions -[Redux middleware pattern]: https://redux.js.org/advanced/middleware/ -[redux store in devtools]: ./images/redux-store-screenshot.png -[foo in the redux store]: ./images/foo-in-the-redux-store.gif -[foo redux actions]: ./images/foo-redux-actions.gif diff --git a/pwa-devdocs/_drafts/pwa-studio-fundamentals/reuse-a-venia-component/index.md b/pwa-devdocs/_drafts/pwa-studio-fundamentals/reuse-a-venia-component/index.md deleted file mode 100644 index 4c1bdae946..0000000000 --- a/pwa-devdocs/_drafts/pwa-studio-fundamentals/reuse-a-venia-component/index.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Reuse a Venia Component ---- - -Here we'll quickly demonstrated how PWA Studio components can be easily reused. - -Import the CategoryList to the Foo component: - -```javascript -import CategoryList from '@magento/venia-ui/lib/components/CategoryList'; -``` - -Next add the following JSX. - -```jsx -Reuse of a the PWA Studio component to render a category list:
-- The Magento PWA Studio project is an open source GitHub project that welcomes community contributions and collaboration. -
-- If you have any questions, issues, or suggestions, please join the #pwa Slack channel at magentocommeng.slack.com. -
- -` and `author` nodes -- The **HTML** content from the `description` node -- The CSS **classes** from all three child nodes (``, `author`, and `description`) - -To retrieve these properties, you'll want to use a combination of [HTMLElement DOM properties][] along with our [utility functions][], as shown next in the example. - -### Example aggregator - -Here is the aggregator we use for the `ExampleQuote` component: - -```js -import { getAdvanced } from '../../utils'; - -export default (node, props) => { - - console.log(node); - - return { - quote: node.childNodes[0].textContent, - author: node.childNodes[1].textContent, - description: node.childNodes[2].innerHTML, - ...getAdvanced(node) - }; -}; -``` - -First we `import` the [utility functions][] we want to use. In our case, we know that our Quote content type provides end users with the Advanced form section. So we import the `getAdvanced()` function from `utils.js`. This function is a wrapper that just runs a number of other utility functions that can be used independently if these values are on different nodes: - -```js -export function getAdvanced(node) { - return { - ...getPadding(node), - ...getMargin(node), - ...getBorder(node), - ...getTextAlign(node), - ...getCssClasses(node), - ...getIsHidden(node) - }; -} -``` - -Then we use the `element` names from the content type HTML (color coded in green above) as our property key names: `quote`, `author`, and `description`. Naming your properties like this helps to identify where the data in the component comes from. - -Next, we use the `textContent` and `innerHTML` DOM properties to grab the text and html values from the appropriate `childNodes`. - -Finally, we use the `getAdvanced()` utility function to retrieve all the property values from the Advanced section of our content type's form and use the spread operator `(...)` to expand them into the current object. - -{: .bs-callout-info} -The Quote content type also has a form section called Background (from the `pagebuilder_base_form_with_background_attributes` form). This section of the form allows end users to enter all kinds of background attributes, such as images, colors, positions and so on. If your custom content uses the Background section, you should retrieve the those attributes using the `getBackgroundImages(node)` utility function. However, to keep things simple for our component, we decided not to pull these attributes from the HTML. - -### Retrieving data from different Appearances - -If your content type has different appearances, the HTML for each appearance will also differ. To handle these differences, we provide the `appearance` within the `props` argument so you can modify your queries in order to retrieve data from the correct node. - -For our Quote content type, we only have one appearance (the default); so we do not need to use it. However, the Row content type has three appearances, so it uses a conditional based on the `props.appearance` value to determine the correct node to use, as shown here: - -```js -// Targeting appearances in the Row aggregator - -export default (node, props) => { - // Determine which node holds the data for the appearance - const dataNode = - props.appearance === 'contained' ? node.childNodes[0] : node; - return { - minHeight: dataNode.style.minHeight ? dataNode.style.minHeight : null, - ... - }; -``` - -## Test the aggregator - -The best way to see the properties returned by your aggregator is using `console.log()`. For our Quote aggregator, we can do something like this: - -```js -import { getAdvanced, getCssClasses, getBackgroundImages } from '../../utils'; - -export default (node, props) => { - console.log(node); - - const propObject = { - quote: node.childNodes[0].textContent, - author: node.childNodes[1].textContent, - description: node.childNodes[2].innerHTML, - ...getAdvanced(node) - }; - - console.log(propObject); - return propObject; -}; -``` - -Adding `console.log(node)` at the beginning of your aggregator function, and at he end (`console.log(propObject)`), helps to show you the HTML you receive and the object you return. The property object returned from our aggregator looks like this: - -![Aggregator object console output](images/AggregatorObjectConsoleOutput.png) - -{: .bs-callout-info} -You will need to know the property `key-values` you are returning so that that you can assign them to corresponding properties in your component when you build it out. - -[utility functions]: <{% link pagebuilder/utility-functions/index.md %}> - -[HTMLElement DOM properties]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentOutput.png b/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentOutput.png deleted file mode 100644 index 813aba5fb5..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentOutput.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentOutput.svg b/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentOutput.svg deleted file mode 100644 index 4e8c130e71..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentOutput.svg +++ /dev/null @@ -1,88 +0,0 @@ - - \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentSteps.svg b/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentSteps.svg deleted file mode 100644 index 5086e6db8f..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentSteps.svg +++ /dev/null @@ -1,140 +0,0 @@ - - \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-component/index.md b/pwa-devdocs/src/pagebuilder/custom-components/add-component/index.md deleted file mode 100644 index c2a0358558..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-component/index.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -title: Add component ---- - -The purpose of a Page Builder component is to recreate a Page Builder content type (from your Magento instance) to display inside a PWA app. Developing this component is similar to developing other React components in PWA Studio. However, the properties defined within a Page Builder component are determined by the properties returned from your configuration aggregator. The following steps highlight how to put these properties to use in your component: - -![Add Component steps overview](images/AddComponentSteps.svg) - -## Step 1: Add local props and prop-types - -The first step is to declare local variables that match the names of the props being passed from your aggregator, for destructuring. For our `ExampleQuote`, we declare and assign these properties as follows: - -```js -const ExampleQuote = props => { - const { - quote, - author, - description, - textAlign, - border, - borderColor, - borderWidth, - borderRadius, - isHidden, - marginTop, - marginRight, - marginBottom, - marginLeft, - paddingTop, - paddingRight, - paddingBottom, - paddingLeft, - cssClasses - } = props; -``` - -With a destructuring assignment, our component takes a `props` object and copies its values to our local variables. All you need to do is make sure the names of your local variables exactly match the names of the `props` passed from your aggregator. As noted before, you can use `console.log(props)` at the top of your component to see the names of the `keys` being passed in on the props object. - -Along with defining your local variables, you need to add the comparable `prop-types` to define exactly what can be passed into your component. The `ExampleQuote` component defines the following `prop-types`: - -```js -import { arrayOf, string, bool } from 'prop-types'; - -ExampleQuote.propTypes = { - quote: string, - author: string, - description: string, - textAlign: string, - border: string, - borderColor: string, - borderWidth: string, - borderRadius: string, - isHidden: bool, - marginTop: string, - marginRight: string, - marginBottom: string, - marginLeft: string, - paddingTop: string, - paddingRight: string, - paddingBottom: string, - paddingLeft: string, - cssClasses: arrayOf(string) -}; -``` - -## Step 2: Add JSX markup - -Your JSX markup should recreate the HTML structure of your Page Builder content type and provide the slots for rendering its content and styles. For example, here is the markup needed to recreate the structure of our Quote content type and host the local content-related `props` values from our aggregator: - -```jsx -const toHTML = str => ({ __html: str }); - -return ( ---); -``` - -Because our `description` property value is HTML, we need to use React's [dangerouslySetInnerHTML][] and `__html` to render it out properly. - -## Step 3: Apply form styles - -To make it easy to apply all the inline styles from your content type to your Page Builder component, you can create a separate object that contains only the styles retrieved from the content type's form. These styles include those that are retrieved by [utility functions][] like `getAdvanced()` and `getBackgroundImages()`. - -For our component, we created an object called `formStyles` to group our form styles as shown here: - -```js -const formStyles = { - textAlign, - border, - borderColor, - borderWidth, - borderRadius, - isHidden, - marginTop, - marginRight, - marginBottom, - marginLeft, - paddingTop, - paddingRight, - paddingBottom, - paddingLeft -}; -``` - -These are the styles returned from the Advanced form section of our Quote content type (using `getAdvanced()`). When they are grouped together as shown, we can apply them all at once to our component, as follows: - -```jsx -return ( -{quote}-{author}- ---); -``` - -Now we need to apply the CSS classes we used to style the rest of our content type. - -## Step 4: Apply CSS classes - -Applying CSS classes to your component in PWA involves importing both your CSS stylesheet and a PWA Studio function called `mergeClasses`. This function does exactly what its name implies: it merges classes from different sources into a single variable you can use to add your classes to your JSX, using `className`. - -For our component, we import our component stylesheet and the `mergeClasses` function as follows: - -```js -import defaultClasses from './exampleQuote.css'; -import { mergeClasses } from '../../../../../classify'; - -``` - -We then merge the classes from our stylesheet with any classes passed in on the props and use a single variable (`classes`) to apply our consolidated classes to the correct nodes in the JSX: - -```jsx -const classes = mergeClasses(defaultClasses, props.classes); - -return ( -{quote}-{author}- ---); -``` - -Merging the `props.classes` ensures that our component can apply and override styles from other components. - -In the previous code block, we only used a single class, `classes.quote`, to style the quote in our component. However, our original class required two different classes (`.quote` and `.blue-quote`) for styling. As a best practice, you want to use the `composes` construct from [CSS Modules][] as much as possible. - -For example, in our `exampleQuote.css`, we composed each color quote class with the `.qoute` class as shown in the following snippet: - -```css -.quote { - display: block; - font-size: 1.4em; - margin: 1em 1em 0.3em 0.6em; - quotes: '\201C''\201D''\2018''\2019'; - text-decoration: none; - font-style: italic; - word-break: normal !important; - line-height: 1.25em; - padding: 0; - font-weight: 300; -} -.blackQuote { - composes: quote; - color: #333333; -} -.blueQuote { - composes: quote; - color: #007ab9; -} -... -``` - -This ensures that for each colored quote class, we also apply the `.quote` class. - -## Component output - -If you have followed along using the `ExampleQuote` component, you should see something like this displayed in the PWA Venia app: - -![Add Component output](images/AddComponentOutput.svg) - -[utility functions]: {% link pagebuilder/utility-functions/index.md %} -[css modules]: {%link technologies/basic-concepts/css-modules/index.md %} -[dangerouslysetinnerhtml]: https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/images/AddStylesheetCamelCase.png b/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/images/AddStylesheetCamelCase.png deleted file mode 100644 index 43aa61b8c0..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/images/AddStylesheetCamelCase.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/images/AddStylesheetSteps.svg b/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/images/AddStylesheetSteps.svg deleted file mode 100644 index 172f49dc95..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/images/AddStylesheetSteps.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/index.md b/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/index.md deleted file mode 100644 index 1e7449389e..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/index.md +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: Add stylesheet ---- - -Styling your Page Builder components is the same as styling any other component in PWA Studio. However, the CSS stylesheet for your component should define CSS classes that are comparable to the CSS classes you use on the frontend for original content type (`view/frontend/web/css/source/content-type/{quote}-{author}- -/_import.less`). The following steps highlight the tasks for setting up the CSS classes for your component: - -![Add Stylesheet steps](images/AddStylesheetSteps.svg) - -## Step 1: Add content type classes - -Start by adding the CSS classes from the frontend css of your content type. For our Quote content type, we copied the frontend styles (`app/code/Example/PageBuilderQuote/view/frontend/web/css/source/content-type/example-quote/_import.less`) and added them to our `exampleQuote.css`. - -## Step 2: Convert LESS to CSS - -PWA studio uses [CSS Modules][]. It does not include tooling for LESS pre-processors, so you will need to convert your LESS into standard CSS style rules. For example, the LESS stylesheet for our Quote content type is shown here, followed by the equivalent CSS we included in our `exampleQuote.css`. - -**Quote content type LESS styles** (`_import.less`): - -```scss -& when (@media-common = true) { - blockquote.quote { - display: block; - font-size: 1.3em; - margin: 1em; - padding: 0.5em 10px; - quotes: "\201C" "\201D" "\2018" "\2019"; - text-decoration: none; - word-break: normal !important; - line-height: 1.5; - padding: 0; - font-weight: 300; - &:before { - content: open-quote; - font-size: 2.6em; - margin-right: 0.2em; - vertical-align: -0.35em; - line-height: 0; - margin-left: -0.5em; - font-weight: 300; - } - &:after { - content: close-quote; - font-size: 0; - line-height: 0; - margin-left: 0; - } - } - div { - &.quote-author { - text-align: left; - padding-right: 30px; - font-size: 14px; - color: #666; - margin-left: 1.1em; - } - &.quote-description { - text-align: left; - padding-right: 30px; - font-size: 14px; - color: #999; - margin-left: 1.1em; - font-weight: 300; - } - } - .black-quote { - color: #333333; - &:before { - color: #333333; - } - } - .blue-quote { - color: #007ab9; - &:before { - color: #71adcc; - } - } - .green-quote { - color: #009900; - &:before { - color: #009900; - } - } - .red-quote { - color: #990000; - &:before { - color: #990000; - } - } - .purple-quote { - color: #990099; - &:before { - color: #990099; - } - } -} -``` - -**Equivalent component styles** (`exampleQuote.css`): - -```css -.quote { - display: block; - font-size: 1.4em; - margin: 1em 1em 0.3em 0.6em; - quotes: '\201C''\201D''\2018''\2019'; - text-decoration: none; - font-style: italic; - word-break: normal !important; - padding: 0; - font-weight: 300; -} -.quote:before { - content: open-quote; - font-size: 2.4em; - margin-right: 0.1em; - vertical-align: -0.3em; - line-height: 0; - margin-left: -0.3em; - font-weight: 300; -} -.quote:after { - content: close-quote; - font-size: 0; - line-height: 0; - margin-left: 0; -} -.quoteAuthor { - padding-right: 30px; - font-size: 16px; - color: #333333; - line-height: 24px; - margin-left: 1.5em; - word-break: normal !important; - font-weight: 600; -} -.quoteDescription { - position: relative; - padding-right: 30px; - font-size: 16px; - line-height: 18px; - color: #666666; - margin-left: 1.5em; - font-weight: 300; - word-break: normal !important; -} -.blackQuote { - color: #333333; -} -.blackQuote::before { - color: #333333; -} -.blueQuote { - color: #007ab9; -} -.blueQuote::before { - color: #007ab9; -} -.greenQuote { - color: #009900; -} -.greenQuote::before { - color: #009900; -} -.redQuote { - color: #990000; -} -.redQuote::before { - color: #990000; -} -.purpleQuote { - color: #990099; -} -.purpleQuote::before { - color: #990099; -} -``` - -## Step 3: Rename classes (optional) - -Renaming your class names to use camelCase instead of hyphens allows you to work with CSS classes in your component as if they were JavaScript object properties. For example, if you name the class for the quote author's name as `.quote-author` (with a hyphen), you must access this class in your component like this: - -```html - {author}-``` - -This not only uses a string which is prone to errors, but you don't have the benefit of your editor's intellisense. - -Compare that to using camelCase for your hyphenated class names by renaming `.quote-author` to `.quoteAuthor` and thereby enabling access to CSS classes using dot syntax, as shown here: - -![Change class names to camelCase](images/AddStylesheetCamelCase.png) - -**Protip**: Use camelCase to rename your CSS classes so that you can use dot syntax and intellisense to browse through your style rules more easily when applying them to your component. - -[css modules]: {%link technologies/basic-concepts/css-modules/index.md %} diff --git a/pwa-devdocs/src/pagebuilder/custom-components/debugging/index.md b/pwa-devdocs/src/pagebuilder/custom-components/debugging/index.md deleted file mode 100644 index 4df74e871e..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/debugging/index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Debugging tips ---- - -If you haven't yet modified the config object and setup the references you'll see the following console warning, telling you the component is missing: - -```text -parseStorageHtml.js?4091:67 No config aggregator defined for content type X, this content type won't be rendered. -``` - -If you _have_ modified the configuration and your content type is still not displaying, debug through `packages/pagebuilder/lib/parseStorageHtml.js` to determine if your configuration item is correctly detected. diff --git a/pwa-devdocs/src/pagebuilder/custom-components/overview/images/OverviewSteps.svg b/pwa-devdocs/src/pagebuilder/custom-components/overview/images/OverviewSteps.svg deleted file mode 100644 index 6442f6f438..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/overview/images/OverviewSteps.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/overview/images/PageBuilderQuoteAdmin.png b/pwa-devdocs/src/pagebuilder/custom-components/overview/images/PageBuilderQuoteAdmin.png deleted file mode 100644 index 3116c95199..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/overview/images/PageBuilderQuoteAdmin.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/overview/images/PageBuilderQuoteStorefront.png b/pwa-devdocs/src/pagebuilder/custom-components/overview/images/PageBuilderQuoteStorefront.png deleted file mode 100644 index e246a6fc41..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/overview/images/PageBuilderQuoteStorefront.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/overview/index.md b/pwa-devdocs/src/pagebuilder/custom-components/overview/index.md deleted file mode 100644 index c9216fe78c..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/overview/index.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Overview ---- - -Let's assume you have at least one _custom_ Page Builder content type rendering content on your Magento storefront. But now you want that content to show up in your PWA app as well. What do you do? Short answer: You create a custom PWA Page Builder component (also know as a "content type component"). The long answer is described in this series of topics. The steps shown here describe the recommended process for developing content type components: - -![Overview of steps](images/OverviewSteps.svg) - -The topics for these steps show you how to create the code that retrieves properties (content and styling) from your content type HTML (in the configAggregator) and assign those properties to the equivalent properties in your in content type component. - -## Prerequisites - -Before you start creating your custom content type component in PWA Studio, make sure you have met the following prerequisites: - -- Your Magento instance should have a custom content type added and saved to the **home** page in the Admin. Currently, the `home` page is the only page you can render Page Builder content within PWA Studio. -- Your Magento instance should render this content type on the home page of your storefront. - -{: .bs-callout-info} -We assume you already have the PWA Studio set up and running in your development environment. If you do not, [use these instructions][] to do that now. - -## Using the Quote content type - -To help explain the process of creating a custom Page Builder component, we frequently refer to a component called `ExampleQuote`. We built this component as the PWA counterpart to the example Quote content type found on the [GitHub pagebuilder-examples repo][]. - -If you want to follow along with these topics more closely, [download and install the PageBuilderQuote module][] in your Magento instance and use it to fulfill the prerequisites previously mentioned. - -## Home page in Admin - -The first prerequisite is to add and save your custom content type to your Magento Home page in Admin. Here we see the Quote content type saved to the Home page in the Admin: - -![PageBuilderQuote in Admin](images/PageBuilderQuoteAdmin.png) - -## Home page on Storefront - -The second prerequisite is to ensure that your custom content type renders successfully in the storefront of your Magento instance. Here we see the Quote content type rendered on the Home page of a Luma storefront: - -![PageBuilderQuote on Storefront](images/PageBuilderQuoteStorefront.png) - -After you have met these prerequisites, you are ready to begin creating your custom Page Builder component in the PWA Studio. - -[use these instructions]: <{% link venia-pwa-concept/setup/index.md %}> - -[download and install the pagebuilderquote module]: https://github.com/magento-devdocs/pagebuilder-examples/tree/master/Example/PageBuilderQuote - -[github pagebuilder-examples repo]: https://github.com/magento-devdocs/pagebuilder-examples/tree/master/Example/PageBuilderQuote diff --git a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/ConfigureComponentOutput.png b/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/ConfigureComponentOutput.png deleted file mode 100644 index 30fc0ed55a..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/ConfigureComponentOutput.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/PageBuilderConfigFile.png b/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/PageBuilderConfigFile.png deleted file mode 100644 index 0a43b1b6a1..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/PageBuilderConfigFile.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/PageBuilderFilesSetup.png b/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/PageBuilderFilesSetup.png deleted file mode 100644 index 7d5b2990ef..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/PageBuilderFilesSetup.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/SetupComponentSteps.svg b/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/SetupComponentSteps.svg deleted file mode 100644 index 3bd49db0b2..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/SetupComponentSteps.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/SetupComponentTest.svg b/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/SetupComponentTest.svg deleted file mode 100644 index e71e7b10b0..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/SetupComponentTest.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/index.md b/pwa-devdocs/src/pagebuilder/custom-components/setup-component/index.md deleted file mode 100644 index 7309edafee..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/index.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Set up component ---- - -Setting up your component is about getting the essential component files in place so that your component is actively participating in the Page Builder component framework. After you create these files and wire them into the component framework, you can focus all your attention on developing each file to faithfully recreate your content type as a PWA component. The following steps highlight the tasks for setting up your component: - -![Component setup steps](images/SetupComponentSteps.svg) - -## Step 1: Create starter files - -The first thing you need to do within PWA Studio is create the directory and skeleton files needed for your component, as follows: - -- **configAggregator.js** (required) - Function to retrieve content and styling properties from your content type's master format HTML. -- **myComponent.js** (required) - React component for populating properties that correspond to the original Page Builder content type. For our ExampleQuote, we use `exampleQuote.js`. -- **myComponent.css** (optional but usually needed) - CSS classes that provide addition styles needed to present your component as desired. For our ExampleQuote, we use `exampleQuote.css`. -- **index.js** (required) - Entry file needed to identify your component in PWA Studio. - -Currently, you need to add your content type's component, like `ExampleQuote`, to the `ContentTypes` directory, where the native Page Builder components are kept. This will change when we implement different rules for extending Page Builder components. But for now, add your custom content type components as shown here: - -![Component file structure](images/PageBuilderFilesSetup.png) - -Starter code for the `ExampleQuote` component files is provided as follows. - -### configAggregator.js - -```js -export default (node, props) => { - return { - // Retrieve properties from node here - }; -}; -``` - -### exampleQuote.css - -```css -/* class for testing setup */ -.testClass { - line-height: 1.4em; - font-size: 1em; - color: #0066cc; -} -``` - -### exampleQuote.js - -```jsx -import React from 'react'; -import { mergeClasses } from '../../../../../classify'; -import defaultClasses from './exampleQuote.css'; -import { shape, string } from 'prop-types'; - -const classes = mergeClasses(defaultClasses, props.classes); - -// Component for testing setup -const ExampleQuote = props => { - return ( --- ); -}; - -ExampleQuote.propTypes = { - classes: shape({ - testClass: string - }), - contentType: string, - appearance: string -} - -export default ExampleQuote; -``` - -### index.js - -```js -export { default } from './exampleQuote'; -``` - -## Step 2: Configure component - -Configuring your component is about connecting your component to the Page Builder component framework. The framework provides a static config object (in `config.js`) that acts as a kind of registry of content types supported within PWA Studio. To include support for your custom content type component, you'll need to add an entry to the `config.js`: - -![Component config file](images/PageBuilderConfigFile.png) - -Open the `config.js` file and `import` your `configAggregator`. The import statement for our ExampleQuote is shown here: - -```js -import exampleQuoteConfigAggregator from './ContentTypes/ExampleQuote/configAggregator'; -``` - -Add an entry that references your `configAggregator` and `component`, using the name of your content type as the `key`. For our `ExampleQuote`, the name of the Quote content type is `example_quote`, so the entry for our Quote component (`ExampleQuote`) in the config file looks like this: - -```js -example_quote: { - configAggregator: exampleQuoteConfigAggregator, - component: React.lazy(() => import('./ContentTypes/ExampleQuote')) -}, -``` - -### A note about lazy loading components - -When building PWAs, performance is key. That's why we recommend loading less critical components using `React.lazy`. This will result in a very slight delay in that content rendering but will ensure we don't bloat the bundle size for the store. For more information, see the [react lazy loading][] docs on the React site. - -By default, we apply `React.lazy` to the following content types: Banner, Slider, Slide Item, Tab, Tab Item, Button, Button Item, Block, Products, HTML, and Divider. - -To have your component loaded lazily you simply have to wrap your `component` reference in a call to `React.lazy` as previously shown for the ExampleQuote component: - -```js -component: React.lazy(() => import('./ContentTypes/ExampleQuote')) -``` - -## Test the component setup - -After adding these files and hooking them up to the framework through the configuration file (`config.js`), your skeleton component will appear on the Venia home page: - -![ExampleQuote component rendered with starter code](images/ConfigureComponentOutput.png) - -If you see this rendering without errors in the Venia app, you are ready to start developing your content type component. - -## Troubleshooting - -If you have errors, make sure you have: - -1. Copied the correct starter code for each of the four files. -2. Added the correct name of your content type to the `config.js` file (`example_quote` if you are using the Quote content type). - -[react lazy loading]: https://reactjs.org/docs/code-splitting.html#reactlazy diff --git a/pwa-devdocs/src/pagebuilder/images/PageBuilderBigPicture1.svg b/pwa-devdocs/src/pagebuilder/images/PageBuilderBigPicture1.svg deleted file mode 100644 index 0c719b64b5..0000000000 --- a/pwa-devdocs/src/pagebuilder/images/PageBuilderBigPicture1.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/images/PageBuilderIntegration.svg b/pwa-devdocs/src/pagebuilder/images/PageBuilderIntegration.svg deleted file mode 100644 index b045c3f488..0000000000 --- a/pwa-devdocs/src/pagebuilder/images/PageBuilderIntegration.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/images/PageBuilderIntegrationDetails.svg b/pwa-devdocs/src/pagebuilder/images/PageBuilderIntegrationDetails.svg deleted file mode 100644 index 5a576ee74d..0000000000 --- a/pwa-devdocs/src/pagebuilder/images/PageBuilderIntegrationDetails.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/index.md b/pwa-devdocs/src/pagebuilder/index.md deleted file mode 100644 index 94c16a106e..0000000000 --- a/pwa-devdocs/src/pagebuilder/index.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Page Builder to PWA integration ---- - -{: .bs-callout-info} -The Page Builder integration to PWA Studio is only compatible with Magento Commerce 2.3.4+. A GraphQL change within Magento Commerce 2.3.4 was necessary in order to integrate the Page Builder Products content type into PWA Studio. - -## Page Builder Integration: The Big Picture - -At the highest level, the Page Builder integration into PWA Studio simply ensures that CMS Pages built in Magento Commerce with _native_ Page Builder content types are rendered correctly within PWA Studio apps. - -The diagram below shows how the PWA Studio makes a request to the Magento Commerce backend to retrieve a CMS page for processing. The Page Builder integration framework processes the original Page Builder HTML and returns a group of React components that faithfully reproduces the Page Builder content for display in a PWA Studio app. - -![Page Builder Integration Big Picture](images/PageBuilderBigPicture1.svg) - -1. The Page Builder integration framework processes Page Builder content types within a CMS Page: Rows, Headings, Banners, Sliders, and so on. - -2. A set of equivalent content type React components -- Row, Heading, Banner, Slider, Text and so on -- are populated with the content and style properties from the original Page Builder content types so they can be displayed correctly within PWA Studio app storefronts. - -## Page Builder Integration: Custom Content Types - -If you only used Page Builder's 15 native content types (Dynamic Blocks are not supported), your Page Builder pages are automatically rendered within a PWA Studio app. No development work is necessary. However, if you use one or more of your own custom Page Builder content types within your CMS pages (for example, a [Quote-Testimonial content type][]), you will need to create your own equivalent Page Builder React component and integrate it within the framework. Otherwise, your custom content type will not appear on the storefront within a PWA Studio app. That area of your page will simply be blank. - -{: .bs-callout-info} -To develop and integrate your own custom content type components into your PWA Studio app, follow our [Creating custom components][] tutorial. - -![Page Builder Integration Overview](images/PageBuilderIntegration.svg) - -## Page Builder Integration Framework: The Details - -As part of the Page Builder integration to PWA Studio, we implemented a framework that converts Page Builder’s master format (HTML) into a structured format that works in React and PWA Studio. The components and functions within the Page Builder integration work together to: - -* Receives Page Builder content types in the original HTML format (**RichContent** and **PageBuilder** components) - -* Extracts the content and properties from each content type's HTML (**Master Format parser**, **config function**, and **property aggregators**) - -* Retrieves the equivalent content type React components for those content types (**ContentTypeFactory**, **config function**, and **content type components**) - -* Populates those React components with the content and style properties from the original content types (**ContentTypeFactory and content type components**) - -* Returns those components for for display in a PWA Studio app (**PageBuilder** and **RichContent** components) - -The components and functions that provide these services are described as follows: - -**RichContent**: The `Content Type: {props.contentType}-Appearance: {props.appearance}-` component provides the entry point into the Page Builder PWA framework. It determines whether the HTML passed by the PWA Studio app contains Page Builder content. If it does, the HTML is sent to the ` ` component for processing. If not, the HTML is sent directly to the PWA Studio app for display. - -**PageBuilder**: The ` ` component (not to be confused with the individual Page Builder React components) directs the parsing of the master format HTML as well as retrieving, populating, and returning the equivalent React components back to the Venia app. - -**Master Format parser**: The master format parser (`parseStorageHtml()`) decomposes the master format HTML into the content type HTML fragments (HTMLElements) that compose the master format. The parser sends the content type HTML to the correct property aggregator (`configAggregator`) using the configuration object. - -**Config function** (_integration point_): The configuration function (`getContentTypeConfig()`) provides an interface for retrieving a content type's _property aggregator_ and its corresponding _content type component_. The configuration object also provides the integration point for your own custom content type components. See [Set up component][] for details. - -**Property aggregator** (_integration point_): The property aggregator for a content type (example: `bannerConfigAggregator`) is a function that retrieves both content and style properties from the content type's HTML. Aggregators typically use both DOM properties and several provided framework utility functions to retrieve these properties and write them to flat property objects used to populate the content type React components. For each of your custom content types, you will need to create your own property aggregator. See [Add aggregator][] for details. - -**Content type component** (_integration point_): The content type component is a React component that is equivalent to a Page Builder content type. There are 15 content type components within PWA Studio: Row, Column, Tabs, Banners, Sliders, and so on. Each content type component is populated with the original content and style properties from the content type to faithfully represent your Page Builder content within a PWA Studio app like Venia. For each of your custom content types, you will need to create the equivalent content type React component . See [Add component][] for details. - -**ContentTypeFactory**: The ` ` component parses a property object tree to retrieve the equivalent React component for each content type property object it finds. It then populates these components and sends them back to the PWA Studio app as a composite React element displayed to the end user. - -## Page Builder Integration Framework: How it works - -The framework executes on the client side to ensure compatibility with the various hosting options available for Magento Commerce. The following flow diagram describes how the parts of the framework work together to render Page Builder components within the Venia app. - -![Page Builder Integration Details](images/PageBuilderIntegrationDetails.svg) - -1. The **Venia app** sends a GraphQL query to get the user's requested page. This requested page comes from the `content` field of `cms_pages` table in Magento's database. The content returned is an HTML string with Page Builder meta data. We call this HTML string the master format, which is passed to the ` ` component for initial processing. - -2. The **RichContent** component determines if the HTML string contains Page Builder content, using simple pattern recognition. If the HTML does not include Page Builder content, it is returned to Venia and rendered as plain HTML. If the HTML does include Page Builder content, the HTML string (which we can now define as a master format) is passed to the ` ` framework component, which starts the process of matching the content types within the master format to their equivalent PWA Studio React components. - -3. The **PageBuilder** framework component passes the master format to the framework's parser function called `parseStorageHTML()`. - -4. The **parser** function parses the master format HTML recursively to decompose all the Page Builder content types into their own `HTMLElement` strings for further processing. When the parser finds a content type, it uses the framework's config function to access that content type's property aggregator. The aggregator retrieves content and styles from the `HTMLElement` and writes them to a flat object (used later to hydrate the content type component). - - {: .bs-callout-info} - Each Page Builder content type has its own corresponding property aggregator. For example, the Heading content type (rendered in the master format as HTML) has a Heading aggregator (`headingConfigAggregator`), which converts the Heading's HTML properties to a flat object with those same properties. The parser does this for each content type it finds in the master format: uses the `getContentTypeConfig()` function to find and run the content type's property aggregator, which returns an object with both the content and the style properties for that content type. All CMS pages built with Page Builder have at least two content types: a Row content type and at least one other content type contained within that Row, such as a Banner. - -5. When the **parser** function finishes processing all the content types within the master format, it returns a property object tree for those content types back to the ` ` component. - -6. The **PageBuilder** framework component passes the property object tree to the framework's ` ` component for further processing. - -7. Much like in step 4 with the parser, the framework's **ContentTypeFactory** component retrieves the equivalent React component for each content type property object it finds within the object tree. - -8. The **ContentTypeFactory** populates those React components with the property values retrieved from each content type's property aggregator. - -9. And finally, the **PageBuilder** framework component returns a composite React element with all the Page Builder content type components needed to render the original Page Builder content within a PWA Studio app. - -[Quote-Testimonial content type]: https://devdocs.magento.com/page-builder/docs/create-custom-content-type/overview.html -[Creating custom components]: <{%link pagebuilder/custom-components/overview/index.md %}> -[add aggregator]: <{%link pagebuilder/custom-components/add-aggregator/index.md %}> -[set up component]: <{%link pagebuilder/custom-components/setup-component/index.md %}> -[add component]: <{%link pagebuilder/custom-components/add-component/index.md %}> diff --git a/pwa-devdocs/src/pagebuilder/known-limitations/images/LimitationsTextAlign.png b/pwa-devdocs/src/pagebuilder/known-limitations/images/LimitationsTextAlign.png deleted file mode 100644 index 9939cd3894..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/known-limitations/images/LimitationsTextAlign.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/known-limitations/index.md b/pwa-devdocs/src/pagebuilder/known-limitations/index.md deleted file mode 100644 index 910cb652d1..0000000000 --- a/pwa-devdocs/src/pagebuilder/known-limitations/index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Known limitations ---- - -The following items are known limitations to implementing PWA Studio components for Page Builder content types: - -- **CMS Pages only** - Page Builder integration within PWA Studio only supports Magento CMS Pages created with Page Builder. It does not support CMS Blocks, Product content, or Category content created with Page Builder. -- **Widgets in TinyMCE** - Widgets are not supported within content types that provide text input from the TinyMCE editor, such as Text, Banner, Slider, and HTML Code. -- **Dynamic Blocks** - Not supported in PWA Studio. PWA Studio currently has no concept of a Dynamic Block. Dynamic Blocks required session information to correctly display their content. Currently this session is not shared between PWA Studio and the backend and there are no GraphQL endpoints for Dynamic Block. -- **Products text alignment** - Text alignment for Products does not work within the PWA Studio gallery because the gallery is rendered with the CSS grid layout. The Alignment property (as set within the Products content type form) will always default to `Left`. -- **Extensibility** - PWA Studio currently lacks an extensibility model, which prevents Page Builder from using an existing framework / model. We can potentially use the comment based root component declaration that is baked into PWA Studio, but this will require additional work. -- **GraphQL query results** - Some content types (such as Products) create a large amount of output from the GraphQL endpoint, even though we don't intend to render it. -- **Staging and Preview** - PWA Studio does not support cache invalidation, which means Staging and Preview are not supported in Venia. \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/utility-functions/index.md b/pwa-devdocs/src/pagebuilder/utility-functions/index.md deleted file mode 100644 index 58924cdaab..0000000000 --- a/pwa-devdocs/src/pagebuilder/utility-functions/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Utility functions ---- - -The utility functions help with retrieving commonly stored data in a content type. For example, the `getAdvanced(node)` wrapper function retrieves all the content type's Advanced form section settings so you do not have to worry about retrieving each one separately. Retrieving background images and associated properties is also made easy with the `getBackgroundImages(node)` function. - -For implementation details [View Source][] - - - -{% include auto-generated/pagebuilder/lib/utils.md %} - -[view source]: https://github.com/magento/pwa-studio/blob/feature/page-builder/packages/pagebuilder/lib/utils.js diff --git a/pwa-devdocs/src/peregrine/index.md b/pwa-devdocs/src/peregrine/index.md deleted file mode 100644 index 5c99451410..0000000000 --- a/pwa-devdocs/src/peregrine/index.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Peregrine ---- - -The Peregrine package is a collection of functions that act as the brains of your visual components. -They provide pieces of logic for UI components, such as the ones provided by the [Venia][] library. -Use or remix these functions and components to create a unique Magento PWA storefront. - -## Custom React hooks - -Many of the functions provided by Peregrine are [custom React hooks][]. -This lets them maintain an internal state without relying on an external library, such as Redux. - -Peregrine hooks are designed to be flexible, and non-opinionated about UI. -They contain code for providing data or behavior logic and do not render content themselves. -Rendering content is left up to UI components. - -Separating logic and presentation code gives developers more flexibility on how to use PWA Studio components with their own custom code. -A developer may choose to use a Venia feature that uses certain Peregrine hooks with minor visual modifications, or -they can use those same Peregrine hooks to develop their own feature with a different UI. - -For more information about custom hooks, see the React documentation for [Building Your Own Hooks][]. - -### Return signatures - -The return signatures of Peregrine hooks vary and is dependent on their purpose. - -Some return an array with *state* and *api* objects, which follow the same pattern as [`useState()`][] and [`useReducer()`]. -This lets you specify the variable names of the provided objects when you [destructure][] the array. - -Other Peregrine hooks return a single object. - -Use the reference docs on this site or in the [JSDoc][] blocks in the source code learn the API for each hook. - -## JSDoc blocks - -Most of the reference docs in this section are generated from [JSDoc][] blocks. -The currently published docs reflect what is available from the most recent release, but -the JSDoc blocks in the source are kept up to date for developers who want to work with unreleased code. - -## Source - -Visit the [`peregrine`][] package to view the source or contribute to this project. - -[venia]: {%link venia-pwa-concept/index.md %} - -[`peregrine`]: https://github.com/magento/pwa-studio/tree/master/packages/peregrine -[custom react hooks]: https://reactjs.org/docs/hooks-custom.html -[destructure]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment -[jsdoc]: https://devdocs.io/jsdoc/ -[`usestate()`]: https://reactjs.org/docs/hooks-reference.html#usestate -[`usereducer()`]: https://reactjs.org/docs/hooks-reference.html#usereducer -[building your own hooks]: https://reactjs.org/docs/hooks-custom.html diff --git a/pwa-devdocs/src/peregrine/reference/container-child/index.md b/pwa-devdocs/src/peregrine/reference/container-child/index.md deleted file mode 100644 index 23f8bf97eb..0000000000 --- a/pwa-devdocs/src/peregrine/reference/container-child/index.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: ContainerChild ---- - -The `ContainerChild` component is the only child allowed within a [Container] in Magento PWA storefront. -This component is responsible for rendering content. - -## Props - -| Name | Required | Description | -| -------- | :-------------------------------------------: | --------------------------------------------------------- | -| `id` | check_box | A unique string identifier | -| `render` | check_box | A [render prop] that should return the children to render | -{:style="table-layout:auto"} - -## Example - -``` jsx -import { ContainerChild } from '@magento/peregrine'; - - -; -``` - -[render prop]: https://reactjs.org/docs/render-props.html -[Container]: {% link technologies/basic-concepts/container-extensibility/index.md %} \ No newline at end of file diff --git a/pwa-devdocs/src/peregrine/reference/hooks/useDropdown/index.md b/pwa-devdocs/src/peregrine/reference/hooks/useDropdown/index.md deleted file mode 100644 index 70bd59e6dd..0000000000 --- a/pwa-devdocs/src/peregrine/reference/hooks/useDropdown/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: useDropdown ---- - - - -{% include auto-generated/peregrine/lib/hooks/useDropdown.md %} diff --git a/pwa-devdocs/src/peregrine/reference/hooks/useEventListener/index.md b/pwa-devdocs/src/peregrine/reference/hooks/useEventListener/index.md deleted file mode 100644 index dd9c2a427b..0000000000 --- a/pwa-devdocs/src/peregrine/reference/hooks/useEventListener/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: useEventListener ---- - - - -{% include auto-generated/peregrine/lib/hooks/useEventListener.md %} diff --git a/pwa-devdocs/src/peregrine/reference/hooks/usePagination/index.md b/pwa-devdocs/src/peregrine/reference/hooks/usePagination/index.md deleted file mode 100644 index 7180f6e258..0000000000 --- a/pwa-devdocs/src/peregrine/reference/hooks/usePagination/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: usePagination ---- - - - -{% include auto-generated/peregrine/lib/hooks/usePagination.md %} diff --git a/pwa-devdocs/src/peregrine/reference/hooks/useSearchParam/index.md b/pwa-devdocs/src/peregrine/reference/hooks/useSearchParam/index.md deleted file mode 100644 index 694d18a804..0000000000 --- a/pwa-devdocs/src/peregrine/reference/hooks/useSearchParam/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: useSearchParam ---- - - - -{% include auto-generated/peregrine/lib/hooks/useSearchParam.md %} - -## Example - -The following example, uses the `useSearchParam()` hook to get the `query` parameter from the URL. - - diff --git a/pwa-devdocs/src/peregrine/reference/hooks/useWindowSize/index.md b/pwa-devdocs/src/peregrine/reference/hooks/useWindowSize/index.md deleted file mode 100644 index 32d563ef73..0000000000 --- a/pwa-devdocs/src/peregrine/reference/hooks/useWindowSize/index.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: useWindowSize ---- - - - -{% include auto-generated/peregrine/lib/hooks/useWindowSize.md %} - -## Examples - -It is recommended to only create/use the WindowSizeContextProvider a single time at the top level of your app: - -```jsx -return( - Used just like a normal render() method} - /> -( - Can render anything a normal component can render- )} - /> -- -) -``` - -Inside a component in your application, use the `useWindowSize()` function to get the window size value that updates when the window size changes. - -```jsx -import { useWindowSize } from '@magento/peregrine'; - -function MyComponent(props) { - - const windowSize = useWindowSize(); - - return ( - - Inner window size: {windowSize.innerWidth} x {windowSize.innerHeight} - - ); - -} -``` diff --git a/pwa-devdocs/src/peregrine/reference/item/index.md b/pwa-devdocs/src/peregrine/reference/item/index.md deleted file mode 100644 index 44e4270a84..0000000000 --- a/pwa-devdocs/src/peregrine/reference/item/index.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Item ---- - - -The `Item` component takes a data object and renders it using a [render prop] or wraps it in an HTML element. - -This component is used as a direct child of the [`Items`] fragment. - -## Props - -| Name | Required | Default | Description | -| ------------ | :-------------------------------------------: | ------- | ------------------------------------------------------------- | -| `classes` | | `{}` | A classname hash | -| `hasFocus` | | `false` | Set to `true` if the browser is currently focused on the item | -| `isSelected` | | `false` | Set to `true` if the item is currently selected | -| `item` | check_box | | A data object. If this is a string, it is rendered as a child | -| `render` | check_box | `'div'` | A render prop or HTML tagname string, such as `"div"`. | -{:style="table-layout:auto"} - -## Example - -``` jsx -{% raw %} -import Item from '@magento/peregrine'; - -- - -{% endraw %} -``` - -[render prop]: https://reactjs.org/docs/render-props.html -[`Items`]: {% link peregrine/reference/items/index.md %} -[`List`]: {% link peregrine/reference/list/index.md %} \ No newline at end of file diff --git a/pwa-devdocs/src/peregrine/reference/items/index.md b/pwa-devdocs/src/peregrine/reference/items/index.md deleted file mode 100644 index 25f4b4e8ca..0000000000 --- a/pwa-devdocs/src/peregrine/reference/items/index.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Items ---- - -The `Items` component uses content in a data object to render a list of [`Item`] components. - -It follows the [Fragments] pattern and returns its children without a wrapping element. -This allows you to decide how you want to wrap your list of items. - -The `Items` component is used as a direct child of the [`List`] component. - -## Props - -| Name | Required | Description | -| ---------------- | :-------------------------------------------: | ------------------------------------------------------------------- | -| `items` | check_box | An iterable that yields `[key, item]` pairs such as an ES2015 [Map] | -| `renderItem` | | A [render prop] or HTML tagname string. | -| `selectionModel` | | A string corresponding to a selection model. | -{:style="table-layout:auto"} - -### Selection models - -{% include peregrine/reference/list-selection-models.md %} - -## Example - -``` jsx -import Items from '@magento/peregrine'; - -const data = { - s: { id: 's', value: 'Small' }, - m: { id: 'm', value: 'Medium' }, - l: { id: 'l', value: 'Large' } -}; - -
-``` - -[`List`]: {% link peregrine/reference/list/index.md %} -[render prop]: https://reactjs.org/docs/render-props.html -[Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map -[Fragments]: https://reactjs.org/docs/fragments.html -[`Item`]: {% link peregrine/reference/item/index.md %} \ No newline at end of file diff --git a/pwa-devdocs/src/peregrine/reference/list/index.md b/pwa-devdocs/src/peregrine/reference/list/index.md deleted file mode 100644 index 05ad2980f3..0000000000 --- a/pwa-devdocs/src/peregrine/reference/list/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: List ---- - - -{% include auto-generated/peregrine/lib/List/list.md %} - -### Selection models - -{% include peregrine/reference/list-selection-models.md %} - -## Example - -``` jsx -{% raw %} -import { List } from '@magento/peregrine'; - -const simpleData = new Map() - .set('s', 'Small') - .set('m', 'Medium') - .set('l', 'Large') - - - -const complexData = new Map() - .set('s', { id: 's', value: 'Small' }) - .set('m', { id: 'm', value: 'Medium' }) - .set('l', { id: 'l', value: 'Large' }) - -
(
{props.children}
)} - renderItem={props => ({props.value} )} -/> -{% endraw %} -``` - -[render prop]: https://reactjs.org/docs/render-props.html -[Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map diff --git a/pwa-devdocs/src/peregrine/reference/price/index.md b/pwa-devdocs/src/peregrine/reference/price/index.md deleted file mode 100644 index 104666cf30..0000000000 --- a/pwa-devdocs/src/peregrine/reference/price/index.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Price ---- - - -{% include auto-generated/peregrine/lib/Price/price.md %} - -## Example - -```jsx -import Price from '@peregrine/Price'; -import cssModule from './my-pricing-styles'; - -; -/* - $ - 88 - . - 81 -*/ -``` diff --git a/pwa-devdocs/src/peregrine/reference/rest-api-client/index.md b/pwa-devdocs/src/peregrine/reference/rest-api-client/index.md deleted file mode 100644 index 1eee2e23fd..0000000000 --- a/pwa-devdocs/src/peregrine/reference/rest-api-client/index.md +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: REST API client ---- - -The REST API client utility module provided by Peregrine allows you to work with non-GraphQL web APIs. -The default implementation is a client that works with the REST API for Magento 2.3 and above. - -## Magento 2 REST API client - -The Magento 2 REST API client provides a `request()` function which places a request to a Magento backend and returns a [`Promise`][] as a response. -This function is similar to the Web standard [`fetch()`][] function with a few differences in [response][] and [error][] handling. -It also contains features to support [multicasting][] and [rolling requests][]. - -For basic use cases, use the `request()` method. -For more advanced cases, use the [`M2ApiRequest`][] class, which the `request()` method wraps. - -### Syntax - -```js -request(resourceUrl, opts) -``` - -#### Parameters - -`resourceUrl` ([`UVString`][]) - -: A [Magento REST endpoint][]. - -`opts` (object) - -: An options object that can contain all possible [fetch options][]. - - Additional options: - - * `parseJSON` (boolean): Automatically parse the response into JSON format. - Defaults to `true`. - * `multicast` (boolean): Manually set whether a request should use the [multicasting][] feature. - -#### Returns - -A [`Promise`][] object that contains the result of the request. See [response handling][response]. - -### Usage - -The following example imports the `request()` function into another module: - -```js -import { RestApi } from '@magento/peregrine'; - -const { request } = RestApi.Magento2; -``` - -Use the `request()` function to place and receive API calls using `async/await` syntax: - -```js -async function displayGuestCartItems(cartId) { - const cartResponse = await request( - `guest-carts/${cartId}`, - { - method: 'GET' - } - ); - const cart = await cartResponse; - console.log(cart.items); -} -``` - -Or use the `Promise` object directly: - -```js -function displayGuestCartItems(cartId) { - return request( - `guest-carts/${cartId}`, - { - method: 'GET' - } - ) - .then(({ items }) => console.log(items);) -} -``` - -### Response handling - -The `request()` method returns a [`Promise`][] object with a fully parsed REST resource instead of an HTTP response as in the standard [`fetch()`][] API. - -To make `request()` behave like `fetch()`, set the value of `parseJSON` to `false` in the options object. -This changes the value passed to the `Promise.resolve()` function back to a [`Response`][] object. - -```js -request( - `guest-carts/${cartId}`, - { - method: 'GET', - parseJSON: false - } -).then(({ response }) => console.log(response);) -``` - -### Error handling - -Promises returned by `request()` are rejected if the server responds with an HTTP error code within the 4xx-5xx range. -This is different from the standard `fetch()` behavior, which ignores HTTP errors so it can resolve the promise and only fails on network connectivity errors. - -The Magento REST API uses HTTP error codes to denote failed operations, so -the `request()` method responds to these server-side errors by rejecting them. -When the server returns an error code, the `request()` method builds an error containing metadata for debugging and rejects the `Promise`. - - -### Multicasting - -The multicasting feature of the Magento 2 REST client collects all successive calls to the `request()` method and returns a single request and response that is shared to all method callers. - -In any distributed architecture, where applications are built from components with view, behavior, and data fetching strategy, multiple components may request the same resource at the same time. -GraphQL clients resolve this by merging GraphQL queries together, dispatching a request as a single call, and distributing the pieces of the GraphQL response to the original callers. -A direct call using `fetch()` or `XMLHttpRequest()` does not provide this functionality. - -The `request()` method makes up for this by using a pattern-matching rule on inflight requests. -All requests with the same method, path, and body text are considered multicastable by default. -A clone of the response object is returned if a request meets the following criteria: - -* The pattern of the new request matches one that is already in progress, i.e. the network has not loaded the resource yet. -* No unsafe operations, such as `POST`, have occurred to the target resource between the time of the original request and the new request. -* The request is not a `POST` request. - These requests create and/or modify server state, so it is unsafe to reuse their results. - -#### Override multicast - -The `multicast` configuration option forces multicasting to be `true` or `false` and bypasses the previously described rules. - -```js -// A normally multicast request forced not to multicast -request('carts/mine',{ method: 'GET', multicast: false }); - -// A normally non-multicast request forced to multicast -request( - 'carts/mine/items', - { - method: 'POST', - body: cartItem, - multicast: true - } -); -``` - -### Rolling requests - -A rolling request is a multicast which overrides and replaces matching, previous multicast requests. -It helps maintain a fresh resource, such as a shopping cart, and reduces network traffic by aborting outstanding matching requests. - -This feature has no effect on non-multicast requests. - -To use a rolling request, set the `cache` configuration option to `reload` or `no-store`. - -### The `M2ApiRequest` class - -The `request()` method is a convenience wrapper on top of the -`M2ApiRequest` class. - -Use the `M2ApiRequest` class if you want more control over your REST requests. - -```js -import { RestApi } from '@magento/peregrine'; -const { M2ApiRequest } = RestApi; - -function placeCancelable(emitter) { - const req = new M2ApiRequest( - 'some/slow/large/resource', - { - method: 'GET', - } - ); - req.run(); - emitter.on('someevent', () => { - req.abortRequest(); - }); - return req.getResponse(); // AbortError -} -``` - -#### API - -`new M2ApiRequest(resourceUrl, opts)` - -: Creates a new `M2ApiRequest` class to a specific `resourceUrl` using the configuration values in `opts`. - See `request()` method [parameters][]. - -`run()` - -: Execute the request. - This must be run before `getResponse()` or `abortRequest()` can be called. - -`getResponse()` - -: Get the promise for the network operation. - This method can only be called after `run()` executes. - This method exists so that requests can reuse the promises from other requests. - - **Returns:** [`Promise`][] - `Promise` object for the result of the request. - -`abortRequest()` - -: Abort the network operation. - Multicasted requests will catch the `AbortError` and attempt to reuse a cached request. - Other requests will pass the `AbortError` rejection to the consumer. - - **Kind:** Instance method of M2ApiRequest - -`isRolling()` - -: Used to determine if a request intends to use the [rolling requests][] feature and override prior requests to the same resource. - - **Returns**: boolean - True if the request is rolling. False otherwise. - -[`Promise`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise -[`fetch()`]: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch -[response]: #response-handling -[error]: #error-handling -[multicasting]: #multicasting -[rolling requests]: #rolling-requests -[`Response`]: https://developer.mozilla.org/en-US/docs/Web/API/Response -[Magento REST endpoint]: https://devdocs.magento.com/guides/v2.3/rest/list.html -[fetch options]: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters -[`UVString`]: https://developer.mozilla.org/en-US/docs/Web/API/USVString -[`M2ApiRequest`]: #the-m2apirequest-class -[parameters]: #parameters diff --git a/pwa-devdocs/src/peregrine/reference/router/index.md b/pwa-devdocs/src/peregrine/reference/router/index.md deleted file mode 100644 index 6efc4c697e..0000000000 --- a/pwa-devdocs/src/peregrine/reference/router/index.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Router ---- - -The Peregrine Router is a client-side router that is designed to understand the different storefront routes within Magento 2. -If using Peregrine to bootstrap your PWA, it is configured automatically. If not, the Router can be manually consumed. - -## Props - -| Name | Required | Description | -| ------------- | :-------------------------------------------: | ------------------------------------------------------------------------------------------------------- | -| `apiBase` | check_box | Root URL of the Magento store (including protocol and hostname) | -| `using` | | Router implementation from React-Router. Possible values: `BrowserRouter`, `HashRouter`, `MemoryRouter` | -| `routerProps` | | Any additional props to pass to React-Router | -{:style="table-layout:auto"} - -## Example - -The following example shows the manual usage of the Router component: - -``` jsx -import ReactDOM from 'react-dom'; -import { Router } from '@magento/peregrine'; - -ReactDOM.render( - , - document.querySelector('main') -); -``` \ No newline at end of file diff --git a/pwa-devdocs/src/peregrine/reference/toasts/useToastContext/index.md b/pwa-devdocs/src/peregrine/reference/toasts/useToastContext/index.md deleted file mode 100644 index 2550588bdb..0000000000 --- a/pwa-devdocs/src/peregrine/reference/toasts/useToastContext/index.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: useToastContext ---- - - - -{% include auto-generated/peregrine/lib/Toasts/useToastContext.md %} - -## Examples - -### Using the Toast context logic - -Import the ToastContextProvider and wrap it around components that use Toast data and functionality. - -```jsx -// MyComponent.js - -import {ToastContextProvider} from '@magento/peregrine' -import {ToastContainer, AddToastComponent} from './MyToastComponents' - -... - -const MyComponent = () =>{ - - return ( - - - ) -} - -... -``` - -Call **useToastContext()** to get the current state of the toast store and a dispatch function. - -```jsx -// MyToastComponents.js - -import {useToastContext} from '@magnto/peregrine'; - -export const ToastContainer = () =>{ - const [toastState, toastDispatch] = useToastContext(); - - const toastData = toastState.map(toast=>{ - // Do something with the toast data - }) - - return// A component which would display based on state. - // A component which adds a toast using actions. - {toastData}-} - -export const AddToastComponent = () =>{ - return - ( -- // Some component that allows you to add toast data using the - // toastDispatch() function or useToast() hook -- ) -} - -``` diff --git a/pwa-devdocs/src/peregrine/reference/toasts/useToasts/index.md b/pwa-devdocs/src/peregrine/reference/toasts/useToasts/index.md deleted file mode 100644 index 093da9fff5..0000000000 --- a/pwa-devdocs/src/peregrine/reference/toasts/useToasts/index.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: useToasts ---- - - - -{% include auto-generated/peregrine/lib/Toasts/useToasts.md %} - -## Examples - -### Adding a toast - -Use the `addToast()` function from the API to add a toast to the toast store. - -{: .bs-callout .bs-callout-info} -If an `onAction()` or `onDismiss()` callback is provided, the implementer _must_ call the passed in `remove()` function. -If the `onDismiss()` callback is not provided, the toast is removed immediately. - -```jsx -const { toasterState, api } = useToast(); -const { addToast } = api; - -addToast({ - type: 'error', - message: 'An error occurred!', - actionText: 'Retry', - onAction: remove => { - async attemptRetry(); - remove(); - }, - onDismiss: remove => { - async doSomethingOnDismiss(); - remove(); - }, - icon:-}); -``` - -See also: [ToastContainer][] - -[toastcontainer]: {%link venia-ui/reference/components/ToastContainer/index.md %} diff --git a/pwa-devdocs/src/peregrine/routing/index.md b/pwa-devdocs/src/peregrine/routing/index.md deleted file mode 100644 index ba9aab5332..0000000000 --- a/pwa-devdocs/src/peregrine/routing/index.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Routing in PWA Studio ---- - -For web applications, routing is the process of mapping a URL to specific page resources. - -In a multi-page application, routing is performed on the server side. -Every URL request fetches new HTML from the server and the browser loads the entire page. -This approach is inefficient because the same assets get loaded every time site navigation occurs. - -For a single-page application (SPA), such as a progressive web app, routing is performed on the client side. -Single-page applications do not reload the browser during navigation. -Instead, the application uses the URL to fetch smaller pieces of data from the server and updates specific items on the page. - -## Routing for PWA Studio storefronts - -PWA Studio provides tools that support both server-side and client-side routing. - -### Server-side routing - -Server-side routing is accomplished using the [UPWARD][] configuration file. -Since the configuration file defines how the server responds to requests, -you can specify a different template to render each page type, such as a CMS page or a product details page. - -Early versions of the Venia storefront used this approach, but -in the current version, every page request now returns the same HTML with the application shell. -The application decides how the page should render based on the request. - -If you want a better idea of how UPWARD works, follow the [Hello UPWARD tutorial][]. - -### Client-side routing - -Client-side routing happens inside the storefront application. -When a user navigates inside the application, it updates the relevant pieces instead of refreshing the entire page to update content. - -Since Venia is a single-page application, it uses client-side routing for internal navigation. - -## How routing works in Venia - -This section goes over the routing flow implemented in Venia. -It is the default workflow for all new projects created using the scaffolding tool, -but it is not the only possible workflow for routing. - -### Initial request - -Venia's UPWARD server handles the initial request to the storefront application. -Its `upward.yml` configuration tells the server to return an `index.html` page created at build time by Webpack, via the [HtmlWebpackPlugin][]. -The content of this file is the same for all page types. - -After the browser loads the application shell, routing is handled client-side by React Router. - -### Routes component - -Used inside the [App component][], the [Routes component][] provides the switch logic for deciding which component to use to render the main content for the current route. - -Routes in a PWA do not have to correspond to routes in the old Magento storefront. Venia has routes not defined in the Magento backend, such as _Create account_ or full page _Checkout_. -These routes are assigned components which render content for those pages in the Routes component. - -### MagentoRoute component - -The [MagentoRoute component][] handles the routes that are Magento-specific, such as a product or category page. -It uses its [Peregrine talon][] counterpart to determine which component to display. - -### useMagentoRoute() talon - -The [`useMagentoRoute()`][] talon returns the correct component for a page type. It uses the [`getRouteComponent()`][] helper function to get the **root component** associated with a page type. -It uses the `resolveUnknownRoute()` function to determine the page type for a route and retrieves the root component associated with that type using a global `fetchRootComponent` function. -The `fetchRootComponent` function is autogenerated at build time by the Buildpack RootComponentsPlugin, which searches for RootComponents in the project and builds a manifest. - -### resolveUnknownRoute() - -The [`resolveUnknownRoute()`][] function is a utility function for fetching page type information from the backend Magento server using a GraphQL query. -The `getRouteComponent()` function uses the information from this query to get the correct root component from an object that maps page types to root components. - -[upward]: {%link venia-pwa-concept/features/modular-components/index.md %} -[hello upward tutorial]: {%link tutorials/hello-upward/simple-server/index.md %} -[peregrine talon]: {%link peregrine/talons/index.md %} - -[app component]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/App/app.js -[routes component]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/Routes/routes.js -[magentoroute component]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/MagentoRoute/magentoRoute.js -[`usemagentoroute()`]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/talons/MagentoRoute/useMagentoRoute.js -[`getroutecomponent()`]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/talons/MagentoRoute/getRouteComponent.js -[`resolveunknownroute()`]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/Router/resolveUnknownRoute.js -[htmlwebpackplugin]: https://webpack.js.org/plugins/html-webpack-plugin/ diff --git a/pwa-devdocs/src/peregrine/talons/index.md b/pwa-devdocs/src/peregrine/talons/index.md deleted file mode 100644 index 9487201abb..0000000000 --- a/pwa-devdocs/src/peregrine/talons/index.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Talons ---- - -Most [React component][] contain two distinct sections: a section for logic and a presentational section. - -The logic section contains code for generating new values from props, maintaining local state, and lifecycle or side effect methods. -This section can be considered the "brains" of the component. - -The content section of a React component contains code that defines the component's DOM structure. -It often uses values from the logic part of the component to pass down into another component or display using HTML elements. - -PWA Studio separates these two sections into distinct components with specific concerns: a Venia UI component and a Peregrine Talon. - -## Peregrine talon overview - -Peregrine talons are the logic component counterparts for Venia UI components. -Each talon in Peregrine is designed to provide data or perform side effects for a specific Venia UI component. - -For example, the [`SearchBar`][] component uses the [`useSearchBar()`][] talon to get initial values and functions it needs to handle changes in focus or search term value. -The `useSearchBar()` talon also keeps track of the component's `expanded` state, which determines how the search bar looks. - -## Talons versus hooks - -Talons are a PWA Studio concept that represent a specialized type of React hook. - -Peregrine **hooks**, such as `useDropdown()` and `useWindowSize()`, are designed to be re-usable pieces of code, but -Peregrine **talons** are designed to fulfill the logic needs of individual Venia UI components. -This means that each talon corresponds to a single Venia component and is not useful outside the component. -If a talon needs to use functionality identical to another talon, it is provided by a Peregrine hook. - -For example, the functionality provided by the `useHeader()` talon is only relevant to the `Header` component. - -## Using talons - -Talons are not re-usable hooks, but they make it easier to work with UI components by providing standard functionality. -This lets developers focus on developing the presentation DOM and CSS pieces of a component. - -Venia UI components use talons by default, so developers can use Venia UI components as is without worrying about talons. -If developers want to change how a Venia UI component looks, they can import its associated talon into a new or modified UI component of the same type. - -### Talon props and returned object - -Talons use many of the same props as its Venia UI component counterpart. -These props are passed into the talon as a single object and are used to generate new values or perform side effects. - -The return value after calling a talon is an API object that UI components can destructure for values to display or assign to events, such as `onClick` or `onHover` functions. - -### Example - -The following code snippet comes from Venia's [`Pagination`][] UI component: - -``` jsx - -... - -import { usePagination } from '@magento/peregrine/lib/talons/Pagination/usePagination'; - -... - -const Pagination = props => { - const { currentPage, setPage, totalPages } = props.pageControl; - - const talonProps = usePagination({ - currentPage, - setPage, - totalPages - }); - - const { - handleLeftSkip, - handleRightSkip, - handleNavBack, - handleNavForward, - isActiveLeft, - isActiveRight, - tiles - } = talonProps; - - ... -} -``` - -[react component]: https://reactjs.org/docs/components-and-props.html -[`usesearchbar()`]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/talons/SearchBar/useSearchBar.js -[`searchbar`]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/SearchBar/searchBar.js -[`pagination`]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/Pagination/pagination.js diff --git a/pwa-devdocs/src/pwa-buildpack/configuration-management/index.md b/pwa-devdocs/src/pwa-buildpack/configuration-management/index.md deleted file mode 100644 index 1e6481838d..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/configuration-management/index.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: Configuration management ---- - -The PWA buildpack library provides small tools to configure your environment and larger, overall workflows that a developer has to configure and control. - -These configurations differ across projects and different environments within those projects. -For example, environments for development, testing, staging, and production are configured to support different behaviors. - -## The `.env` file - -Like the rest of PWA Studio, buildpack uses environment variables as its central source of configuration settings. -A PWA Studio project using buildpack requires a [`.env` file][] in its root directory. -Each line in the file contains a configuration using the following form: - -```text -NAME=value -``` - -In any script in any programming language, you can access these environment variables directly by sourcing the file as a legal POSIX shell script. - -## Command Line Interface (CLI) - -Buildpack provides a [`buildpack` CLI][] for creating `.env` files and validating environments. -It also provides library methods for connecting environment management workflows with other tools. - -Using these provided tools, you can keep global configuration values in a central location and propagate them throughout your project. -This lets you pass common settings down to different library functions without tightly coupling those settings together. - -## Configuration management rationale - -PWA Studio follows the principle that _all configuration that **can** be environment variables, **should** be environment variables_. - -Environment variables are portable, cross-platform, and reasonably secure. -They can be individually overridden to give the user a great deal of control over a complex system. -The [twelve-factor app][] methodology recommends storing config in the environment as its third factor. - -Many tools use environment variables strictly as edge-case overrides and store their canonical configuration in other formats because -under the strict POSIX definition, environment variables have some limitations: - -- An environment variable name is case insensitive. -- An environment variable's value can only be a string. -- Environment variables cannot be nested nor schematized, so they have no built-in data structures. -- Environment variables all belong to a single namespace, and every running process has access to all of them. - -These drawbacks are serious enough that some applications use alternate formats, such as: - -- `XML` -- `JSON` -- `YAML` -- `INI` / `TOML` -- `.properties` files in Java -- `.plist` files in MacOS -- PHP associative arrays -- Apache directives - -These formats have the following advantages over environment variables: - -1. They are a standard human-readable file format -2. They can support nesting and/or namespacing to organize values -3. They support data types and metadata - -However, none of these formats have _won_ and become an undisputed replacement for environment variables. -Each one has its own set of quirks and undefined behaviors. -None of them are deeply integrated with OS, shell, and container environments, and -they often do not work consistently across language runtimes. - -PWA Studio chooses to use environment variables, while providing simple tools for file format, namespacing, and validation. - -A centralized configurator passes on formatted pieces of the environment to specific tools as parameters, so -these tools do not need to know the specifics of the configuration scheme. -Entry point scripts, such as `server.js` and `webpack.config.js`, can use the [`loadEnvironment()`][] tool to deserialize environment variables into any kind of data structure, while storing persistent values in an `.env` file in the project root directory. - -Buildpack combines the features of several tools: - -- [dotenv][] for managing environment variables with `.env` files -- [envalid][] for describing, validating, and making defaults for settings -- [camelspace][] for easily translating configuration between flat environment variables and namespaced objects - -## Best practices - -The **config rule** in the [twelve-factor app][] methodology distinguishes configuration that "does not vary between deploys" from configuration that does. -It requires that configuration that does change between deploys be stored in the environment. -PWA Studio does not make such a distinction. -For config that must never vary, the PWA project maintainer can hardcode that configuration in the entrypoint scripts what use `loadEnvironment()`. - -To have environment-variable-based configuration management and enjoy the benefits of file format, namespacing, and validation at the same time, it's important to use `loadEnvironment()` in a certain way. - -### Configuration object - -The purpose of a function such as [`loadEnvironment()`][] is to keep configuration organized without tightly coupling a system to a manager object. -To achieve this, it is important to use `loadEnvironment()` and the `Configuration` object it produces at the "top level" or entry point of a program. - -Avoid passing a `Configuration` object directly to other tools. -These tools should be usable without `loadEnvironment()`. -It is always the responsibility of an outer function to pass plain configuration to an inner dependency. - -Use the `Configuration` object only when moving between logic layers: - -**Bad**: passing the `Configuration` object to library methods - -```js -await PWADevServer.configure({ - publicPath: config.output.publicPath, - graphqlPlayground: true, - projectConfig: loadEnvironment(__dirname) -}, config); -``` - -The same principle holds when creating your own utilities. - -**Bad**: expecting a `Configuration` object in a library function - -```js -class MyWebpackPlugin { - constructor(config) { - this.options = config.section('myWebpackPlugin'); - } -} -``` - -**Good**: passing plain objects created by the Configuration object - -```js -const projectConfig = loadEnvironment(__dirname); -await PWADevServer.configure({ - publicPath: config.output.publicPath, - graphqlPlayground: true, - ...projectConfig.sections( - 'devServer', - 'imageService', - 'customOrigin' - ), - ...projectConfig.section('magento') -}, config); -``` - -### Naming convention - -POSIX standard environment variables may not be case sensitive and may not allow very many special characters. - -The best policy is to use `ALL_CAPS_UNDERSCORE_DELIMITED_ALPHANUMERIC_VARIABLE_NAMES` when defining environment variables directly. -**Buildpack will ignore any environment variables which do not follow this convention.** - -Buildpack converts between this strict all-caps format (also known as **SCREAMING_SNAKE_CASE**) and a more convenient JavaScript object which can be nested at any level of delimiter. -When defining new environment variables, make their names long and safely namespace them with prefixes as long as necessary. -`Configuration` objects have `.section()` and `.sections()` methods to create targeted, small JavaScript objects with shorter names. - -### Fallback - -By default, buildpack respects three levels of "fallback" values: - -1. Currently declared environment variables, which can be populated on process startup -2. Values from the `.env` file in the project root -3. Defaults from the metadata in the [Project Environment Definitions][] - -Additional layers of configuration and on-disk fallback are discouraged. -Inside scripts, environment variables may be combined and merged, but -too much fall-through of project configuration can result in unpredictable and hard-to-maintain runtime configuration. - -### Project environment definitions - -All the environment variables expected and/or used by buildpack are defined in [`packages/pwa-buildpack/envVarDefinitions.json`][]. - -This file is used for: - -- Creating a self-documenting `.env` file -- Validating environments -- Deprecating and supporting older settings which have changed - -If you are contributing to the PWA Studio project and want to add new functionality that should be configured via the environment or change any environment configuration, follow these best practices: - -- Define any new variables in the `packages/pwa-buildpack/envVarDefinitions.json` file. - The variable definition object follows the API of [envalid][], with the addition of a `type` property indicating the `envalid` method to use. -- Organize variables into named sections in the `sections` list. -- Use the namespacing practices encouraged by [camelspace][] and `loadEnvironment()`. - - For example, a new utility `goodStuff()` might demand environment variables starting with `GOOD_STUFF_`, - and `packages/pwa-buildpack/envVarDefinitions.json` might include a new section in its `sections` list. -- After making any changes to `packages/pwa-buildpack/envVarDefinitions.json`, record them in the `changes` list in that file. - - - Change entries are objects which include: - - `type`: **Required.** The type of the change, either `removed` or `renamed`. No other types of change need change entries. - - `name`: **Required.** The affected environment variable name. - - `dateChanged`: **Required.** The date the change entry was added, in a format parseable by the JavaScript `Date` constructor. - - `warnForDays`: **Optional**, default `180`. A number of days that the warning should keep logging on every run, counting from the `dateChanged`. The default _and_ maximum is 180 days, so use this property only if you want the change to log for a _shorter_ time than default. This prevents an old, out-of-date warning message from cluttering logs long after the user no longer needs to see it. - - `removed` entries should include a human-readable `reason`. - **After removing a variable definition, leave the `removed` entry permanently** to log an error if the old variable is found, encouraging out-of-date installations to upgrade. - - `renamed` entries should include the old name as `name`, and the new name as `updated`. - They must also include a `supportLegacy` boolean. - If this is `true`, then `loadEnvironment()` will continue to support the old value while logging a warning, until either the new variable name has a value, or the change entry expires. - -[`buildpack` cli]: {%link pwa-buildpack/reference/buildpack-cli/index.md %} -[`loadenvironment()`]: {%link pwa-buildpack/reference/buildpack-cli/load-env/index.md %} -[project environment definitions]: {%link pwa-buildpack/reference/environment-variables/core-definitions/index.md %} - -[`.env` file]: https://www.npmjs.com/package/dotenv -[dotenv]: https://www.npmjs.com/package/dotenv -[twelve-factor app]: https://12factor.net/config -[envalid]: https://npmjs.com/package/envalid -[camelspace]: https://npmjs.com/package/camelspace -[`packages/pwa-buildpack/envvardefinitions.json`]: https://github.com/magento/pwa-studio/blob/develop/packages/pwa-buildpack/envVarDefinitions.json diff --git a/pwa-devdocs/src/pwa-buildpack/index.md b/pwa-devdocs/src/pwa-buildpack/index.md deleted file mode 100644 index 28c6578d9e..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/index.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: PWA Buildpack ---- - -PWA Buildpack is a build and development tool and library for Magento Progressive Web Apps. -Use the PWA Buildpack project to set up and configure your local environment for PWA development. - -## Setup - -Follow the [Project setup tutorial] to set up a PWA development environment. - -If you are having trouble setting up your environment, see the [Troubleshooting page]. - -## Contribute - -Visit the [`pwa-buildpack`] package in the PWA Studio repository to contribute to this project. - -[`pwa-buildpack`]: https://github.com/magento/pwa-studio/tree/master/packages/pwa-buildpack -[Project setup tutorial]: {% link pwa-buildpack/project-setup/index.md %} -[Troubleshooting page]: {% link pwa-buildpack/troubleshooting/index.md %} \ No newline at end of file diff --git a/pwa-devdocs/src/pwa-buildpack/project-setup/index.md b/pwa-devdocs/src/pwa-buildpack/project-setup/index.md deleted file mode 100644 index 66ceb585b4..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/project-setup/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Project setup ---- - -## Documentation unpublished - -Sorry! -We have unpublished this topic because the content was out of date with the current state of the project. - -Please use the instructions under [Venia storefront setup][] as a starting point for working with the PWA Studio tools. - -[Venia storefront setup]: {%link venia-pwa-concept/setup/index.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-custom-origin/index.md b/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-custom-origin/index.md deleted file mode 100644 index 89d9748b8b..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-custom-origin/index.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: create-custom-origin ---- - -The `create-custom-origin` is a [`buildpack`][] CLI subcommand which creates a unique local hostname and trusted SSL certificate for your project. - -Usage example with `npx`: - -```sh -npx @magento/pwa-buildpack create-custom-origin -``` - -This feature requires administrative access, so -it may prompt you for an administrative password at the command line. -It does not permanently elevate permissions for the dev process, but -instead, it launches a privileged subprocess to execute one command. - -{: .bs-callout .bs-callout-info} -**Note:** -This command should be used only in a development environment and never as part of a production deployment process. - -## Why PWA development requires a secure custom origin - -### HTTPS is required - -Some PWA features, such as ServiceWorkers and Push Notifications, are only available on HTTPS secure domains. -Some browsers make exceptions for the domain `localhost`, but this is non-standard. - -HTTPS development is becoming the norm, but -creating a self-signed certificate and configuring your server and browser to support this is a complex process. - -The `create-custom-origin` command automates this process reliably on most operating systems. -It uses [devcert][] to edit your local hostfile, create and manage certificates, and try to configure web browsers to "trust" the certificate. -This prevents security errors from showing up in browsers. - -In the future, browsers will require trust, as well as SSL itself, to enable some features. - -{: .bs-callout .bs-callout-info} -**Note:** -PWADevServer uses OpenSSL to generate these certificates; your operating system must have an `openssl` command of version 1.0 or above to use this feature. - -### Unique domains prevent ServiceWorker collisions - -PWA features, such as ServiceWorkers, use the concept of a 'scope' to separate installed ServiceWorkers from each other. -A scope is a combination of a domain name, port, and path. -If you use `localhost` for developing multiple PWAs, you run the risk of Service Workers overriding or colliding with each other. - -## Customization - -Use environment variables in the `CUSTOM_ORIGIN_` namespace to change the behavior of the `create-custom-origin` command. - -| Environment Variable Name | Default Value | Description | -| --- | --- | --- | -| `CUSTOM_ORIGIN_ENABLED` | `true` | Enable the custom origin feature | -| `CUSTOM_ORIGIN_ADD_UNIQUE_HASH` | `true` | Add a unique hash string to the custom origin. | -| `CUSTOM_ORIGIN_SUBDOMAIN` | | Allows you to manually specify the subdomain prefix of the custom origin instead of using the package name. | -| `CUSTOM_ORIGIN_EXACT_DOMAIN` | | Allows you to specify the _exact_ domain of the custom origin instead of a subdomain under `.local.pwadev`. | - -Set these variables permanently in your `.env` file, or argue them at the command line for overrides: - -```sh -CUSTOM_ORIGIN_EXACT_DOMAIN="my.pwa" \ -npx @magento/pwa-buildpack create-custom-origin . -``` - -### Unique hash - -If `CUSTOM_ORIGIN_ADD_UNIQUE_HASH` is set to `true`, the `create-custom-origin` command adds a unique hash string to the custom origin. -This string is based on the filesystem location. - -This naturally separates domains when running multiple project folders on one developer machine. - -[`buildpack`]: {%link pwa-buildpack/reference/buildpack-cli/index.md %} - -[devcert]: https://github.com/davewasmer/devcert diff --git a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-env-file/index.md b/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-env-file/index.md deleted file mode 100644 index de4a4cf411..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-env-file/index.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: create-env-file ---- - -Whether its a new storefront project or a fresh PWA Studio repository clone, PWA Studio requires a `.env` file to set up the environment for your site. - -The `create-env-file` subcommand for the [`buildpack`][] CLI command automatically creates this file using pre-defined environment variables and default values. - -Usage example with `npx`: - -```sh -npx @magento/pwa-buildpack create-env-file -``` - -This command generates a `.env` file in the specified directory. - -The `.env` file follows the `dotenv` file format and includes documentation comments for the environment variable declarations. -The `create-env-file` command uses the [`envVarDefinitions.json`][] file in the PWA Studio source code to create this file. - -## Command flags - -| Name | Description | -| ---------------- | -------------------------------------------------------------------- | -| `--use-examples` | Use `example` values for all variables in the generated `.env` file. | - -## Defining variables for the `.env` file - -Use any of the following methods to define the generated variables in the `.env` file: - -- Set one or more variables defined in the [`envVarDefinitions.json`][] file before running `create-env-file` to override the `default` values written to the `.env` file. - These values can be set using shell scripting or other OS-specific methods. -- Call `create-env-file` with the `--use-examples` flag to use the `example` values for variables declared in the `envVarDefinitions.json` file. - Calling the `create-env-file` command without this flag still writes the `example` values to the `.env` file, but - the entry is commented out. - -Variables with no environment definitions nor `example` values in the `envVarDefinitions.json` file are declared in the `.env` file with an empty value. - -Example: - -```text -MAGENTO_BACKEND_URL= -``` - -## Programmatic API - -Adding the `@magento/pwa-buildpack` dependency to your project gives you access to the programmatic API for creating the `.env` file. - -### `createDotEnvFile(directory, options)` - -Uses the current environment variables and [`envVarDefinitions.json`][] file to generate the contents of a `.env` file. - -#### Example - -```js -const { createDotEnvFile } = require('@magento/pwa-buildpack'); - -const fileContents = createDotEnvFile(process.cwd()); -``` - -#### Parameters - -| Parameter | Data type | Description | -| --------------------- | -------------------------------------------- | ---------------------------------------------------------- | -| `dirOrEnv` | `string` path or a `process.env`-like object | Provides the path to the project root. | -| `options` | `object` | An object containing additional options. | -| `options.logger` | `object` | The object to use for logging. | -| `options.useExamples` | `boolean` | Whether to populate the `.env` file with `example` values. | - -If `dirOrEnv` is a string and the specified directory contains a `.env` file, it is read before being overwritten to preserve existing variables. - -If `dirOrEnv` is a `process.env`-like object, the `.env` file is not parsed before being overwritten. - -#### Return value - -The return value is the string value of a `.env` file. - -Parse this value using the `dotenv` API or write it out to the filesystem. - -[`buildpack`]: {%link pwa-buildpack/reference/buildpack-cli/index.md %} - -[`envvardefinitions.json`]: https://github.com/magento/pwa-studio/blob/develop/packages/pwa-buildpack/envVarDefinitions.json diff --git a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-project/index.md b/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-project/index.md deleted file mode 100644 index cc1741b3be..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-project/index.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: create-project ---- - -The `create-project` sub-command of the [`pwa-buildpack`][] CLI is a [scaffolding][] tool used to create a fresh PWA Studio app in a new project directory. - -Normally this command is used indirectly through the `@magento/pwa` scaffolding tool. -The tool collects the parameter values through its interactive prompt and passes them on to the command as options. - -This tool is also available for developers or third-party automation tools to use directly. - -**Example:** Using the command with `npx`: - -```sh -npx @magento/pwa-buildpack create-project ./new-pwa \ - --name @magezilla/new-pwa \ - --template venia-concept \ - --backend-url https://local.magento \ - --author MageZilla -``` - -This example creates a new project in the `./new-pwa` folder. -The package metadata for the project lists the project name as `@magezill/new-pwa` and the author as `MageZilla`. -It also creates a `.env` file with the backend URL set to `https://local.magento`. - -After creating the project, it installs the package dependencies, including the Venia, Peregrine and Buildpack libraries needed to build the application. - -## Running the command - -Use the `npx` tool to download the current version and execute the command: - -```sh -npx @magento/pwa-buildpack create-project [ ...] -``` - -The first argument in the command is the directory for the new project. -If the directory does not exist, it is created. -If the directory is not empty, files that the tool generates overwrite the existing files. - -The directory can be the current directory `.`, which is the default if no first argument is passed. - -{: .bs-callout .bs-callout-warning} -Do not install buildpack globally on your development system to use this command. -This can cause incompatible versions between a product version and the global version. - -### Command options - -Run `npx @magento/pwa-buildpack create-project --help` to see the list of command options. - -You can specify these options in any order after `buildpack create-project `. - -| Name | Description | -| --------------- | -------------------------------------------------------------------------------------------------------------------------- | -| `--template` | NPM package or directory name of the template to use for the new project. **Currently only `venia-concept` is supported.** | -| `--backend-url` | URL value, set in the `.env` file, of the backing Magento instance to use in developer mode. | -| `--name` | Name for the `package.json` `"name"` field. Must be a legal NPM package name. Defaults to directory name. | -| `--author` | Text for the `package.json` `"author"` field. Usually a name followed by an email address in angle brackets. | -| `--install` | Whether to install dependencies after project creation. Defaults to `true`. | -| `--npm-client` | NPM client used to manage this repository. Both `npm` (the default) and `yarn` are supported. | - -{: .bs-callout .bs-callout-warning} -**Note:** -Do not use this command as part of a production deployment process. -Use it only in a development environment. - -[`pwa-buildpack`]: {%link pwa-buildpack/reference/buildpack-cli/index.md %} -[scaffolding]: {%link pwa-buildpack/scaffolding/index.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/index.md b/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/index.md deleted file mode 100644 index 30eaf469d3..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/index.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: buildpack Command Line Interface ---- - -The `buildpack` command is a command line toolkit with subcommands. - -Running it with no arguments produces the following output: - -```text -buildpack - -Commands: - buildpack create-custom-origin Get or create a secure, unique - hostname/port combination and a - trusted SSL certificate for local - development, which enables all PWA - features. - buildpack create-env-file Generate a .env file in the provided - directory to store project - configuration as environment variables - variables - buildpack load-env Load and validate the current - environment, including .env file if - present, to ensure all required - configuration is in place. - -Options: - --version Show version number [boolean] - --help Show help [boolean] - -Invoke buildpack with a subcommand (eg. `buildpack create-env-file`) and the arguments to that subcommand. -``` - -## Running the `buildpack` command - -### As a project dependency - -A project with the `@magento/pwa-buildpack` dependency installed can use the `buildpack` command in its NPM scripts: - -```json -"scripts": { - "load-env": "buildpack load-env ." -} -``` - -With this example, you can run `npm run-script load-env` or `yarn run load-env` to use the local copy of the `buildpack` CLI. - -### Using `npx` - -Invoke `buildpack` directly using NPM's `npx` tool, which installs packages and runs their CLIs in a single command: - -```sh -npx @magento/pwa-buildpack -``` - -{: .bs-callout .bs-callout-warning} -It is not recommended to globally install buildpack with `yarn global add` or `npm install --global`. -Individual projects should use their own versions, to guarantee expected behavior. - -## Available subcommands - -The `buildpack` CLI provides the following subcommands: - -- [`create-custom-origin`][] - Gets or creates a trusted SSL certificate for local PWA development. -- [`create-env-file`][] - Generates a new `.env` file in the current directory. -- [`load-env`][] - Loads and validates the current environment. - -[`create-custom-origin`]: {%link pwa-buildpack/reference/buildpack-cli/create-custom-origin/index.md %} -[`create-env-file`]: {%link pwa-buildpack/reference/buildpack-cli/create-env-file/index.md %} -[`load-env`]: {%link pwa-buildpack/reference/buildpack-cli/load-env/index.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/load-env/index.md b/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/load-env/index.md deleted file mode 100644 index 6e0ad5b889..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/load-env/index.md +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: load-env ---- - -The `load-env` subcommand for the [`buildpack`][] CLI command loads and validates the local `.env` file according to the variable declarations in the [`envVarDefinitions.json`][] file. -This includes any deprecated or changed settings. - -When loading from `.env`, `buildpack` does not override previously declared variables. - -## Command flags - -| Name | Description | -| ----------------- | ----------------------------------------------------------------------------------------- | -| `--core-dev-mode` | Used only by the core PWA Studio repository for quick setups of the core dev environment. | - -The `--core-dev-mode` flag tells `buildpack` to run `buildpack create-env-file --use-examples` if an existing `.env` file does not exist in the given directory path. - -## Usage tips - -- Use the `load-env` command in NPM scripts instead of directly invoking it with `npx` -- Use a command, shell script, or spawned subprocess to override individual environment variables at start time. -- The command does not require a `.env` file to be present. - - If a `.env` file is not present, the environment is still valid if another process or command sets the required variables. - If the file is not present and the variable `NODE_ENV` is not set to `production`, `buildpack` logs a warning. - -## Programmatic API - -Adding the `@magento/pwa-buildpack` dependency to your project gives you access to the programmatic API for loading the `.env` file. - -### `loadEnvironment(dirOrEnv, [logger])` - -Loads a given directory's `.env` file and provides a [configuration object][]. - -#### Example - -```js -const { loadEnvironment } = require('@magento/pwa-buildpack'); - -const configuration = loadEnvironment(process.cwd()); -``` - -#### Parameters - -| Name | Data type | Description | -| ---------- | ------------------------------------- | ---------------------------------------------------------------- | -| `dirOrEnv` | `string` path or `process.env` object | Provides a path to the project root. | -| `logger` | `object` | An optional logger object to use instead of the default console. | - -If the `dirOrEnv` parameter is a `process.env` object, it will not attempt to parse a `.env` file. - -#### Return value - -The `loadEnvironment()` function returns a configuration object. - -### Configuration object - -Use the configuration object returned by `loadEnvironment()` as a single source of truth for configuration. - -#### Properties - -| Name | Alias | Description | -| --------------- | :------: | ------------------------------ | -| `env` | - | The raw environment object | -| `isProduction` | `isProd` | True if `NODE_ENV=production` | -| `isDevelopment` | `isDev` | True if `NODE_ENV=development` | -| `isTest` | - | True if `NODE_ENV=test` | - -#### Methods - -The configuration object provides methods that return settings in specific namespaces. -This lets you pass smaller objects instead of a single, plain object full of global configuration values. - -`section(sectionName)` -: Returns a plain object with environment variables in the `sectionName` namespace. -The property keys are [camelCased][] for convenience. - -`sections(...sectionNames)` -: Returns a plain object with environment variables from the specified namespaces. -The namespaces are assigned to different camelCased properties named after the section name. - -`all()` -: Returns the entire environment object, camelCased for convenience, with no namespace separations. - -### Full example script - -The following example is a script that starts an [UPWARD][] server using configuration values loaded from the environment and `.env` file in the project path. - -```js -import { loadEnvironment } from '@magento/pwa-buildpack'; - -// Give `loadEnvironment` the path to the project root. -// If the current file is in project root, use the Node builtin `__dirname`. -const configuration = loadEnvironment('/Users/me/path/to/project'); - -// `loadEnvironment` has now read the contents of -// `/Users/me/path/to/project/.env` and merged it with any environment -// variables that were alredy set. - -// Create an UPWARD server using env vars that begin with `UPWARD_JS_` -createUpwardServer(configuration.section('upwardJs')); - -// If these environment variables are set: -// -// UPWARD_JS_HOST=https://local.upward/ -// UPWARD_JS_PORT=8081 -// -// then `configuration.section('upwardJs')` produces this object: -// -// { -// host: 'https://local.upward', -// port: '8081' -// } -// -// No other environment variables are included in this object unless they begin -// with `UPWARD_JS_` which is the equivalent of `upwardJs` camel-cased. - - -// The .all() method turns the whole environment into an object, with all -// CONSTANT_CASE names turned into camelCase names. -const allConfig = configuration.all(); - -// This object will have one property for each set environment variable, -// including the UPWARD variables named above. -// But `configuration.all()` does not namespace them, they have longer names: -// -// { -// upwardJsHost: 'https://local.upward', -// upwardJsPort: '8081' -// } -// -// This huge object defeats the purpose of loadEnvironment() and should -// only be used for debugging. - -// Instead, let's create an UPWARD server combining two environment variable -// sections with hardcoded overrides to some values. -createUpwardServer({ - ...configuration.section('upwardJs'), - ...configuration.section('magento'), - bindLocal: true -}); - -// This uses JavaScript object spreading to combine several sections of -// configuration and override a value. -// If the environment contains these values: -// -// UPWARD_JS_HOST=https://local.pwadev -// UPWARD_JS_PORT=443 -// UPWARD_JS_BIND_LOCAL= -// MAGENTO_BACKEND_URL=https://local.magento -// -// Then the above code passes the following object to `createUpwardServer`: -// -// { -// host: 'https://local.pwadev', -// port: '443', -// backendUrl: 'https://local.magento', -// bindLocal: true -// } - - -// The `sections()` method can split an env object into named subsections: -createUpwardServer(configuration.sections('upwardJs', 'magento')); - -// Given the same environment variables as above, this code will pass the -// following to `createUpwardServer`: -// -// { -// upwardJs: { -// host: 'https://local.pwadev', -// port: '443', -// bindLocal: '' // the null string is used as a falsy value -// }, -// magento: { -// backendUrl: 'https://local.magento' -// } -// } -// -// (The above is not the actual config object format for `createUpwardServer`, -// but if it was, that's how you'd make it.) - -// Use the convenience properties `isProd` and `isDev` instead of testing -// `process.env.NODE_ENV` directly: -if (configuration.isDev) { - console.log('Development mode'); -} -``` - -[upward]: {%link technologies/upward/reference-implementation/index.md %} -[`buildpack`]: {%link pwa-buildpack/reference/buildpack-cli/index.md %} -[configuration object]: {%link pwa-buildpack/configuration-management/index.md %} - -[`envvardefinitions.json`]: https://github.com/magento/pwa-studio/blob/develop/packages/pwa-buildpack/envVarDefinitions.json -[camelcased]: https://npmjs.com/package/camelspace diff --git a/pwa-devdocs/src/pwa-buildpack/reference/configure-webpack/index.md b/pwa-devdocs/src/pwa-buildpack/reference/configure-webpack/index.md deleted file mode 100644 index 0badf28d3e..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/configure-webpack/index.md +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: configureWebpack ---- - -## `configureWebpack(options)` - -A function that returns a Webpack configuration object. - -Import and call `configureWebpack()` in your project's `webpack.config.js` file to generate a Webpack configuration object suited to your PWA Studio project and its dependencies. - -**Returns:** -A [Promise][] that resolves to a configuration object for webpack. - -The generated configuration object tells Webpack how to process the project's source code and generate bundles. -It is a [complete Webpack configuration object][] that is ready for immediate use. - -You can also modify it in your `webpack.config.js` before returning it out of your own configure function. - -{: .bs-callout .bs-callout-info} -`configureWebpack()` is asynchronous. -Webpack accepts a Promise for a configuration, so -you can return the result of `configureWebpack` directly out of the exported function in `webpack.config.js`. -If you want to modify the configuration, you must use `await`. - -### Parameters - -| Name | Type | Description | -| ----------------- | ---------- | ------------------------------------------------------------------------ | -| `options` | `Object` | Options for generating the configuration object | -| `options.context` | `String` | _Required._ The path of the project root directory | -| `options.vendor` | `String[]` | A list of module names to force Webpack to include in a "commons" bundle | -| `options.special` | `Object` | An object that maps module names to a set of configuration. | - -{: .bs-callout .bs-callout-info} -To make your project performant, limit the `options.vendor` list to strictly necessary dependencies required by most or all modules. - -### Special flags - -The `options.special` parameter tells `configureWebpack()` to create special configurations for specific modules. - -By default, Webpack treats the source code of your project very differently than the dependency code. -Webpack does so because public NPM modules are not reliably compatible with advanced JavaScript features. -Developers get around this by customizing the Webpack configuration rules. - -`configureWebpack()` offers a simple API: for each module you want to treat special, add these named flags. -It will adjust Webpack configuration to run that module and its files through additional build steps. - -#### `esModules` flag - -If `true`, `configureWebpack()` generates the configuration for processing `.js` files from the named module as ES Modules. -This allows Webpack to use advanced optimizations on them, but -it may fail if the module contains noncompliant code. - -#### `cssModules` flag - -If `true`, `configureWebpack()` generates the configuration for processing `.css` files from the named module as CSS Modules. -This allows Webpack to maintain a separate namespace for every CSS Module, including modules inside dependencies. - -This prevents style collisions between sibling modules, but -it may fail if the module does not actually use CSS Module patterns. - -#### `graphqlQueries` flag - -If `true`, `configureWebpack()` generates the configuration that tells webpack to look for `.graphql` files in the dependency and precompile them for better performance. - -All GraphQL query files in all modules will appear in the GraphQL playground, but -this setting allows you to choose which dependencies have queries you want to debug. - -#### `rootComponents` flag - -If `true`, `configureWebpack()` generates the configuration that tells webpack to look for RootComponent files in a module's `src/RootComponents` or `RootComponents` subdirectories. - -This allows a third-party dependency to provide RootComponents to your app automatically, but -it may slow down the build if you add too many modules that do not have RootComponents. - -#### `upward` flag - -If `true`, `configureWebpack()` generates the configuration that tells weback to look for an `upward.yml` file in a module's root directory and merge it with the project's root `upward.yml` file. - -This lets third-party dependencies contribute to UPWARD behavior, but -it may cause collisions or merge problems if the UPWARD files contradict each other. - -## Example - -The following example is taken from `packages/venia-concept/webpack.config.js`. -It represents a typical setup using `configureWebpack` to generate Webpack config. -It also demonstrates that `configureWebpack` returns a recognizable Webpack object, which you can modify. - -```js -const { configureWebpack } = require('@magento/pwa-buildpack'); - -module.exports = async env => { - const config = await configureWebpack({ - context: __dirname, - vendor: [ - '@apollo/react-hooks', - 'apollo-cache-inmemory', - 'apollo-cache-persist', - 'apollo-client', - 'apollo-link-context', - 'apollo-link-http', - 'informed', - 'react', - 'react-dom', - 'react-feather', - 'react-redux', - 'react-router-dom', - 'redux', - 'redux-actions', - 'redux-thunk' - ], - special: { - // Treat code originating in the `@magento/peregrine` module - // as ES Modules, just like the project source itself. - '@magento/peregrine': { - esModules: true - } - // Treat code originating in the `@magento/venia-ui` as though - // it uses ES Modules, CSS Modules, GraphQL queries, RootComponents, - // and UPWARD definitions. This is the right set of flags for a UI - // library that makes up the bulk of your project. - '@magento/venia-ui': { - cssModules: true, - esModules: true, - graphqlQueries: true, - rootComponents: true, - upward: true - } - }, - env - }); - - // configureWebpack() returns a regular Webpack configuration object. - // You can customize the build by mutating the object here, as in - // this example: - config.module.noParse = [/braintree\-web\-drop\-in/]; - // Since it's a regular Webpack configuration, the object supports the - // `module.noParse` option in Webpack, documented here: - // https://webpack.js.org/configuration/module/#modulenoparse - - return config; -}; -``` - -[complete webpack configuration object]: https://webpack.js.org/configuration/ -[promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise diff --git a/pwa-devdocs/src/pwa-buildpack/reference/environment-variables/core-definitions/index.md b/pwa-devdocs/src/pwa-buildpack/reference/environment-variables/core-definitions/index.md deleted file mode 100644 index 47d1add86d..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/environment-variables/core-definitions/index.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Core environment variable definitions ---- - -Environment variable definitions are used for validation and documentation of the [configuration management system][] of PWA Studio. - -Build scripts normally use the [values set in the current environment][], but it is sometimes necessary to use the definitions themselves, such as when an extension defines its own global config variables. - -There are two ways to access the environment variable definitions object: - -- Third-party code should use the builtin target [`envVarDefinitions`][] when adding definitions. -- Core Buildpack code uses [`getEnvVarDefinitions()`][], which builds environment variable definitions for the project. - It starts with core variables listed below and then calls the `envVarDefinitions` target so installed extensions can add their own variables. - - - -{% include auto-generated/buildpack/reference/envVarDefinitions.md %} - -[configuration management system]: {%link pwa-buildpack/configuration-management/index.md %} -[`envvardefinitions`]: {%link pwa-buildpack/reference/targets/index.md %}#module_BuiltinTargets.envVarDefinitions -[core variables]: {%link pwa-buildpack/reference/environment-variables/core-definitions/index.md %} -[values set in the current environment]: {%link pwa-buildpack/reference/buildpack-cli/load-env/index.md %}#loadenvironmentdirorenv-logge - -[`getenvvardefinitions()`]: https://github.com/magento/pwa-studio/blob/develop/packages/pwa-buildpack/lib/Utilities/getEnvVarDefinitions.js diff --git a/pwa-devdocs/src/pwa-buildpack/reference/environment-variables/definitions-api/index.md b/pwa-devdocs/src/pwa-buildpack/reference/environment-variables/definitions-api/index.md deleted file mode 100644 index c0a2bda81a..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/environment-variables/definitions-api/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Environment variable definition API ---- - - - -{% include auto-generated/pwa-buildpack/lib/Utilities/getEnvVarDefinitions.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/index.md b/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/index.md deleted file mode 100644 index 0b0d698589..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: BuildBus ---- - - - -{% include auto-generated/pwa-buildpack/lib/BuildBus/BuildBus.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/target/index.md b/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/target/index.md deleted file mode 100644 index ae781f66ac..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/target/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Target ---- - - - -{% include auto-generated/pwa-buildpack/lib/BuildBus/Target.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/targetprovider/index.md b/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/targetprovider/index.md deleted file mode 100644 index 3bca7f0d26..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/targetprovider/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: TargetProvider ---- - - - -{% include auto-generated/pwa-buildpack/lib/BuildBus/TargetProvider.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/magento-resolver/index.md b/pwa-devdocs/src/pwa-buildpack/reference/magento-resolver/index.md deleted file mode 100644 index 1fd62b8e0d..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/magento-resolver/index.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: MagentoResolver ---- - -An adapter that configures Webpack to resolve assets using Magento PWA conventions. - -This module generates a configuration object used in the [`resolve`] property of a Webpack config. -The configuration object tells Webpack how to traverse the filesystem structure for assets required in source files. - -Currently, MagentoResolver does very little, but it's likely that the Magento development environment will require custom resolution rules in the future; this utility sets the precedent of the API for delivering those rules. - -## API - -### `configure(options)` - -**Parameters:** - -* `options:` - Configuration object that describes where the PWA storefront folders are located. Must have a `root` property set to the context (root directory) of the project. - -**Return:** - -A [Promise] configuration type for webpack. - -{: .bs-callout .bs-callout-info} -**Note:** -`MagentoResolver.configure()` is asynchronous. - -## Example - -In `webpack.config.js`: - -``` js -const buildpack = require('@magento/pwa-buildpack'); -const MagentoResolver = buildpack.Webpack.MagentoResolver; - -module.exports = async env => { - const config { - /* webpack entry, output, rules, etc */ - - - resolve: await MagentoResolver.configure({ - paths: { - root: __dirname - } - }) - - }; - - return config; -} -``` - - - -{: .bs-callout .bs-callout-tip} -The special `__dirname` variable in Node always refers to the directory containing the currently executing script file. -This is different from the "working directory", which is the current directory of the shell when the current process was started. - -{: .bs-callout .bs-callout-info} -**Note:** -The example provided uses the newer, cleaner `async/await` syntax instead of using Promises directly. - - -[`resolve`]: https://webpack.js.org/configuration/resolve/ -[Promise]: https://webpack.js.org/configuration/configuration-types/#exporting-a-promise diff --git a/pwa-devdocs/src/pwa-buildpack/reference/pwa-dev-server/index.md b/pwa-devdocs/src/pwa-buildpack/reference/pwa-dev-server/index.md deleted file mode 100644 index 44c81717e1..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/pwa-dev-server/index.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: PWADevServer ---- - -A utility for configuring a development OS and a `webpack-dev-server` for PWA development. - -A typical webpack local development environment uses the [`devServer`][] settings in `webpack.config.js` to create a temporary, local HTTP server to show edits in real time. - -## Basic Features - -PWADevServer adds an optimized PWA development server to a Webpack configuration object. - -The dev server provides the following useful features: - -### Hot reload - -The hot reload feature refreshes the page or a relevant subsection of the page whenever you save a change that affects it. -It uses Webpack's [Hot Module Replacement](https://webpack.js.org/concepts/hot-module-replacement/) feature to replace components and stylesheets inline. - -### Proxy server - -The dev server acts as a proxy server for API and media requests to Magento. -It is configured using environment variables. - -The `MAGENTO_BACKEND_URL` environment variable configures the proxy server to accept GraphQL, REST, and media requests and passes them to Magento. - -The proxy server also transforms host and referral headers to make them compatible with Magento settings. - -### Root level ServiceWorker - -The dev server serves a JavaScript file at the root path that registers a ServiceWorker scoped to the whole website. -It can also disable that ServiceWorker when caching would interfere with realtime changes. - -### Verbose debugging - -The dev server adds verbose debugging information to error pages to help with development. - -## Optional Features - -The following dev server features are optional and are available on the initial run and confirmed on subsequent runs. -They are configured in the `.env` file. - -### Custom hostname - -The custom hostname feature uses a local hostname for the current project. -This hostname must be created for the current project by running `buildpack create-custom-origin .`. - -### GraphQL Playground IDE - -The dev server provides a [GraphQL Playground IDE][GraphQL Playground feature] to debug the GraphQL queries in the project. - -### SSL certificate configuration - -The dev server creates and cache a 'self-signed' SSL certificate that allow the use of HTTPS-only features during development. - -{: .bs-callout .bs-callout-info} -**Note:** -Updating the OS security settings to trust the self-signed certificate requires elevated permissions, so -you may be prompted for a password during the setup process. - -### Content transformation - -The content transformation feature masks the Magento 2 domain name in all HTML -attributes, replacing it with the development server domain name. - -## GraphQL Playground feature - -[GraphQL Playground][] is an enhanced version of the in-browser GraphQL debugging tool GraphiQL. - -Enable this feature by setting the `PWADevServerOptions.graphqlPlayground` configuration option to `true`. - -Browse to the `/graphiql` path on your PWADevServer to use this feature. - -[create SSL certificate]: #creating-an-ssl-certificate -[secure and unique hostname for the dev server]: #creating-a-secure-and-unique-hostname -[`devServer`]: https://webpack.js.org/configuration/dev-server/ -[Promise]: https://webpack.js.org/configuration/configuration-types/#exporting-a-promise -[`SecureHostOptions`]: #securehostoptions -[`subdomain: string`]: #subdomain -[`exactDomain: string`]: #exactdomain -[GraphQL Playground feature]: #graphql-playground-feature -[GraphQL Playground]: https://github.com/prisma/graphql-playground diff --git a/pwa-devdocs/src/pwa-buildpack/reference/root-components-plugin/index.md b/pwa-devdocs/src/pwa-buildpack/reference/root-components-plugin/index.md deleted file mode 100644 index ebc966af73..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/root-components-plugin/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: MagentoRootComponentsPlugin ---- - -This plugin creates [unique chunks] for each Root Component in a Magento PWA project and extension. - -For example, given a `RootComponents` directory in a PWA project with the following structure: - -``` sh -├── Page1 -│ └── index.js -├── Page2 -│ └── index.js -└── Page3 - └── index.js -``` - -The plugin creates unique chunks for `Page1`, `Page2`, and `Page3`. -Further webpack optimization techniques, such as [`CommonsChunkPlugin`], can be applied as usual. - -## Example usage - -``` javascript -// webpack.config.js - -const path = require('path'); -const { MagentoRootComponentsPlugin } = require('@magento/pwa-buildpack'); - -module.exports = { - entry: { - main: path.join(__dirname, 'src') - }, - output: { - path: path.join(__dirname, 'dist'), - filename: '[name].js', - chunkFilename: '[name].chunk.js' - }, - plugins: [ - new MagentoRootComponentsPlugin({ - rootComponentsDirs: [path.join(__dirname, 'src/RootComponents')], // optional - manifestFileName: 'roots-manifest.json' // optional - }) - ] -}; -``` - -[unique chunks]: https://webpack.js.org/guides/code-splitting/ -[`CommonsChunkPlugin`]: https://webpack.js.org/plugins/commons-chunk-plugin/ diff --git a/pwa-devdocs/src/pwa-buildpack/reference/serviceworker-plugin/index.md b/pwa-devdocs/src/pwa-buildpack/reference/serviceworker-plugin/index.md deleted file mode 100644 index ab4986a6a7..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/serviceworker-plugin/index.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: ServiceWorkerPlugin ---- - -A webpack plugin for configuring a ServiceWorker for different PWA development scenarios. - -This plugin is a wrapper around the [Google Workbox Webpack Plugin]. -It generates a caching ServiceWorker based on assets emitted by webpack. - -The following configurations are available for this plugin: - -* **normal development** - the ServiceWorker is disabled -* **service worker debugging** - the ServiceWorker and hot-reloading are enabled. - -## API - -### `ServiceWorker(options)` - -Plugin constructor for the `ServiceWorkerPlugin` class. - -#### Parameters - -* **`options: PluginOptions`** - Configuration object for the ServiceWorkerPlugin - -The `PluginOptions` object contains the following properties: - -| Property: Type | Description | -| --------------------------------------- | ---------------------------------------------------------------------------------- | -| `env:`[`EnvironmentObject`] | **Required.** An object that represents the current environment. | -| `paths: object` | **Required.** Map of important project locations. Must at least contain a `root` property set to the context (root directory) of the project. | -| `enableServiceWorkerDebugging: boolean` | Toggles [service worker debugging]. | -| `serviceWorkerFilename: string` | **Required.** The name of the ServiceWorker file this project creates. | -| `runtimeCacheAssetPath: string` | A remote URL or root path to assets the ServiceWorker should cache during runtime. | -{:style="table-layout:auto"} - -The `EnvironmentObject` contains the following properties: -{:#environmentobject} - -| Property: Type | Description | -| --------------- | ------------------------------------------ | -| `mode: string` | Must be **development** or **production**. | -{:style="table-layout:auto"} - -## Example - -In `webpack.config.js`: - -``` js -const path = require('path'); -const buildpack = require('@magento/pwa-buildpack'); -const ServiceWorkerPlugin = buildpack.Webpack.ServiceWorkerPlugin; - -module.exports = async env => { - const config = { - /* webpack config, i.e. entry, output, etc. */ - plugins: [ - /* other plugins */ - new ServiceWorkerPlugin({ - env: { - mode: 'development' - }, - - paths: { - output: path.resolve(__dirname, 'web') - }, - enableServiceWorkerDebugging: true, - serviceWorkerFileName: 'sw.js', - runtimeCacheAssetPath: 'https://cdn.url' - }) - ] - }; - - return config; - -}; - -``` - -## Service worker debugging - -When `PluginOptions.enableServiceWorkerDebugging` is set to `true`, hot reloading is enabled and the ServiceWorker is active in the document root. - -When this value is set to `false`, the ServiceWorker is disabled to prevent cache interruptions when hot reloading assets. - - -[Google Workbox Webpack Plugin]: https://developers.google.com/web/tools/workbox/guides/generate-service-worker/ -[`EnvironmentObject`]: #environmentobject -[service worker debugging]: #service-worker-debugging diff --git a/pwa-devdocs/src/pwa-buildpack/reference/targets/index.md b/pwa-devdocs/src/pwa-buildpack/reference/targets/index.md deleted file mode 100644 index eb5b2ce59e..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/targets/index.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Built-in Targets ---- - -Buildpack's targets follow the same Target API as other packages' targets, but they play a unique role. Buildpack targets are the fundamental "roots" of the PWA Studio Target system. - -All other Targets operate by intercepting other Targets. -BuildBus runs the declare and intercept phases by itself. -But nothing _calls_ targets to run any interceptors until Buildpack begins the process, by directly invoking one of its _own_ targets. - -The Buildpack targets are therefore very generic and low-level. They are meant to be used as building blocks for higher-level feature targets, such as adding routing or navigation logic. - -Even deeper than Buildpack targets are the very similar Hooks that make up [Webpack's plugin system](https://v4.webpack.js.org/api/plugins/). Interceptors can use Buildpack's `webpackCompiler` target to acquire a reference to the Webpack Compiler object for each build, and can then do anything a Webpack plugin can do. -Because of their similarity in form and function, the PWA Studio Targets system integrates seamlessly into the larger Webpack ecosystem as a commerce-driven superset of its functionality. - - - -{% include auto-generated/pwa-buildpack/lib/BuildBus/declare-base.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/transform-requests/index.md b/pwa-devdocs/src/pwa-buildpack/reference/transform-requests/index.md deleted file mode 100644 index 1f1abe35a7..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/transform-requests/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Transform Requests ---- - -The built-in [`transformModules`][] target is a powerful way to customize the build process for a partiular file or set of files. -Many common Targets are implemented using the `transformModules` target and a custom transformer module. - -Interceptors of this target receive a single function as their first argument. This is the `addTransform` function documented below. - - - -{% include auto-generated/pwa-buildpack/lib/WebpackTools/ModuleTransformConfig.md %} - - -[`transformModules`]: {%link pwa-buildpack/reference/targets/index.md %}#module_BuiltinTargets.transformModules diff --git a/pwa-devdocs/src/pwa-buildpack/scaffolding/custom-project-templates/index.md b/pwa-devdocs/src/pwa-buildpack/scaffolding/custom-project-templates/index.md deleted file mode 100644 index 87ea67adee..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/scaffolding/custom-project-templates/index.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: Custom project templates ---- - -PWA Studio [scaffolding tools][] allow you to specify a template to build a new storefront project. -The default template they use is the `venia-concept` project. - -## Buildpack folder - -The `venia-concept` has a `_buildpack` directory in the project root and a script called `create.js` inside that directory. -The presence of `create.js` within the `_buildpack` directory indicates that this project can be used as a template for the [`buildpack create-project`][] command. - -### The `create.js` file - -The `create.js` file defines a function that returns an object with `ignores`, `before`, `visitor`, and `after` properties. -These properties are functions that provide instructions for the buildpack `create-project` command. - -The function defined in `create.js` is passed in an object with the following properties: - -- `fs` - An instance of the [`fs-extra` library][], which provides utilities for most of the common copy operations. -- `tasks` - An object which provides common handlers that template developers can use for globs. -- `options` - An object that contains the parameters used in the `buildpack create-project` command. - -When the create project command executes, it walks the template project's directory tree and applies the instructions provided by the returned object's properties. - -#### `ignores` - -The `ignores` property is an array of [glob patterns][]. -Files that match these patterns are not processed by the create project command. - -Use this property to prevent the create command from processing project-specific or unimportant files. - -### `before` - -The `before` property defines a function that runs before the command walks the directory tree. -Use this property to add pre-processing logic during project creation. - -### `visitor` - -The `visitor` property is a mapping object that maps a glob pattern to a file handler function. -The glob pattern is the map key, and the file handler function is the value associated with that key. - -When the project creation tool walks the directory tree, it looks for files that match each glob pattern and runs the visitor function associated with that pattern. - -Use this property to perform custom transformation logic on a file before copying it to the new project. - -```js -{ - visitor: { - 'package.json': ({ path, targetPath, options }) => { - const pkg = fs.readJsonSync(path); - pkg.name = options.name; - fs.writeJsonSync(targetPath, JSON.stringify(pkg, null, 4)); - } - } -} -``` - -This is an example of a visitor property that targets the template project's `package.json` file and modifies its name before writing it out to the `targetPath`. - -{: .bs-callout .bs-callout-warning} -**Note:** -The `buildpack create-project` command does not perform the actual file copy. -Use the convenient `tasks.IGNORE` and `tasks.COPY` handlers provided by the tool to perform common ignore and copy file tasks. - -### `after` - -The `after` property defines a function that runs after the command walks the directory tree. -Use this property to add post-processing logic during project creation. - -[scaffolding tools]: {%link pwa-buildpack/scaffolding/index.md %} -[`buildpack create-project`]: {%link pwa-buildpack/reference/buildpack-cli/create-project/index.md %} - -[glob patterns]: https://en.wikipedia.org/wiki/Glob_(programming) -[`fs-extra` library]: https://www.npmjs.com/package/fs-extra diff --git a/pwa-devdocs/src/pwa-buildpack/scaffolding/index.md b/pwa-devdocs/src/pwa-buildpack/scaffolding/index.md deleted file mode 100644 index 9665d71141..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/scaffolding/index.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Scaffolding ---- - -Project scaffolding is a technique for auto-generating files to support a specific project structure. -PWA Studio provides scaffolding tools to simplify project creation and help developers get started. - -Developers should use the PWA Studio libraries Magento publishes to the NPM package repository. -Early adopters of the PWA Studio project forked and worked off the project repository, but -this practice is not recommended now that scaffolding tools are available. - -## Venia concept package - -The `venia-concept` package is a good example of a PWA Studio starter application. -Most of its UI and logic come from its `@magento/venuia-ui` and `@magento/peregrine` dependencies, so -it has very little code in its own project folder. - -Since the project structure is small and simple, PWA Studio scaffolding tools use this project as the default template for creating new storefront projects. -Customizing these projects is as simple as importing small pieces of `venia-ui` and combining them with custom code. - -## The `@magento/create-pwa` command - -Using the [`@magento/create-pwa`][] project initializer is the fastest way to get a PWA Studio project set up for development. -It is a user-friendly version of the [`create-project`][] sub-command in the [`pwa-buildpack`][] CLI tool. - -Since the package name begins with `create-`, it is considered a project generator and, -the command can be run as `@magento/pwa`. -Run this project generator directly from the NPM package respository with Yarn: - -```sh -yarn create @magento/pwa -``` - -Or with NPM: - -```sh -npm init @magento/pwa -``` - -This command launches an interactive questionnaire in the command line for configuring different parts of the project. - -[`create-project`]: {%link pwa-buildpack/reference/buildpack-cli/create-project/index.md %} -[`pwa-buildpack`]: {%link pwa-buildpack/reference/buildpack-cli/index.md %} - -[`@magento/create-pwa`]: https://www.npmjs.com/package/@magento/create-pwa diff --git a/pwa-devdocs/src/pwa-buildpack/troubleshooting/index.md b/pwa-devdocs/src/pwa-buildpack/troubleshooting/index.md deleted file mode 100644 index 9f5ba25c7b..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/troubleshooting/index.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Troubleshooting ---- - -This page lists solutions for common issues reported by community members for the PWA Buildpack project. -If you run into any other problems please [create an issue] or let us know in our [Slack channel]. - -To provide more details for your issue, enable verbose console logging. -Instead of `yarn start` run the following command to set a debugging environment variable: - -``` sh -DEBUG=pwa-buildpack:* yarn start -``` - -Paste the result console output into the issue. Thank you! - -## Common issues - -* [Validation errors when running developer mode](#validation-errors) -* [Venia queries to GraphQL produce validation errors](#graphql-validation-errors) -* [Browser displays "Cannot proxy to " error and the console displays `ENOTFOUND`](#cannot-proxy) -* [Webpack hangs for a long time before beginning compilation](#webpack-hangs) -* [Browser cannot resolve the `.local.pwadev` site](#cannot-resolve-site) -* [Browser does not trust the generated SSL certificate](#untrusted-ssl-cert) - -## Resolutions - -**Validation errors when running developer mode**{:#validation-errors} - -Make sure you ran `npx @magento/pwa-buildpack create-env-file packages/venia-concept` in the root directory. -The file that command generates will hold variables for your local development environment. - -**Venia queries to GraphQL produce validation errors**{:#graphql-validation-errors} - -Venia and its GraphQL queries are out of sync with the schema of the connected Magento instance. -Make sure your Magento instance is up to date with the latest from Magento 2.3 development branch. - -To test whether your queries are up to date, run the following command in the project root: - -``` sh -yarn run validate-queries -``` - -**Browser displays "Cannot proxy to " error and the console displays `ENOTFOUND`**{:#cannot-proxy} - -Make sure your Magento store loads in more than one browser. - -If you are running a local DNS server or VPN, add an entry to your hostfile and manually map this domain so NodeJS can resolve it. - -**Webpack hangs for a long time before beginning compilation**{:#webpack-hangs} - -You may have an old version of the `pwa-buildpack` project. -Update your project using the following command: - -``` sh -yarn upgrade -``` - -Make sure you have a current version of openssl on your system using the following command: - -``` sh -openssl version -``` - -The version should be 1.0 or above (or LibreSSL 2, in the case of OSX High Sierra.) - -You can install higher versions of OpenSSL with [Homebrew] on OSX, [Chocolatey] on Windows, or your Linux distribution's package manager. - -**Browser cannot resolve the `.local.pwadev` site**{:#cannot-resolve-site} - -Another program or process has edited your [host file] and removed the entry for your project domain. You can [manually edit your hostfile] to add the entry back, but you should examine your other installed software to see what has overwritten the previous change. - -**Browser does not trust the generated SSL certificate**{:#untrusted-ssl-cert} - -Generating certificates is handled by [devcert][]. It depends on OpenSSL, so make sure you have a current version of openssl on your system using the following command: - -``` sh -openssl version -``` - -The version should be 1.0 or above (or LibreSSL 2, in the case of OSX High Sierra.) - -You can install higher versions of OpenSSL with [Homebrew] on OSX, [Chocolatey] on Windows, or your Linux distribution's package manager. - -If you're running Linux, make sure that `libnss3-tools` (or whatever the equivalent is) is installed on your system. Further information provided in [this section of the devcert readme][]. - -Some users have suggested deleting the `devcert` folder to trigger certificate regeneration. - -* For MacOS users, this folder is usually found at: - ```sh -~/Library/Application Support/devcert - ``` -* For Windows users, this folder is usually found at: - ```text -${User}\AppData\Local\devcert - ``` - -[create an issue]: https://github.com/magento/pwa-buildpack/issues -[Slack channel]: https://magentocommeng.slack.com/messages/C71HNKYS2/team/UAFV915FB/ -[host file]: https://en.wikipedia.org/wiki/Hosts_(file) -[manually edit your hostfile]: https://support.rackspace.com/how-to/modify-your-hosts-file/ -[Homebrew]: https://brew.sh/ -[Chocolatey]: https://chocolatey.org/ -[devcert]: https://github.com/davewasmer/devcert -[this section of the devcert readme]: https://github.com/davewasmer/devcert#skipcertutil diff --git a/pwa-devdocs/src/reference/ui-components/index.md b/pwa-devdocs/src/reference/ui-components/index.md deleted file mode 100644 index 3863ff275f..0000000000 --- a/pwa-devdocs/src/reference/ui-components/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md %} \ No newline at end of file diff --git a/pwa-devdocs/src/releases/index.md b/pwa-devdocs/src/releases/index.md deleted file mode 100644 index c4f27a9d02..0000000000 --- a/pwa-devdocs/src/releases/index.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Releases -redirect_to: https://github.com/magento/pwa-studio/releases/ ---- \ No newline at end of file diff --git a/pwa-devdocs/src/search.md b/pwa-devdocs/src/search.md deleted file mode 100644 index 402661f171..0000000000 --- a/pwa-devdocs/src/search.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -layout: search -title: Search Results -menu_title: Search -permalink: /search/ ---- diff --git a/pwa-devdocs/src/static/fonts/.gitkeep b/pwa-devdocs/src/static/fonts/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pwa-devdocs/src/static/images/.gitkeep b/pwa-devdocs/src/static/images/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pwa-devdocs/src/static/images/contribute.png b/pwa-devdocs/src/static/images/contribute.png deleted file mode 100644 index c2d2c0ab29..0000000000 Binary files a/pwa-devdocs/src/static/images/contribute.png and /dev/null differ diff --git a/pwa-devdocs/src/static/images/getting-started.png b/pwa-devdocs/src/static/images/getting-started.png deleted file mode 100644 index b16a9da4d4..0000000000 Binary files a/pwa-devdocs/src/static/images/getting-started.png and /dev/null differ diff --git a/pwa-devdocs/src/static/images/repos.png b/pwa-devdocs/src/static/images/repos.png deleted file mode 100644 index 8f81546587..0000000000 Binary files a/pwa-devdocs/src/static/images/repos.png and /dev/null differ diff --git a/pwa-devdocs/src/static/images/what-is-pwa.png b/pwa-devdocs/src/static/images/what-is-pwa.png deleted file mode 100644 index 33d59357a5..0000000000 Binary files a/pwa-devdocs/src/static/images/what-is-pwa.png and /dev/null differ diff --git a/pwa-devdocs/src/technologies/basic-concepts/app-shell/index.md b/pwa-devdocs/src/technologies/basic-concepts/app-shell/index.md deleted file mode 100644 index b3da829254..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/app-shell/index.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Application Shell -contributors: - - gavin2point0 ---- - -Magento PWA Studio uses an application shell architecture to shorten the time it takes to load a branded experience in the UI instead of a blank page. - -This approach involves heavily caching the minimal amount of HTML, CSS and JS to load the basic UI of the page before fetching the rest through an API. - -App shell rendering is instantaneous on repeat visits because the majority of the page is in the cache. -It also prevents unnecessary data usage because it removes the need to download static content more than once. - -The following is a simple example of an application shell: - -``` html - - - - - - - - - Document - - - -- - - - -App Shell
-- -- -- -- - - - - - -``` diff --git a/pwa-devdocs/src/technologies/basic-concepts/client-side-caching/index.md b/pwa-devdocs/src/technologies/basic-concepts/client-side-caching/index.md deleted file mode 100644 index e6f414d709..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/client-side-caching/index.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: Client-side caching ---- - -Client-server communication is slow and expensive. -Performance is an important feature for any Progressive Web Application (PWA), so -requests to the server should be minimized. - -Offline mode is also a required feature for a PWA. -In offline mode, the application must be able to serve pages that have been recently viewed. - -These features are implemented with the help of a client-side cache. -This local cache stores data from resources as they are fetched. -Once a resource has been cached, the service worker may consult the cache on subsequent requests for that resource to boost performance. - -## Service Worker caching - -A [service worker][] is a JavaScript file that runs in a separate thread from the main execution thread in a web application. -Service workers can intercept network requests and fetch cached data or store results from a network request into the cache. - -### Venia service worker - -Venia's service worker behavior is defined in the [`src/sw.js`][] file using Google's [Workbox][] library. - -You do not need to use Workbox to define service worker behavior, but -Workbox makes this task easier by removing boilerplate code that is always used when working with service workers. - -Venia uses the following [caching strategies][] with its service worker: - -#### [Stale-while-revalidate][] - -The stale-while-revalidate strategy tells the service worker to use a cached response if it exists. -A separate network request is made for that resource and the cache is updated for future requests. - -This strategy is used when the most up to date version of a resource is not necessary for an application. - -| Route pattern | Description | -| ------------------------------------------------- | -------------------- | -| `/` | The application root | -| `/.\\.js$` | JavaScript files | -| `/\/media\/catalog.*\.(?:png|gif|jpg|jpeg|svg)$/` | Catalog image files | - -#### [Network first][] - -The network first strategy tells the service worker to get a resource from the network first. -If a network connection cannot be made, the service worker uses the cache as a fallback. - -This strategy is used for data that may change frequently on the server. - -| Route pattern | Description | -| ------------- | ----------- | -| `\\.html$` | HTML pages | - -#### [Cache first][] - -The cache first strategy tells the service worker to use the data from the cache. -Unlike the stale-while-revalidate strategy, no network call is made to update the cache. - -If a response is not found in the cache, a network call is made to get the resource and cache the response. - -This strategy is used for non-critical assets that do not get updated very often. - -| Route pattern | Description | -| ------------- | --------------------------------------- | -| `images` | Image files served from the application | - -## Caching in the Apollo GraphQL client - -The Venia implementation storefront uses the Apollo GraphQL client to make requests to the Magento GraphQL endpoint. -It also incorporates the default [`InMemoryCache`][] implementation to add caching abilities to the client. - -The cache is persisted between browser sessions in `window.localstorage` using the [`apollo-cache-persist`][] module. -This lets the Apollo client maintain its cached data even when the user closes the application. - -By default, `InMemoryCache` uses a cache first strategy for all queries. -This strategy is set using the `fetchPolicy` prop on the `Query` component. - -Caching for Apollo is set up in the [`src/drivers/adapter.js`][] file. - -[service worker]: https://developers.google.com/web/ilt/pwa/introduction-to-service-worker -[`src/sw.js`]: https://github.com/magento/pwa-studio/blob/master/packages/venia-concept/src/sw.js -[workbox]: https://developers.google.com/web/tools/workbox/ -[caching strategies]: https://developers.google.com/web/tools/workbox/modules/workbox-strategies -[stale-while-revalidate]: https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#stale-while-revalidate -[network first]: https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#network-falling-back-to-cache -[cache first]: https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-falling-back-to-network -[`inmemorycache`]: https://www.apollographql.com/docs/react/advanced/caching -[`apollo-cache-persist`]: https://github.com/apollographql/apollo-cache-persist -[`src/drivers/adapter.js`]: https://github.com/magento/pwa-studio/blob/master/packages/venia-concept/src/drivers/adapter.js diff --git a/pwa-devdocs/src/technologies/basic-concepts/client-state-reducers-actions/index.md b/pwa-devdocs/src/technologies/basic-concepts/client-state-reducers-actions/index.md deleted file mode 100644 index abd1475659..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/client-state-reducers-actions/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=12 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/component-data-binding/index.md b/pwa-devdocs/src/technologies/basic-concepts/component-data-binding/index.md deleted file mode 100644 index cf9bbec486..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/component-data-binding/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=9 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/container-extensibility/index.md b/pwa-devdocs/src/technologies/basic-concepts/container-extensibility/index.md deleted file mode 100644 index ddd0410da6..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/container-extensibility/index.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Container extensibility ---- - -A **Container** is an HTML element that contains 0 or more [`ContainerChild`] components. -It acts as the target for `magento-loader-layout` operations. - -## Creating a Container - -To create a Container in a React component, add a `data-mid` prop to any DOM element, such as a `div`, `span`, etc. -The value of the `data-mid` prop *must* be a literal string value. -It cannot be a dynamic value or a variable reference. - -**Example:** -``` jsx - -``` - -**Note:** -*Composite components, such as a class or function, cannot be used as a Container.* - - -## Extending a Container - -[`ContainerChild`] components are the only allowed children of a Container. -This makes it possible to extend a Container using the `magento-loader-layout` tool from the [PWA Buildpack]. - -`magento-loader-layout` supports the following operations: - -* Remove a container -* Remove a child component in a container -* Insert content before a child component in a container -* Insert content after a child component in a container - - -[`ContainerChild`]: {% link peregrine/reference/container-child/index.md %} -[PWA Buildpack]: {% link pwa-buildpack/index.md %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/content-rendering/index.md b/pwa-devdocs/src/technologies/basic-concepts/content-rendering/index.md deleted file mode 100644 index 6177a15827..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/content-rendering/index.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Content Rendering ---- - -Browsers require HTML to display page content. -Server-side rendering and client-side rendering are two ways a browser can get rendered HTML content for a page. -This topic goes over these two ways of rendering content supported by PWA Studio and UPWARD. - -## Server-side rendering (SSR) - -Server-side rendering (SSR) is a method of providing pre-generated HTML as a response to an HTTP request. - -For example, the content of this website is pre-built from source files. -These files are converted into HTML pages and uploaded into an HTTP hosting server. -When a user visits the site, the server returns the pre-built HTML file for the browser to render. - -Example: - -```html - - - - - -My Website - - -Header content - -Main body content - - - -``` - -Server-side languages, such as PHP and Java, can also render custom HTML per request to make the experience more dynamic. -This is how Magento currently works. - -## Client-side rendering (CSR) - -Client-side rendering is another method of delivering HTML content to the browser. -Instead of providing the entire HTML page content on a request, the server returns a page with minimal content. -The page depends on a JavaScript file that finishes rendering the HTML on the page. - -The following is an example of what a bare page response looks like: - -```html - - - - - -My Web App - - - - - - -``` - -In this example, the `app.js` script runs after the page loads. -A common behavior for this type of file is to generate an HTML DOM tree and insert it into a root element on the page. -This pattern is often used for single page applications such as a PWA Storefront. - -## Content rendering and Search Engine Optimization (SEO) - -When and how page content renders is an important part of Search Engine Optimization (SEO). - -When a search engine crawler processes a page, it indexes the initial HTML response from the server. -Some crawlers, such as the [Googlebot][], have the ability to execute JavaScript to simulate client-side rendering. -The varying effectiveness of search engines to process client-side rendered content is an important factor to keep in mind when developing your storefront's content rendering strategies. - -Boosting a site's SEO while providing a rich, dynamic experience is a balancing act between server-side rendering and client-side rendering. - -## Content rendering in PWA Studio - -### UPWARD and server-side rendering - -The UPWARD specification supports server-side rendering through it's [JavaScript][] and [PHP][] server implementations. -The specification provide different resolvers that can return HTML content as a response to a request. - -Use the following resolvers in your applications UPWARD configuration file to enable server-side rendering. - -#### FileResolver - -The FileResolver configuration lets you use the contents of a static file in your response body. -You can pre-build static HTML files for your application and map URL to the content using the FileResolver. -This is the fastest way to deliver a server-side rendered HTML response to a request. - -#### TemplateResolver - -The TemplateResolver configuration lets you use templates to create a server-side rendered response. -Templates are more flexible than pre-built static HTML files because they let you use template variables to create the final HTML response. -Server-side rendering performance with the TemplateResolver is dependent on the complexity of the templates it uses. - -### Venia content rendering process - -Venia uses both server-side and client-side rendering to display page content. - -The following is the sequence of events that occur when a browser requests a page from the Venia storefront: - -1. The application's UPWARD server receives the request and checks to see if it is a valid page request. -2. If the request is for a page, the UPWARD server returns a pre-built, server-side rendered HTML response that contains the PWA application shell. -3. After the browser loads the initial application shell, a JavaScript bundle renders the rest of the page content on the client side using React components. - These React components may make additional calls to the UPWARD server to get the data they need to finish rendering. - -[googlebot]: https://en.wikipedia.org/wiki/Googlebot - -[javascript]: https://github.com/magento/pwa-studio/tree/develop/packages/upward-js - -[php]: https://github.com/magento-research/upward-php diff --git a/pwa-devdocs/src/technologies/basic-concepts/critical-path/index.md b/pwa-devdocs/src/technologies/basic-concepts/critical-path/index.md deleted file mode 100644 index 2a398f2a0e..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/critical-path/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=18 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/css-modules/index.md b/pwa-devdocs/src/technologies/basic-concepts/css-modules/index.md deleted file mode 100644 index 7d9e7dbc22..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/css-modules/index.md +++ /dev/null @@ -1,228 +0,0 @@ ---- -title: CSS Modules ---- - -A [CSS Module][] is a CSS file that defines class and animation names that are scoped locally by default. - -CSS modules let you import your `.css` file into a JavaScript Object with the CSS definitions as properties. -It also lets you use the `compose` property to extend and modularize style definitions. - -CSS modules do not have an official specification nor are they a browser feature. -They are part of a compilation process that executes against your project to convert scoped classes and selectors into CSS files that the browser can parse and understand. - -Tools such as [Webpack][] are used to perform this compilation process. - -PWA Studio supports CSS modules out-of-the-box and using them is the recommended approach for styling components. - -## Why you should use CSS modules - -React lets you split the UI into independent and reusable components, which allows you to update small parts of your UI without refreshing the page. - -As React applications grow, the amount of components and layers increases. -Simple style changes can have unintended side effects on different parts of a complex page. - -CSS modules give you the ability to control your element styles in a more granular way. -They allow you to build different layers of styles while building your application using a modular approach. -CSS modules make it easy and fast to achieve tasks such as upgrading buttons, headings, grids, etc. - -For more information on reusable components and code sharing in front end development see: [Block Element Modifier (BEM)][] - -## Webpack configuration - -[Webpack][] uses the Webpack [style-loader][] and [css-loader][] modules to bundle CSS styles using a configuration that looks like the following: - -``` javascript -// webpack configuration -{ - test: /\.css$/, - use: [ - 'style-loader', - { - loader: 'css-loader', - options: { - importLoaders: 1, - localIdentName: '[name]-[local]-[hash:base64:3]', - modules: true - } - } - ] -}, -``` - -The following is an explanation of each `css-loader` configuration: - -`importLoaders` - -: Tells Webpack how many loaders to apply to imported resources before applying `css-loader`. - -`localIdentName` - -: Defines the format of the generated local ident. - In this case, it is a combination of the following values: - - * `[name]` - the component name - * `[local]` - the CSS definition name - * `[hash:base64:3]` - a random base64 hash of 3 digits - - **Example:** `Subtitle-titleHighlighted-rCN` - -`modules` - -: Enables or disables CSS modules. - -For more information about Webpack configuration, follow these links to the official documentation: - -* [Webpack CSS Loader modules documentation][] -* [Webpack CSS Loader composing documentation][] - -## How it works - -The following is a basic example of how styles are used without modules: - -``` css -/* styles.css */ -.heading { color: yellow; background-color: blue; margin: 0 0 1rem; } -.titleHighlighted { padding: 1rem 2rem; text-align: center; } -``` - -``` jsx -// subtitle.js -import React, { Component } from 'react'; -import "./styles.css"; - -class Subtitle extends Component { - render() { - return ( --- ); - } -} - -export default Subtitle; -``` - -This approach is perfectly valid, but it has several downsides as the amount of components and CSS definitions grows. -All your definitions are shared across all components which forces you to reference your elements by its DOM inheritance or create unique definition names. - -To avoid this, you can use CSS modules to create a component with locally scoped styles: - -``` jsx -// subtitle.js - -import React, { Component } from 'react'; -import myStyles from './styles.css'; - -class Subtitle extends Component { - render() { - return ( -My Title
-My Title
--- ); - } -} - -export default Subtitle; -``` - -## Creating and composing CSS modules - -Any valid `.css` file can be a CSS module. -The difference is that the style definitions in that file are scoped to specific components instead of globally. - -The `composes` property is used in CSS module files to combine local style definitions. -The following example creates a CSS module that applies the `.heading` style definition wherever `.titleHighlighted` is used. - -``` css -/** ./styles.css */ -.heading { - color: yellow; - background-color: blue; - margin: 0 0 1rem; -} - -.titleHighlighted { - composes: heading; - padding: 1rem 2rem; - text-align: center; -} -``` - -### Composing from another file - -By default, `composes` looks for style definitions in the local file. -To reuse a definition from another file, use the `from` keyword. - -The following example `composes` the `heading` definition with the `baseHeading` definition from the `default_heading.css` file. - -``` css -/* default_heading.css */ -.baseHeading { color: yellow; background-color: blue; margin: 0 0 1rem; } - -/* styles.css */ -.heading { - composes: baseHeading from './default_heading.css'; - font-weight: bold; -} -``` - -## Importing and applying styles - -The syntax for importing a CSS module is the same as importing a JavaScript module. - -``` jsx -import myStyles from './styles.css'; -``` - -The style definitions in the CSS module are available as properties of `myStyles`. -They are used as values in an element's `className` attribute. - -The following example defines a `Subtitle` component which uses the `titleHighlighted` style definition: - -``` jsx -// ./subtitle.js -import React, { Component } from 'react'; -import myStyles from './styles.css'; - -export Subtitle extends Component -{ - render() { - return ( -My Title
-My Title
--- ); - } -} - -export default Subtitle; -``` - -This example assigns a style based on component logic: - -``` jsx - render() { - const { isHighlighted, title } = this.props; - - // we evaluate which class to apply, based on a prop received - const finalStyle = isHighlighted ? myStyles.titleHighlighted : myStyles.heading; - - return( -My Subtitle
--- ); - } -``` - -[Webpack]: https://webpack.js.org/ -[CSS Module]: https://github.com/css-modules/css-modules -[style-loader]: https://github.com/webpack-contrib/style-loader -[css-loader]: https://github.com/webpack-contrib/css-loader -[Webpack CSS Loader composing documentation]: https://webpack.js.org/loaders/css-loader/#composing -[Webpack CSS Loader modules documentation]: https://webpack.js.org/loaders/css-loader/#modules -[Block Element Modifier (BEM)]: http://getbem.com/ diff --git a/pwa-devdocs/src/technologies/basic-concepts/graphql/index.md b/pwa-devdocs/src/technologies/basic-concepts/graphql/index.md deleted file mode 100644 index f25684b20d..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/graphql/index.md +++ /dev/null @@ -1,307 +0,0 @@ ---- -Title: GraphQL -contributors: Jstein19 ---- - -## What is GraphQL - -[GraphQL][] is a language for querying and manipulating data. -It is widely viewed as more powerful, flexible, and efficient than REST. - -## Benefits provided by GraphQL - -### Predictable results from your queries - -A GraphQL query returns only data the user asks for in their query. - -### Single request for many results - -A single request made through GraphQL can return any number of resources and their fields by following references between them as defined in the typed schema. - -### Organized data with a typed schema - -A single schema defines how users access data using GraphQL. -These schemas, formatted as JSON objects, let users know exactly how to get the data they need. - -The following is an example of a schema that defines a `Species` type with `name` and `origin` fields: - -``` graphql -type Species { - name: String - origin: Planet -} -type Planet { - name: String -} -``` - -{: .bs-callout .bs-callout-info} -_**Note:** The `origin` field is a `Planet` type, which also has a `name` field._ - -## Why use GraphQL over REST - -While GraphQL and REST are both specifications for constructing and querying APIs, GraphQL has some significant advantages over REST. - -### No versioning - -REST APIs typically have multiple versions, such as v1, v2, etc. -This is because updating endpoints in REST will often impact existing queries. - -With GraphQL, there is no need for versioning, since new types and fields can be added to the schema without impacting existing queries. - -Removing fields is done through deprecation instead of deleting them from the schema. -If an old query tries to read a deprecated field, GraphQL displays a customized warning. - -``` -type ExampleType { - firstName: String - lastName: String - name: String @deprecated(reason: "Split this field into two. Use `firstName` and `lastName`") -} -``` - -This prevents old queries from throwing confusing errors when trying to read outdated fields, lending to code maintainability. - -### Faster and more efficient - -REST APIs typically require loading from multiple URLs. -Imagine a REST API designed to get users and their forum posts. -`users/{ title }
-` would return information like `name` and `user/ /posts` would have to be queried separately to return the user's `comments`. - -With GraphQL, these `types` and their `fields` are returned using one query, which saves calls to the API. - -In the following schema example, a `User` type contains a `posts` field, which is an array of `Post` types: - -``` graphql -type Query { - user(id: Int): User - # This is our resolver; our entry into the query - # It lets us query `user` with an argument `id` - # And Expects to return a type `User` - # Yes, you can leave comments in schemas! -} - -type User { - id: Int! - name: String - posts: [Post] -} - -type Post { - id: Int! - title: String - author: User -} -``` - -{: .bs-callout .bs-callout-info} -_**Note:** The exclamation mark (!) next to a field in the schema indicates it is `non-nullable`, which means the GraphQL service promises to always return a value for this field on a query._ - -A query for this schema that requests the name and all the post titles for a specific user would look like the following: - -``` graphql -{ - user(id: 12345) { - name - posts { - title - } - } -} -``` - -The data response for the query would look like the following: - -``` -{ - "data": { - "user": { - "name": "Jane Doe" - "posts": [ - { - title: "Hello World" - }, - { - title: "I Love GraphQL" - } - ] - } - } -} -``` - -## Sample queries - -### Simple query - -Imagine a database that simply contains an object `User`, with the fields `name`, `email`, and `phone`. - -``` graphql -type Query { - user: User -} - -type User { - name: String - email: String - phone: String -} -``` - -A simple query requesting this data would look like the following: - - ``` graphql - { - user { - name - email - phone - } - } - ``` - -The response to this query would look like the following: - -``` -{ - "data": { - "user": { - "name": "Jane Doe" - "email": "JaneDoe@example.com" - "phone": "012-345-6789" - } - } -} -``` - -### Custom data query - -What if you don't need the `phone` number from `User`? -The previous query can be rewritten to return specific fields: - -``` graphql -{ - user { - name - email - } -} -``` - -The response only provides the data requested: - -``` -{ - "data": { - "user": { - "name": "Jane Doe" - "email": "JaneDoe@example.com" - } - } -} -``` - - -### Arguments in a query - -Now, what if you had multiple users and needed to grab a specific one using its `id`? -Well, with GraphQL you can pass arguments into the query: - -``` -{ - user(id: 12345) { - id - name - email - } -} -``` - -The response would look like the following: - -``` -{ - "data": { - "user": { - "id": "12345" - "name": "Jane Doe" - "email": "JaneDoe@example.com" - } - } -} -``` - -{: .bs-callout .bs-callout-info} -_**Note:** The `id` field is requested in the response in this example, but this is optional. It is used here to demonstrate that the correct user is returned._ - -### Query connected resources - -In this example, imagine that in our database a `User` is associated with multiple hobbies. -The schema would look like the following: - -``` graphql -type Query { - user: User -} - -type User { - name: String - email: String - phone: String - hobbies: [Hobby] -} - -type Hobby { - name: String - frequency: String -} -``` - -The following query requests the hobbies associated with a specific user: - -``` -{ - user(id: 12345) { - name - email - phone - hobbies { - name - frequency - } - } -} -``` - -The response would look like the following: - -``` -{ - "data": { - "user": { - "name": "Jane Doe" - "email": "JaneDoe@example.com" - "phone": "012-345-6789" - "hobbies": [ - { - "name": "painting", - "frequency": "weekly" - }, - { - "name": "video games", - "frequency": "daily" - } - ] - } - } -} -``` - -Notice how the user's `hobbies` are returned in an `array` as defined in the schema. - -## Learn more - -This topic just covers the basics of GraphQL. -To learn more, visit the [GraphQL][] website. - -[GraphQL]: https://graphql.org/ \ No newline at end of file diff --git a/pwa-devdocs/src/technologies/basic-concepts/index.md b/pwa-devdocs/src/technologies/basic-concepts/index.md deleted file mode 100644 index 4442f20ccf..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/index.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Basic Concepts ---- - -The tools provided by the Magento PWA Studio project allows you to create websites that are fast, mobile-friendly, and reliable. -This topic lists the basic concepts you need to know to work with the Magento PWA Studio tools. - -## Application shell - -An application shell provides the basic user interface structure for a progressive web application. - -For more information, see [Application shell][]. - -## Service worker - -A service worker is a script that runs in the background. -Progressive web applications use service workers for caching and resource retrieval. -[ _[Help write this topic][service worker]_ ] - -## Component data binding - -Component data binding refers to the way data flows between the source and a UI component. -Progressive web applications use data binding patterns to connect dynamic data with the user interface. -[ _[Help write this topic][component data binding]_ ] - -## GraphQL - -GraphQL is a specification for a data query language client side and a service layer on the server side. -It is used to request and push data in a progressive web application. - -For more information, see [GraphQL][]. - -## CSS modules - -CSS modules are modular and reusable CSS styles. -This allows you to develop components with styles that do not conflict with external style definitions. - -For more information, see [CSS modules][]. - -## Client state, reducers, and actions - -Client state, reducers, and actions are [Redux][] concepts used to manage and handle the state of a web application. -[ _[Help write this topic][client state, reducers, and actions]_ ] - -## Loading and offline states - -Loading and offline are both states that must be handled by progressive web applications. -[ _[Help write this topic][loading and offline states]_ ] - -## Container extensibility - -Writing extensible containers allow others to re-use and alter your container without modifying the source. - -For more information, see [Container extensibility][]. - -## Performance patterns - -Performance is an important feature for a progressive web app. -There are many strategies and patterns available to help boost the performance of a PWA. -[ _[Help write this topic][performance patterns]_ ] - -## Root components and routing - -The root component of an application is the DOM node under which all other nodes are managed by React. -Routing is the ability to map a URL pattern to the appropriate handler. -[ _[Help write this topic][root components and routing]_ ] - -## Critical path - -The critical path for rendering refers to the steps the browser takes to process the HTML, CSS, and JavaScript files to display a website. -Optimizing the critical path is important to get the best performance out of a progressive web application. -[ _[Help write this topic][critical path]_ ] - -[container extensibility]: {%link technologies/basic-concepts/container-extensibility/index.md %} -[graphql]: {%link technologies/basic-concepts/graphql/index.md %} -[css modules]: {%link technologies/basic-concepts/css-modules/index.md %} -[application shell]: {%link technologies/basic-concepts/app-shell/index.md %} - -[redux]: https://redux.js.org/introduction/core-concepts -[service worker]: https://github.com/magento/pwa-studio -[component data binding]: https://github.com/magento/pwa-studio -[client state, reducers, and actions]: https://github.com/magento/pwa-studio -[loading and offline states]: https://github.com/magento/pwa-studio -[performance patterns]: https://github.com/magento/pwa-studio -[root components and routing]: https://github.com/magento/pwa-studio -[critical path]: https://github.com/magento/pwa-studio diff --git a/pwa-devdocs/src/technologies/basic-concepts/loading-offline-states/index.md b/pwa-devdocs/src/technologies/basic-concepts/loading-offline-states/index.md deleted file mode 100644 index a06aeb5592..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/loading-offline-states/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=13 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/performance-patterns/index.md b/pwa-devdocs/src/technologies/basic-concepts/performance-patterns/index.md deleted file mode 100644 index d092770e54..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/performance-patterns/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=16 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/root-components-routing/index.md b/pwa-devdocs/src/technologies/basic-concepts/root-components-routing/index.md deleted file mode 100644 index 9f731b7933..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/root-components-routing/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=17 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/service-worker/index.md b/pwa-devdocs/src/technologies/basic-concepts/service-worker/index.md deleted file mode 100644 index 59ee2d2d7e..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/service-worker/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=14 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/state-management/index.md b/pwa-devdocs/src/technologies/basic-concepts/state-management/index.md deleted file mode 100644 index c506303bab..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/state-management/index.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: State management ---- - -## What is state management - -An application, such as a PWA storefront, uses state data to render dynamic content to the user. -State management describes the way the application handles changing state data as a result of user interactions. - -Interactions, such as clicking on a button or loading the page, modify the state and update the appearance or behavior of the application. - -For example, a shopper clicks on a button to add an item to the shopping cart. -The application needs a way to add that item to the shopping cart while the shopper continues to browse the application. -It also needs to update the visual components that use shopping cart data to reflect the new state. - -## Local versus global state - -Local and global are the two different types of state a component can depend on. - -Local state data is any data scoped within a component or its children components. -This type of data is not shared with a component's parent or peer data. -Otherwise, that data should be [lifted][]. - -For example, a button component's disabled state is never used outside that component, so -it is categorized as local state data. - -```jsx -const MyButton = () => { - const [isDisabled, setIsDisabled] = useState(false); - - const handleClick= useCallback(() => setIsDisabled(true),[]) - - return ; -} -``` - -Global state data is any data made available to components in the entire application. -Components that depend on a global state value subscribe to changes for that value and re-render themselves. -Most components do not depend on the entire global state. -Instead, a component only uses small pieces of the entire global state. - -Shopping cart data is an example of global state data that components in different levels of the application use and modify. - -## Common state management technologies - -There are many libraries and framework features that implement state management. -This section describes two such technologies used in the PWA Studio project. - -### Redux - -[Redux][] is a state management design pattern and library. -It promotes the idea of a global object tree that contains the state of the whole application. -This object is known as a [store][]. - -The store is a read-only object, which can only be updated by dispatching a [reducer][] function. -Reducer functions accept the current state and an [action][] object as parameters and returns the next state. - -Application components are able to [dispatch][] various actions to update the state. -Components can also [subscribe][] to state changes to update their appearance or behavior. - -Early versions of PWA Studio used the Redux library directly as the primary mechanism for managing application state, -and the Redux pattern can be seen in hooks such as [`useRestResponse()`][]. - -Currently, PWA Studio abstracts away its Redux implementation details using Peregrine hooks and context providers. -This opens up the possibility of the project replacing Redux in Peregrine with another state management library without breaking state dependent components, such as those in Venia. - -PWA Studio allows you to customize reducers and enhancers. -The following example uses `combineReducers()` to combine the default Peregrine reducers with custom reducers specific to the project and uses the combined reducers when creating the Redux store. - -```jsx -// Example src/store.js file - -import { combineReducers, createStore } from 'redux'; -import { enhancer, reducers } from '@magento/peregrine'; - -import myReducers from './lib/reducers'; - -// You can add your own reducers here and combine them with the Peregrine exports. -const rootReducer = combineReducers({ ...reducers, ...myReducers }); - -export default createStore(rootReducer, enhancer); -``` - -### React hooks - -React version 16.8 introduced the concept of [hooks][]. -Hooks allow [function components][] to manage their own internal state by letting them use the same component lifecycle features available to class components. - -Earlier versions of React only allowed class components to manage state, -so stateful classes often became complex and hard to understand. -Hooks help developers to decompose large components into smaller functions that are focused on specific logic, such as fetching data. - -Since PWA Studio favors using function components over classes, it uses many of React's [built-in hooks][] in its Venia and Peregrine libraries. -The Peregrine library also provides [custom React hooks][] for storefront developers. -These hooks contain common Magento storefront logic such as state management. - -## State management in PWA Studio - -State management in PWA Studio is a mix of the Redux library, React hooks, and React context providers. -The Redux library is the underlying technology that powers state management behind the scenes, but -components do not interact with the global store directly. -Instead, components that need global state data use React hooks and context providers to read or update the current state. - -### Context providers - -React components look and behave as a result of their props. -Normally, this means an application needs to explicitly pass state data as a prop down the React application tree to components that need that data. -This is known as _prop drilling_. - -To avoid prop drilling, React provides the [Context][] feature. -The Context feature allows an application to define a value and make it available to its descendants without passing it down the tree. - -A Context object contains a Provider and Consumer property. -A `Context.Provider` component defines the shared data for its children, and -a corresponding `Context.Consumer` acquires the data and subscribes to any changes. - -PWA Studio uses the Context feature to provide application state data to storefront components through the [`PeregrineContextProvider`][] component. -Wrapping an application with the `PeregrineContextProvider` lets its components access different slices of the entire application state. - -{% raw %} - -```jsx -// Example src/index.js - -import React from 'react'; -import ReactDOM from 'react-dom'; - -import { Adapter } from '@magento/venia-drivers'; -import { PeregrineContextProvider } from '@magento/peregrine'; - -import store from './store'; // This was defined in the previous example -import MyApplication from `./src/components/MyApplication`; - -const apiBase = new URL('/graphql', location.origin).toString(); - -ReactDOM.render( - - , - document.getElementById('root') -); - -``` - -{% endraw %} - -### Global state slices - -Peregrine exposes global state data in slices through the `PeregrineContextProvider` component and custom React hooks. -A state data slice is a subset of values from the global state. -Each slice contains data about a specific part of the application, such as the shopping cart state or user session state. - -To access a global state slice, wrap the `PeregrineContextProvider` around the main application (as shown in the previous example). - -Next, import the appropriate [context hook][] and decompose the array returned by the hook function call. -The decomposed array yields the state data and an API object to update that state. - -```jsx -// Example src/components/MyWelcomeMessage/myWelcomeMessage.js - -import { useUserContext } from '@magento/peregrine/lib/context/user'; - -const MyWelcomeMessage = () => { - const [userContext, userContextApi] = useUserContext(); - - const {isSignedIn, currentUser} = userContext; - const { firstname, lastname } = currentUser; - - if(isSignedIn){ - return Welcome {firstname} {lastname}!; - } - - return null; - -} - -export default MyWelcomeMessage; -``` - - -[`userestresponse()`]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/hooks/useRestResponse.js -[`peregrinecontextprovider`]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/PeregrineContextProvider/peregrineContextProvider.js -[context hook]: https://github.com/magento/pwa-studio/tree/develop/packages/peregrine/lib/context - -[redux]: https://redux.js.org/introduction/getting-started -[store]: https://redux.js.org/glossary#store -[reducer]: https://redux.js.org/glossary#reducer -[action]: https://redux.js.org/basics/actions -[dispatch]: https://redux.js.org/api/store#dispatchaction -[subscribe]: https://redux.js.org/api/store#subscribelistener -[hooks]: https://reactjs.org/docs/hooks-intro.html -[function components]: https://reactjs.org/docs/components-and-props.html#function-and-class-components -[built-in hooks]: https://reactjs.org/docs/hooks-reference.html -[custom react hooks]: https://reactjs.org/docs/hooks-custom.html -[context]: https://reactjs.org/docs/context.html -[lifted]: https://reactjs.org/docs/lifting-state-up.html diff --git a/pwa-devdocs/src/technologies/contribute/index.md b/pwa-devdocs/src/technologies/contribute/index.md deleted file mode 100644 index bacfbe9b11..0000000000 --- a/pwa-devdocs/src/technologies/contribute/index.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Contributing ---- - -Thank you for your interest in contributing to the PWA Studio project! - -Before you start, please take a moment to read through the following guidelines: - -- [Code of Conduct][] -- [Support][] - -## Terms - -**Core Team** -: The Magento core engineering/product team working on the PWA Studio project. - -**Community Maintainer** -: A community point of contact approved by the Core Team to help with project administration. - -Current list of maintainers: - -- [Jordan Eisenburger](https://github.com/Jordaneisenburger) -- [Lars Roettig](https://github.com/larsroettig) - -**Community Advisory Board** -: Consists of Community Maintainer(s) and Core Team members who help drive prioritization and scoping for community driven **help wanted** features and enhancements. - -**Directly Responsible Individual** -: The assigned developer for a specific issue. -This person is responsible for ensuring the issue is completed in a reasonable amount of time and to a certain standard. - -## Ways to contribute - -- [Identify and create issues](#identify-and-create-issues) -- [Select a groomed issue](#select-a-groomed-issue) -- [Help answer community questions](#help-answer-community-questions) - -### Identify and create issues - -If you encounter an issue while using PWA Studio or you have a suggestion for a new feature, let us know by [creating an issue][]. -Provide as much detail as you can to help us reproduce or analyze the issue before prioritizing it. - -When the issue is created, it is placed in the **Backlog** column of the [Community Backlog][] project. -Contact someone from the Community Advisory Board to bring the issue to our attention and we will add the **help wanted** label to it. - -_Please avoid creating GitHub issues asking for help on bugs in your own project that are outside the scope of this project._ - -#### Grooming new issues - -Every week, the Community Advisory Board meets to look at the **Backlog** column of the Community Backlog project. -The board grooms the backlog issues and moves issues that are well-defined and has value to the **Prioritized** column. - -If an issue does not provide enough details or provides no value, we will leave a comment and give you an opportunity to respond. -If there is no response before the next grooming session, the issue is closed. - -### Select a groomed issue - -The main way to contribute to the project is by working on an issue. -Look through the **Prioritized** column in the [Community Backlog][] for issues that are available for you to work on. - -_Do not attempt to work on something unrelated to the issues inside the **Prioritized** column._ - -If you see an issue you would like to work on in the **Prioritized** column, notify a Community Maintainer in the issue comments (by using @) to let them know you are interested. -The Community Maintainer will follow up with you to make sure you understand the scope of the changes being asked for in the issue. - -After the Community Maintainer assigns the issue to you, it is moved to the **In Progress** column of the [Community Backlog][] to prevent others from picking up the issue. - -#### Working on the solution - -As a contributer, you should familiarize yourself with the project's [coding standards and conventions][]. - -The issue will provide you with guidance for what we think the solution should look like. -If you are unsure about anything, reach out to anyone in the Community Advisory Board and we will provide more details. - -To get your contribution accepted, you must sign [Adobe's Contributor License Agreement (CLA)](https://opensource.adobe.com/cla.html). -You only need to sign the CLA once. - -#### PR review process - -After you submit your PR, the Community Advisory Board will assign one or more reviewers to look over your solution and ensure quality and adherence to standards. -As the Directly Responsible Individual for the issue, you are expected to address all feedback before the issue is sent to our QA and merged. - -If at any point in the review cycle you have commitments preventing you from addressing feedback, or -if there is a suggestion you do not understand, please let us know! -We are happy to pair program or complete those changes for you to help push the PR across the finish line. - -If you would like to do a demo of your PR at our weekly community sync on Fridays, let a Community Maintainer know so you can be added to the schedule. - -### Help answer community questions - -Another way to help contribute to this project is to help answer community questions about PWA Studio. - -Our community is growing every day, and people are evaluating or trying out PWA Studio for the first time. -Join our [#pwa Slack channel][] and help out fellow community members with their questions or share your experiences working with PWA Studio! - -[code of conduct]: CODE_OF_CONDUCT.md -[support]: SUPPORT.md -[community backlog]: https://github.com/magento/pwa-studio/projects/3 -[#pwa slack channel]: https://magentocommeng.slack.com/archives/C71HNKYS2 -[creating an issue]: https://github.com/magento/pwa-studio/issues/new/choose -[coding standards and conventions]: https://github.com/magento/pwa-studio/wiki/Project-coding-standards-and-conventions diff --git a/pwa-devdocs/src/technologies/magento-compatibility/index.md b/pwa-devdocs/src/technologies/magento-compatibility/index.md deleted file mode 100644 index fee5103e80..0000000000 --- a/pwa-devdocs/src/technologies/magento-compatibility/index.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Magento compatibility ---- - -This page lists PWA Studio versions and their compatible Magento core version. - - - -{% include auto-generated/magento-compatibility.md %} - -## What compatibility means - -If you are working directly with the PWA Studio repository, make sure the version you are working with is compatible with your Magento backend. - -GraphQL queries in Venia are a main source of incompatibility between versions. -Breaking GraphQL schema changes in Magento require an update to the GraphQL queries used in the Venia storefront. - -## Incompatibility scenarios - -- A developer has the latest PWA Studio, such as **2.1.0** or greater, but the `MAGENTO_BACKEND_URL` still points to a Magento 2 instance running **2.3.0**. -- A developer is running an older version of PWA Studio, such as **2.0.0**, but the `MAGENTO_BACKEND_URL` points to a Magento 2 instance running **2.3.1**. - -## Compatibility checks - -Since **2.1.0**, PWA Studio includes a query validation step during the build process. -This step reports on any GraphQL incompatibility it encounters. - -## Solving compatibility issues - -Developers have two options for solving compatibility issues: - -- Upgrade or downgrade the PWA Studio version to match the Magento 2 backend version -- Upgrade or downgrade the backend Magento 2 version to match the PWA Studio version diff --git a/pwa-devdocs/src/technologies/overview/images/pwa-studio-developer-overview.png b/pwa-devdocs/src/technologies/overview/images/pwa-studio-developer-overview.png deleted file mode 100644 index 8c5b20d8ca..0000000000 Binary files a/pwa-devdocs/src/technologies/overview/images/pwa-studio-developer-overview.png and /dev/null differ diff --git a/pwa-devdocs/src/technologies/overview/index.md b/pwa-devdocs/src/technologies/overview/index.md deleted file mode 100644 index 1876869653..0000000000 --- a/pwa-devdocs/src/technologies/overview/index.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Overview ---- - -This page provides a brief description of a Progressive Web App (PWA) and its relationship to the Magento PWA Studio project. - -## What is a Progressive Web App - -A Progressive Web App, or PWA, is a web application that uses modern web technologies and design patterns to provide a reliable, fast, and engaging user experience. - -The following features define a basic PWA website: - -- **Fast** - PWA sites use a variety of performance optimization strategies to provide a responsive experience or load content fast, even on slow networks. -- **Secure** - PWA sites use HTTPS connections for enhanced security. -- **Responsive** - PWA sites implement responsive design strategies to provide a consistent experience on desktops, tablets, and mobile devices. -- **Cross-browser compatible** - PWA sites work equally well on all modern browsers, such as Chrome, Edge, Firefox, Safari. -- **Offline Mode** - PWA sites cache content to ensure that some content can be served when a user is offline. -- **Mobile "Install"** - Mobile users can add PWA sites to their home screens and even receive Push notifications from the site. -- **Shareable content** - Each page in a PWA site has a unique URL that can be shared with other apps or social media. - -## What is the Magento PWA Studio project - -![pwa studio overview][] - -The Magento PWA Studio project is a set of developer tools that allow for the development, deployment, and maintenance of a PWA storefront on top of Magento 2. -It uses modern [tools and libraries][] to create a build system and framework that adheres to the Magento principle of extensibility. - -The Magento PWA Studio project provides the following tools: - -- **[pwa-buildpack][] CLI tools** - Contains the main build and development tools for a Magento PWA. -- **[Peregrine][] hooks and components** - Contains a collection of useful components and custom React hooks for a Magento PWA. -- **[Venia][] store and visual components** - The Venia package contains a proof of concept Magento 2 storefront built using the PWA Studio tools. - It also provides visual components you can use in your own projects. -- **[UPWARD][]** - A specification for a file that determines the behavior of the application server. - The project provides [UPWARD-JS][], which is a JavaScript implementation of an UPWARD server. -- **[pwastudio.io][]** - The project provides documentation to help guide developers towards creating a Magento PWA storefront. -- **Shared Magento server** - Developers have access to a Magento application running in the Cloud to help jumpstart storefront development. - This server contains sample data and is maintained by the team to ensure that you are developing on the latest version of Magento. - This shared instance is open to all PWA Studio developers. - -[tools and libraries]: {% link technologies/tools-libraries/index.md %} -[pwa-buildpack]: {% link pwa-buildpack/index.md %} -[peregrine]: {% link peregrine/index.md %} -[venia]: {% link venia-pwa-concept/index.md %} -[upward]: {% link technologies/upward/index.md %} -[upward-js]: {% link technologies/upward/reference-implementation/index.md %} -[pwa studio overview]: {%link technologies/overview/images/pwa-studio-developer-overview.png %} - -[pwastudio.io]: https://pwastudio.io diff --git a/pwa-devdocs/src/technologies/storefront-architecture/buildtime/index.md b/pwa-devdocs/src/technologies/storefront-architecture/buildtime/index.md deleted file mode 100644 index 625efab799..0000000000 --- a/pwa-devdocs/src/technologies/storefront-architecture/buildtime/index.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: Buildtime architecture ---- - -The build architecture of PWA Studio is the system used to compile JavaScript and CSS source code into a production-ready PWA storefront application. - -## Magento store dependency - -PWA Studio is part of Magento's [service-oriented architecture][] vision. -This vision minimizes dependencies by separating the merchant-facing store admin and the shopper-facing storefront application. -Separating these two applications minimizes the dependencies between them. - -The Venia build system respects this principle by running the build process independent from the Magento core application. -However, the build system does use the Magento API at compilation time for additional validation and optimization of storefront code. - -## Repository organization - -Unlike Magento themes, the source code for a PWA Studio storefront does not need to be located within the Magento application code. -A PWA Studio storefront and its backing Magento server are two separate applications, so -their codebase is separate from each other. - -The Venia concept storefront uses the `yarn` package for dependency management, but -storefronts built using PWA Studio can also use NPM to manage dependencies and run scripts. - -Early adopters of PWA Studio have cloned the [`pwa-studio` repository][] and made direct customizations to the Venia concept source. -This can lead to conflicts when updating to the latest version of the codebase. -The preferred approach is to add PWA Studio tools and libraries as dependencies in a project. - - - -## Build pipeline - -The build pipeline is the mechanism that consumes the project source code to generate production-ready files. -This process includes code [transpilation][] and smart script bundling. -Like most modern Web compilation tools, it is built on [NodeJS][]. - -The main tools used for the build pipeline are [Babel][] and [Webpack][]. -The Buildpack library provides a convenient API for configuring these tools, but the underlying API for building a Magento PWA is a direct configuration of Babel and Webpack. - -The Venia example storefront project contains an opinionated build pipeline setup, using Buildpack's `configureWebpack` API, but -developers can also use the PWA-Studio build libraries and configurations to define custom pipelines. - -### Venia build steps - -The following sections provide insight into the processes that make up Venia's build pipeline. - -#### Starting a build - -Venia's build process begins at the command prompt. -It is compatible with OSX and most Linux environments that use a `bash` shell. - -{: .bs-callout .bs-callout-warning} -Windows support is an ongoing project. - -PWA Studio projects use [NPM scripts][] to organize frequently used commands. -These `yarn run` commands are found in the `scripts` section of the Venia storefront's [`package.json`][] file. - -Use the `build` command to start the build process: - -```sh -yarn run build -``` - -#### Cleanup step - -The build process runs a `clean` script to remove old artifacts from the Venia concept's `dist` directory before generating the code. - -#### Environment validation - -The next phase uses the `buildpack load-env` command to load and validate the `.env` file, which describes the store project configuration. -This file is found in the root directory of the Venia concept project. - - - -{: .bs-callout .bs-callout-info} -If there is no `.env` file in your project, create one with the `buildpack create-env-file` command. - - - -#### Query validation - -After the environment validation phase, the build runs the `validate-queries` script. -This script uses the [`graphql-cli-validate-magento-pwa-queries`][] tool to analyze the GraphQL queries in the project and validates them against the schema downloaded from the configured Magento instance. - -{: .bs-callout .bs-callout-info} -The connected Magento instance is defined by the `MAGENTO_BACKEND_URL` environment variable. - -#### Webpack execution - -The final step in the build process uses the webpack CLI (`webpack`) to process files into bundles. -The `webpack.config.js` file in the storefront project's root configures webpack to use external tools, such as Babel and Workbox, during file processing and bundle creation. - -The artifacts generated by webpack are located in the `dist` folder. -These are static files ready to be served from an HTML document's app shell. - -When a browser loads these files, it launches a single-page application that is the Venia storefront. - -### Other build features - -The following build features are used mainly in a development environment. -They are not part of the normal production build process. - -#### Watch mode - -The `watch` script launches a development server and a persistent compiler process that monitors the source code for changes. -When a change is detected, it initiates an incremental rebuild instead of a full build to keep the application in the browser up to date. - -This feature allows you to make edits in the code and see the changes in the application without going through the full build process. - -#### Linting and testing - -The Venia concept project also contains scripts for formatting (`yarn run prettier`), style analysis (`yarn run lint`), and running unit tests (`yarn test`). - -Use these scripts to keep your codebase well-formatted and test functionality. - -[nodejs]: https://nodejs.org/en/about/ -[webpack]: https://webpack.js.org/ -[transpilation]: https://en.wikipedia.org/wiki/Source-to-source_compiler -[babel]: https://babeljs.io -[npm scripts]: https://docs.npmjs.com/misc/scripts -[service-oriented architecture]: https://en.wikipedia.org/wiki/Service-oriented_architecture -[`package.json`]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-concept/package.json -[`graphql-cli-validate-magento-pwa-queries`]: https://github.com/magento/pwa-studio/tree/develop/packages/graphql-cli-validate-magento-pwa-queries -[`pwa-studio` repository]: https://github.com/magento/pwa-studio/ diff --git a/pwa-devdocs/src/technologies/storefront-architecture/index.md b/pwa-devdocs/src/technologies/storefront-architecture/index.md deleted file mode 100644 index d05d37a6e1..0000000000 --- a/pwa-devdocs/src/technologies/storefront-architecture/index.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Storefront architecture ---- - -Unlike a Magento theme, which is dependent on the core Magento application, a PWA Studio storefront exists on a different application layer from Magento. -The storefront still communicates with the core Magento application, but it is not tightly coupled with it. - -The following sections provide information about Magento architecture designs that enable PWA Studio storefront development. - -## Headless architecture overview - -Headless architecture refers to the idea of separating the presentation layer from the data and business logic layer. -Decoupling these two layers give merchants the ability to make changes to the frontend without modifying code for the backend services. - -In the context of PWA Studio, the storefront is the frontend application and Magento is the connected backend service. -A PWA Studio storefront does not use any of Magento's frontend theme assets, layout files, or scripts. -Instead, it defines its own frontend files and uses Magento's GraphQL and REST services to send or request data. - -For more information about headless eCommerce, read the Magento blog post titled [The Future Is Headless][]. - -## Magento microservices - -Microservice architecture is a design pattern that separates an application into independent, deployable services. -Each independent service communicates with the others through lightweight APIs. -This is known as **service isolation**. - -Magento services, such as those for customers, product catalog, and checkout, provide an API through [service contracts][]. -PWA Studio storefronts interact with these services through [Magento's GraphQL][] and REST services. - -For more information about Magento's research on service isolation, see [Magento Service Isolation Vision][]. - -[the future is headless]: https://magento.com/blog/best-practices/future-headless -[magento's graphql]: https://github.com/magento/graphql-ce -[magento service isolation vision]: https://github.com/magento/architecture/blob/master/design-documents/service-isolation.md -[service contracts]: https://devdocs.magento.com/guides/v2.3/extension-dev-guide/service-contracts/service-contracts.html diff --git a/pwa-devdocs/src/technologies/storefront-architecture/runtime/index.md b/pwa-devdocs/src/technologies/storefront-architecture/runtime/index.md deleted file mode 100644 index 45f0a612c1..0000000000 --- a/pwa-devdocs/src/technologies/storefront-architecture/runtime/index.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Runtime architecture ---- - -A PWA Studio storefront's runtime architecture describes how each of its pieces interact with Magento when it is deployed. - -The following sections describe characteristics for the runtime architecture of storefronts built using PWA Studio. -Many of these characteristics follow Magento's vision for [service isolation][]. - -## API-only relationships - -A PWA Studio storefront application communicates with Magento using its external API. -Those external API services communicate with Magento's internal service modules and returns any results through that same external API. - -**GraphQL** is the preferred API to use for client data and store behavior. -[GraphQL API][] coverage increases with every Magento release, but -until full coverage is complete, developers can use the [**REST API**][] to fill in existing coverage gaps. - -To make secure, admin-authorized calls, configure the storefront's [UPWARD][] server to make the request using REST or RPC. - -Use **HTTPS** when passing requests through the UPWARD server to static and media resources in Magento. - -## One-way coupling - -The coupling between a PWA Studio storefront and Magento should go in one direction. -The storefront has a dependency on Magento, which is attached as a service, but -the Magento application should not have a dependency on the storefront. - -## Decoupled deployments - -A PWA Studio storefront and its backing Magento instance should be deployed as separate instances on separate hardware. -Using [UPWARD][] allows you to deploy these applications using different technology stacks with the dependency configured at build-time. - -Another option is to deploy the storefront to the Magento server directly using the [PHP implementation of UPWARD][]. -This is a possible option if the Magento instance is hosted in the [Magento cloud][]. - -## Storefront replacement mechanism - -A PWA Studio storefront replaces Magento's frontend theme. - -Since the coupling between the storefront and Magento is one way, Magento does not know to direct front end traffic to the storefront application. -This means that the Magento frontend theme, such as Luma, is still available by connecting directly to the Magento server. - -Use a [reverse proxy][] in your Magento server to route incoming frontend traffic to the storefront application. -If the storefront application is deployed in the same server as Magento, which can be the case if you are using [Magento cloud][] hosting, then the `magento-upward-connector` module handles the frontend replacement. - -[upward]: {% link technologies/upward/index.md %} -[magento cloud]: {%link tutorials/cloud-deploy/index.md %} - -[service isolation]: https://github.com/magento/architecture/blob/master/design-documents/service-isolation.md -[php implementation of upward]: https://github.com/magento-research/upward-php -[reverse proxy]: https://en.wikipedia.org/wiki/Reverse_proxy -[graphql api]: https://devdocs.magento.com/guides/v2.3/graphql/ -[**rest api**]: https://devdocs.magento.com/guides/v2.3/rest/bk-rest.html diff --git a/pwa-devdocs/src/technologies/theme-vs-storefront/index.md b/pwa-devdocs/src/technologies/theme-vs-storefront/index.md deleted file mode 100644 index 814ef2baa4..0000000000 --- a/pwa-devdocs/src/technologies/theme-vs-storefront/index.md +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: Magento theme vs PWA storefront ---- - -A traditional Magento store uses theme components to define the look and feel of the front-end store. -Magento's PWA Studio introduces a different approach for creating a custom front-end experience using storefront applications. - -This topic compares the traditional Magento theme development approach with a more modern approach of developing a Magento storefront using PWA Studio tools. - -## Definitions - -### Magento theme - -A Magento theme is a type of [Magento component][] that defines how a store looks. -It is deeply integrated with the Magento application and depends on the core Magento code for functionality. - -A Magento theme is always built on top of an existing parent theme. -Out of the box, Magento provides the **Blank** and **Luma** themes that developers extend or customize to create custom storefronts. - -All Magento themes inherit from a parent theme. -At the top of the inheritance chain is the Magento Blank theme, which provides the base files for a theme. -Every other theme builds on, overrides, or customizes these files. - -For more information on Magento themes, see the Magento 2 [Frontend Developer Guide][]. - -### Magento storefront application - -A Magento storefront application is a [progressive web app][] built using PWA Studio tools. - -It is made up of an application shell that exists in the browser and a [middle tier service layer][] that sits between the shell and a [headless Magento][] backend. - -Unlike a Magento theme, a storefront application does not inherit from a parent theme. -Instead, the application is composed of [React][] modules that provide the different pieces of functionality. -These pieces can be swapped out to change behavior or even removed entirely. - -For an example of a storefront application, read about the [Venia][] storefront, a reference implementation created using PWA Studio tools. - -### Components - -Both Magento theme and PWA storefront application use pieces that are known as **components**, but -each approach uses a different definition of this term. - -In Magento theme development, _components_ mostly refers to [Magento UI Components][]. -These components are standard UI elements, such as tables, buttons, and dialogs, that Magento provides to make theme development easier. - -In PWA Studio, _components_ refers to [React][] components. -React components are modular pieces that make up a React application, such as a Magento PWA storefront. - -## Dependency management - -A Magento theme uses a [Composer][] file to specify its dependencies and relies on Magento's file resolution mechanism to make sure the required theme files are available. - -PWA Studio uses [Yarn][] for dependency management and validation scripts to make sure it is compatible with the backend Magento server. - -## Inheritance vs modularity - -Since Magento themes inherit from a parent theme, the effort needed to create a custom storefront is dependent on the additional customizations needed on top of a base theme. -Some themes build off **Luma** or other existing themes and apply minimal customizations, such as logo and color changes, to create a unique look for a store. -Other themes use **Blank** as the base and require more customization work. - -This inheritance approach tightly couples a Magento theme with the themes up its inheritance chain. -As a result, parent theme updates can lead to unexpected side effects for its dependent child themes. - -Magento PWA storefront development uses a more modular approach for creating a storefront. - -Instead of starting with a base theme and customizing the pieces, a developer puts together a storefront from scratch using different React modules. -This approach provides greater flexibility and control during the storefront creation process. - -Since they are independent and modular, side effects from updating each piece is minimized. -Non-breaking updates can be applied to other modules while keeping others to a stable version. - -## Required skillset - -The skillset required to work with Magento themes is different from the skillset required for a PWA storefront because of the technologies used in each approach. - -### Magento frontend developers - -In addition to knowing standard JS libraries, such as jQuery and KnockoutJS, Magento theme developers need general knowledge about Magento component development and specialized knowledge about its templating and layout system. - -The following table is a summary of general skills needed for Magento theme development: - -| Skill | Description | -| -------------------------------- | ----------------------------------------------------------- | -| PHP | The primary language of the Magento codebase | -| JavaScript (JS) | Core web language | -| [jQuery][] | A JS library used for things such as DOM manipulations | -| [KnockoutJS][] | JS framework used for binding data models to the UI | -| Cascading Style Sheets ([CSS][]) | Defines the style for a websites | -| Leaner Style Sheets ([Less][]) | Language extension for CSS | -| XML | Format used by Magento for configuration and layout | -| [Magento layouts][] | Layouts represent the structure for a page | -| [Magento templates][] | Templates define how layout blocks are presented on a page | -| [Magento UI library][] | Frontend library for Magento theme developers | -| [Magento UI components][] | Another frontend library for Magento theme developers | -| [Composer][] | Package and dependency manager | -{:style="table-layout: auto;"} - -### Magento PWA storefront developers - -The barrier for entry for a PWA Studio developer is lower than a Magento theme developer. -PWA Studio development requires less Magento-specific knowledge to create a custom storefront, and -the tools and concepts it uses are more common and standard among the general front-end developer community. - -The following table is a summary of general skills needed for PWA storefront development: - -| Skill | Description | -| ------------------------------------- | --------------------------------------------------- | -| JavaScript (JS) | Core web language | -| [React][] | A JS library for building user interfaces | -| [Redux][] | A JS library for handling application state | -| [GraphQL][] | An API query language | -| [webpack][] | Project assets bundler | -| Cascading Style Sheets ([CSS][]) | Defines the style for a websites | -| [CSS modules][] | Locally scoped style definitions | -| JavaScript Object Notation ([JSON][]) | Data-interchange format | -| [Peregrine][] | React components library provided by the PWA Studio | -| [Yarn][] | JS package and dependency manager | -{:style="table-layout: auto;"} - -[progressive web app]: {%link technologies/overview/index.md %} -[Venia]: {%link venia-pwa-concept/index.md %} -[middle tier service layer]: {%link technologies/upward/index.md %} -[GraphQL]: {%link technologies/basic-concepts/graphql/index.md %} -[CSS modules]: {%link technologies/basic-concepts/css-modules/index.md %} -[Peregrine]: {%link peregrine/index.md %} - -[Magento component]: https://devdocs.magento.com/guides/v2.1/extension-dev-guide/bk-extension-dev-guide.html -[headless Magento]: https://magento.com/blog/best-practices/future-headless -[KnockoutJS]: https://knockoutjs.com/ -[jQuery]: https://jquery.com/ -[Less]: http://lesscss.org/ -[CSS]: https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/css-topics/css-overview.html -[Magento UI library]: https://magento-devdocs.github.io/magento2-ui-library/ -[Magento layouts]: https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/layouts/layout-overview.html -[Magento templates]: https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/templates/template-overview.html -[Magento UI components]: https://devdocs.magento.com/guides/v2.3/ui_comp_guide/bk-ui_comps.html -[React]: https://reactjs.org/ -[Redux]: https://redux.js.org/ -[JSON]: https://www.json.org/ -[webpack]: https://webpack.js.org/ -[Yarn]: https://yarnpkg.com/ -[Composer]: https://getcomposer.org/doc/00-intro.md -[Frontend Developer Guide]: https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/bk-frontend-dev-guide.html diff --git a/pwa-devdocs/src/technologies/tools-libraries/images/pwa-tools-technology-overview.png b/pwa-devdocs/src/technologies/tools-libraries/images/pwa-tools-technology-overview.png deleted file mode 100644 index e938c1f966..0000000000 Binary files a/pwa-devdocs/src/technologies/tools-libraries/images/pwa-tools-technology-overview.png and /dev/null differ diff --git a/pwa-devdocs/src/technologies/tools-libraries/index.md b/pwa-devdocs/src/technologies/tools-libraries/index.md deleted file mode 100644 index 06cbe1844a..0000000000 --- a/pwa-devdocs/src/technologies/tools-libraries/index.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: Tools and libraries ---- - -![tools and technology overview][] - -To work with the utilities provided by the Magento PWA Studio project, you should be familiar with the tools and libraries listed in the following table: - -| | Contributor | Frontend developer | Sysadmin/Devops/Backend developer | -| ------------------------- | :-------------------------------------------: | :-------------------------------------------: | :------------------------------------------------: | -| [PHP](#php) | | | help_outline | -| [JavaScript](#javascript) | check_box | check_box | help_outline | -| [webpack](#webpack) | check_box |help_outline | | -| [React](#react) | check_box | check_box | | -| [Redux](#redux) | check_box | help_outline | | -| [GraphQL](#graphql) | check_box | check_box | check_box | -| [Workbox](#workbox) | check_box | check_box | | - -## PHP - -[PHP][] is the core language used in the Magento application, but -it is not one used by the main PWA Studio project. -In general, you do not need to know PHP to work with PWA Studio tools. - -If your storefront requires heavy customizations to the Magento backend, you will need to know PHP to make the necessary backend changes. - -## JavaScript - -[JavaScript][] is a programming language used to add logic and interactive behaviors to web applications. -JavaScript is the primary language used in the PWA Studio project, and -knowing how to develop with it is necessary for using PWA Studio in your own projects. - -For frontend development, browser compatibility is important for creating a consistent experience. -Different web browsers have different version of JavaScript installed, so -developers should build their applications with this in mind. - -For backend developers, scripts and services in PWA Studio are created using [node.js][]. -It is the environment used in the PWA Studio project, but -it is not a required one for your own projects. - -## webpack - -[webpack][] is a configuration-driven asset bundler and optimizer for JavaScript applications. - -webpack's primary function is to create one or more bundles from the dependencies in your project's modules. -webpack is also able to transform, package, or optimize resources and assets using plugins. -This allows you to extend webpack's functionality beyond JavaScript bundling. - -The [pwa-buildpack][] library contains webpack tools for setting up a development or production environment. -The configuration for these tools are found in a project's `webpack.config.js` file. - -webpack is not a required library for your own projects, but -it is recommended for the development and performance benefits it provides. - -## React - -[React][] officially describes itself as a _JavaScript library for building user interfaces_. -The library provides the following features that make PWA development easier: - -- **Simple** - The React library does one thing: build a user interface. - It does this without making assumptions about the underlying technology stack. - This flexibility gives you the freedom to choose the appropriate solutions for the rest of your project. - -- **Declarative** - Creating a complex user interface is difficult when working directly with the DOM API. - React allows you to describe how your interface should look for a specific application state, and - the library takes care of rendering the UI correctly when the state changes. - -- **Modular** - React encourages developers to create modular and reusable components. - Taking a modular approach to development makes your code easier to debug and maintain. - -### Hooks - -[React hooks][] are a feature introduced in React 16.8. -They allow the use of state and logic encapsulation without using class components. - -Since hooks allow you to store state inside functional components, they are a good alternative to using [Redux](#redux). - -The [Peregrine][] library provides custom hooks for common storefront behaviors and logic. -Developers must be familiar with using hooks to get the most out of the PWA Studo library. - -## Redux - -[Redux][] is a JavaScript library used for managing state in a web application. - -It provides a global store object that holds application state that multiple components depend on. -Components that plug into the store have direct access to the specific state data they need. - -This library is often paired with React to alleviate the problem of passing data down multiple component layers. - -{: .bs-callout .bs-callout-warning} -Redux is currently being refactored out of the [Venia example storefront][] in favor of [React hooks](#hooks). -However, Redux is still a valid library for managing state in your own projects. - -## GraphQL - -[GraphQL][] is a specification for a data query language on the client side and a service layer on the server side. -It is often seen as an alternative to using [REST][] endpoints. - -One of the main advantages GraphQL has over REST is that a single GraphQL endpoint can accommodate requests for any combination of X, Y, and Z pieces of data, -whereas REST requires specialized endpoints for different data request combinations. -Unlike REST, which can require multiple server requests to aggregate data, -a single GraphQL request returns only the data needed and nothing more. - -Performance is an important metric for PWAs. -Using GraphQL improves this by reducing the number of server calls and the amount of data returned. - -The [Venia example storefront][] uses the [Apollo client][] to fetch data from a GraphQL endpoint, but -with a little extra work, it is possible to use alternative client libraries in your own project. - -## Workbox - -Google's [Workbox][] library provides modules that make it easy to work with [service workers][]. -It is useful for boosting performance by controlling cache behavior and enables offline mode, which is a requirement for any Progressive Web Application. - -[pwa-buildpack]: {% link pwa-buildpack/index.md %} -[tools and technology overview]: {%link technologies/tools-libraries/images/pwa-tools-technology-overview.png %} -[venia example storefront]: {% link venia-pwa-concept/index.md %} -[peregrine]: {%link peregrine/index.md %} - -[webpack]: https://webpack.js.org/ -[react]: https://reactjs.org/ -[redux]: https://redux.js.org/ -[graphql]: https://graphql.org/ -[rest]: https://en.wikipedia.org/wiki/REST -[javascript]: https://developer.mozilla.org/en-US/docs/Learn/JavaScript -[node.js]: https://nodejs.org/en/about/ -[php]: https://php.net/ -[react hooks]: https://reactjs.org/docs/hooks-intro.html -[apollo client]: https://www.apollographql.com/docs/react/why-apollo/ -[workbox]: https://developers.google.com/web/tools/workbox/ -[service workers]: https://developers.google.com/web/fundamentals/primers/service-workers/ diff --git a/pwa-devdocs/src/technologies/upward/images/upward-server-diagram.png b/pwa-devdocs/src/technologies/upward/images/upward-server-diagram.png deleted file mode 100644 index b28e7d4f7e..0000000000 Binary files a/pwa-devdocs/src/technologies/upward/images/upward-server-diagram.png and /dev/null differ diff --git a/pwa-devdocs/src/technologies/upward/index.md b/pwa-devdocs/src/technologies/upward/index.md deleted file mode 100644 index f8d8127dae..0000000000 --- a/pwa-devdocs/src/technologies/upward/index.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: UPWARD ---- - -**UPWARD** is an acronym for Unified Progressive Web App Response Definition. -An UPWARD definition file describes how a web server delivers and supports a Progressive Web Application. - -UPWARD definition files provide details about server behavior using platform-independent, [declarative][] language. -This lets a Progressive Web Application run on top of an UPWARD-compliant server in any language on any tech stack because the application is only concerned about the HTTP endpoint behavior from the UPWARD server. - -The main purpose of an UPWARD server is to do the following: - -1. Receive a request from the [application shell][] -1. Determine the appropriate service or process to handle the request -1. Get the results from the service or process -1. Build the HTTP response from the results -1. Send the response back to the application shell - -## Where UPWARD belongs in the PWA architecture - -An UPWARD server sits between a PWA and its resources, such as Magento. -It acts as the backend service for a PWA frontend that is able to proxy requests to connected services or serve static files. - -![UPWARD server diagram]({% link technologies/upward/images/upward-server-diagram.png %}) - -See [RATIONALE.md][] in the `upward-spec` package for a more detailed explanation of the need for an UPWARD server. -### UPWARD definition file - -An UPWARD server uses a definition file to determine the appropriate process or service for a request from an application shell. -It describes how the server should handle a request and build the response for it. - -A PWA project can include an UPWARD definition file to specify its service dependencies. -Using this definition file, an UPWARD server can be created using any language. -The [`upward.yml`][] file in the Venia storefront package is an example of an UPWARD definition file, and -the [upward-js][] server is JavaScript implementation of that specification. - -A PWA project can also use a definition file to discover the services for an existing UPWARD server and build around that specification. - -## Characteristics of an UPWARD server - -UPWARD server implementations need to have the following characteristics: - -### Idempotent - -Requests sent to an UPWARD server are [idempotent][]. -This means that a request to the server has no side effects, so -it does not matter if you send the same request multiple times to the server. - -### Provide a simple communication strategy for services - -All services provided by the server are available through a single data exchange strategy, such as GraphQL. -Limiting the methods of communication between a PWA and its resources simplifies PWA development. -It removes the responsibility of knowing how to work with different external resources and -allows developers to concentrate on using a single, familiar technology. - -### Contain no business logic - -Having business logic spread across multiple architectural layers is an antipattern that harms testability. -The declarative nature of an UPWARD specification prevents the creation of arbitrary business logic on the server. -It pushes this logic into re-usable templates or queries, the frontend application, or the backend services, so it cannot hide in the middle tier. - -### Stateless - -Since an UPWARD server cannot contain business logic, it also cannot hold a local state. -This responsibility is also moved to the frontend or backend layer. - -### Secure - -UPWARD server implementations must serve data over [HTTPS][] to protect the information and privacy of PWA users. - -### Support caching - -An UPWARD server itself is not a cache, -but it must serve static resources from [edge servers][] when possible. -This supports the need for content that a PWA can [cache and reuse when offline][]. - ---- - -**Next:** [Reference Implementation][] - -[choreograph]: https://en.wikipedia.org/wiki/Service_choreography -[application shell]: https://developers.google.com/web/fundamentals/architecture/app-shell -[declarative]: https://en.wikipedia.org/wiki/Declarative_programming -[gateway]: https://docs.microsoft.com/en-us/azure/architecture/patterns/gateway-aggregation -[HTTPS]: https://developers.google.com/web/fundamentals/security/encrypt-in-transit/why-https -[edge servers]: https://en.wikipedia.org/wiki/Content_delivery_network -[idempotent]: https://developer.mozilla.org/en-US/docs/Glossary/Idempotent -[RATIONALE.md]: https://github.com/magento/pwa-studio/blob/master/packages/upward-spec/RATIONALE.md -[`upward.yml`]: https://github.com/magento/pwa-studio/blob/master/packages/venia-concept/upward.yml -[upward-js]: https://github.com/magento/pwa-studio/tree/master/packages/upward-js -[cache and reuse when offline]: https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/ - -[Reference Implementation]: {% link technologies/upward/reference-implementation/index.md %} diff --git a/pwa-devdocs/src/technologies/upward/reference-implementation/index.md b/pwa-devdocs/src/technologies/upward/reference-implementation/index.md deleted file mode 100644 index dbcb395f7b..0000000000 --- a/pwa-devdocs/src/technologies/upward/reference-implementation/index.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Reference Implementation ---- - -The [upward-js][] package is a reference implementation of the [UPWARD][] specification built using JavaScript. -This package is able to run as standalone server or as an Express/Connect middleware. - -{: .bs-callout .bs-callout-info } -If you followed the instructions for [Setting up Venia][], it automatically sets up and uses this implementation as its application shell server. - -## Installation - -Use the following command to install upward-js in your project: - -```sh -yarn add @magento/upward-js -``` - -## Usage - -Use the command line, server API, or middleware API to launch the upward-js server. - -### Command line - -You can make this project available to the command line by installing it globally: - -```sh -yarn global add @magento/upward-js -``` - -Launch the server in the foreground using the following command: - -```sh -upward-js-server -``` - -This command does not take arguments. -Instead, it uses the following environment variables for configuration: - -| Variable | Required | Description | -| ----------------------- | -------- | ------------------------------------------- | -| `UPWARD_JS_UPWARD_PATH` | Yes | The path to the server definition file. | -| `UPWARD_JS_BIND_LOCAL` | Yes | This must be set to 1. | -| `UPWARD_JS_LOG_URL` | No | Prints the bound URL to stdout if set to 1. | -{:style="table-layout:auto"} - -### Server API - -Require `server` from `@magento/upward-js` in your Node script to import the server into your project. - -Example: - -``` js -const { server } = require('@magento/upward-js'); - -const { app } = upward({ - upwardPath: './my-upward-server.yml' -}) - -app.listen(8000); -``` - -### Middleware API - -Use `middleware` from `@magento/upward-js` to use the middleware into your project. -This middleware is compatible with Express 4, Connect, and other frameworks that use this common pattern. -It returns a Promise for a function which handles request/response pairs. - -Example: - -``` js -const express = require('express'); -const { middleware } = require('@magento/upward-js'); - -const app = express(); - -app.use(otherMiddlewaresMaybe); - -app.use(middleware('./my-upward-server.yml')); -``` - -You can also pass an `IOAdapter` as a second argument to the middleware. - -[upward-js]: https://github.com/magento/pwa-studio/tree/master/packages/upward-js - -[UPWARD]: {% link technologies/upward/index.md %} -[Setting up Venia]: {% link venia-pwa-concept/setup/index.md %} diff --git a/pwa-devdocs/src/technologies/versioning/index.md b/pwa-devdocs/src/technologies/versioning/index.md deleted file mode 100644 index ae398c49d7..0000000000 --- a/pwa-devdocs/src/technologies/versioning/index.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: Versioning strategy ---- - -## Rules for incrementing the version - -PWA Studio follows [Semantic Versioning][] rules when incrementing the version for each release. - -According to the Semantic Versioning specifications, given the `MAJOR.MINOR.PATCH` version number format: - -* **MAJOR** version increases happen when there are changes to the [public API][]. -* **MINOR** version increases happen when functionality is added while preserving backwards compatibility. -* **PATCH** version increases happen for backwards-compatible bug fixes. - -See [Semantic Versioning][] documentation for specific details about the type of changes allowed within each version. - -## Public API - -PWA Studio considers the following to be part of its public API: - -### Published Venia and Peregrine components - -Venia and Peregrine make their components available through their `index.js` files. -Any component exported through this file is considered public API. - -Sub-components can be found inside component directories. -These components are not part of the public API unless they are exported in the component's `index.js` file. - -### Component props - -React components use props as input data to define how they look and behave. - -Since props affect how a component renders or acts, the props used by published PWA Studio components are considered public API. - -[Semantic Versioning]: https://semver.org/ -[public API]: #public-api diff --git a/pwa-devdocs/src/tutorials/cloud-deploy/index.md b/pwa-devdocs/src/tutorials/cloud-deploy/index.md deleted file mode 100644 index a9d07ae044..0000000000 --- a/pwa-devdocs/src/tutorials/cloud-deploy/index.md +++ /dev/null @@ -1,244 +0,0 @@ ---- -title: Magento Cloud deployment ---- - -## Prerequisites - -- An existing Magento Cloud project -- Composer -- Yarn or NPM -- A [Magento PWA Studio][] storefront managed by NPM or Yarn. - You are not required to publish to npmjs.com, but - NPM or Yarn should be able to access your project code through Git. - -For this tutorial, the [`@magento/venia-concept`][] package for the [Venia storefront][] is used as a template, but any PWA available though NPM with an UPWARD compatible YAML file is supported. - -These instructions provide a method for building your application bundle in the Magento Cloud, but -you can get the same results by building locally with the same environment variables as your targeted production environment, and then checking your local build artifacts into source control. - -{: .bs-callout .bs-callout-warning} -Magento Cloud does not support node processes, so you cannot use UPWARD-JS to serve your storefront project. -You must use the [magento2-upward-connector][] module with [UPWARD-PHP][] to deploy your storefront in Magento Cloud. - -## Add Composer dependencies - -Use the `composer` CLI command to include the UPWARD module in the Magento installation: - -```sh -composer require magento/module-upward-connector -``` - -This command modifies the `composer.json` file and adds the package entry to the `require` section of the `composer.json` file. - -```json -"magento/module-upward-connector": "^1.0.1" -``` - -## Add Venia sample data (optional) - -The Venia storefront works best with the Venia sample data installed. There is an [automated script](https://pwastudio.io/venia-pwa-concept/install-sample-data/) in the `@magento/venia-concept` package, or you can follow the manual steps here. - -If you are deploying your own custom storefront, you may skip this step and continue to the next section. - -### Add sample data repository information - -Use the `composer` CLI to add the sample data repositories to the `composer.json` file: - -```sh -composer config repositories.catalog-venia vcs https://github.com/PMET-public/module-catalog-sample-data-venia -``` - -```sh -composer config repositories.configurable-venia vcs https://github.com/PMET-public/module-configurable-sample-data-venia -``` - -```sh -composer config repositories.customer-venia vcs https://github.com/PMET-public/module-customer-sample-data-venia -``` - -```sh -composer config repositories.tax-venia vcs https://github.com/PMET-public/module-tax-sample-data-venia -``` - -```sh -composer config repositories.sales-venia vcs https://github.com/PMET-public/module-sales-sample-data-venia -``` - -```sh -composer config repositories.media-venia vcs https://github.com/PMET-public/sample-data-media-venia -``` - -These commands add the following entries to the `composer.json` file: - -```json -"catalog-venia": { - "type": "vcs", - "url": "https://github.com/PMET-public/module-catalog-sample-data-venia" - -}, - "configurable-venia": { - "type": "vcs", - "url": "https://github.com/PMET-public/module-configurable-sample-data-venia" - - }, - "customer-venia": { - "type": "vcs", - "url": "https://github.com/PMET-public/module-customer-sample-data-venia" - - }, - "tax-venia": { - "type": "vcs", - "url": "https://github.com/PMET-public/module-tax-sample-data-venia" - - }, - "sales-venia": { - "type": "vcs", - "url": "https://github.com/PMET-public/module-sales-sample-data-venia" - - }, - "media-venia": { - "type": "vcs", - "url": "https://github.com/PMET-public/sample-data-media-venia" - - }, -``` - -### Require the sample data modules - -Run the following `composer` CLI commands to install the sample data modules into Magento: - -```sh -composer require magento/sample-data-media-venia:dev-master -``` - -```sh -composer require magento/module-catalog-sample-data-venia:dev-master -``` - -```sh -composer require magento/module-configurable-sample-data-venia:dev-master -``` - -```sh -composer require magento/module-customer-sample-data-venia:dev-master -``` - -```sh -composer require magento/module-tax-sample-data-venia:dev-master -``` - -```sh -composer require magento/module-sales-sample-data-venia:dev-master -``` - - -These commands modify the `composer.json` file and adds the sample data modules to the `require` section: - -```json -"magento/module-catalog-sample-data-venia": "dev-master", -"magento/module-configurable-sample-data-venia": "dev-master", -"magento/module-customer-sample-data-venia": "dev-master", -"magento/module-tax-sample-data-venia": "dev-master", -"magento/module-sales-sample-data-venia": "dev-master", -"magento/sample-data-media-venia": "dev-master", -``` - -## Install dependencies - -### Composer dependencies - -_Optional_: If you manually modified the `composer.json` file to make the changes described in the previous steps, update your `composer.lock` with these new dependencies: - -```sh -composer update -``` - -## Specify Cloud server environment - -{: .bs-callout .bs-callout-info} -If you build your project locally and check the build artifacts into your Magento Cloud project, skip the **Install NPX and Yarn** and **Update build hooks** sections. - -### Install NPX and Yarn - -If your project supports Yarn, which is the case for `venia-concept`, add the following entry to the `.magento.app.yaml` file. - -```yaml -dependencies: - nodejs: - yarn: "*" -``` - -### Update build hooks - -The `venia-concept` storefront uses a newer version of Node than the default environment provides. -It also uses Yarn to install its dependencies. - -The following update to the `hooks.build` section of `.magento.app.yaml` installs NVM and the latest LTS release of Node. - -It also uses NPX to run the `buildpack` CLI tool with the `create-project` sub-command to scaffold the application using the `venia-concept` template. -After scaffolding completes, it installs and builds the application and moves the build artifact to a persistent area on the file system. - -```yaml -hooks: - # We run build hooks before your application has been packaged. - build: | - set -e - - unset NPM_CONFIG_PREFIX - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.35.1/install.sh | bash - export NVM_DIR="$HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - nvm install --lts=dubnium - - npx @magento/pwa-buildpack create-project /tmp/pwa --template venia-concept --backend-url https://[your-cloud-url-here] --name Venia --author Magento --install false --npm-client yarn - cd /tmp/pwa - # Override this environment variable at runtime given all scaffolded dependencies are devDependencies - NODE_ENV=development yarn install --ignore-optional - yarn build - cp -p -r dist/ "$HOME/pwa" - cd $HOME - - php ./vendor/bin/ece-tools build:generate - php ./vendor/bin/ece-tools build:transfer -``` - -### Add required environment variables - -Use the Magento Cloud GUI or modify the `variables.env` entry in `.magento.app.yaml` to add any required environment variables. - -The following table lists the required environment variables for the Venia storefront: - -| Name | Value | -| ------------------------------------ | ------------------------------------------------------------------------------------------------------- | -| `CONFIG__DEFAULT__WEB__UPWARD__PATH` | `/app/pwa/upward.yml` (absolute path to UPWARD YAML configuration) | -| `NODE_ENV` | `production` | -| `MAGENTO_BACKEND_URL` | `https://[your-cloud-url-here]` | -| `CHECKOUT_BRAINTREE_TOKEN` | `- -- ` | -| `MAGENTO_BACKEND_EDITION` | `EE` (enable Magento Commerce features) | -| `IMAGE_OPTIMIZING_ORIGIN` | `backend` (use Fastly for image optimization) | - -## Commit modified files - -Commit all changes to the following files: - -- `.magento.app.yaml` -- `composer.json` -- `composer.lock` - -## Push changes - -Push your local changes for your deployment and wait for it to complete. - -## Congratulations - -You have installed a PWA storefront on the Cloud! - -You should be able to navigate to the frontend URL of your Cloud instance and see your PWA storefront. - -[magento pwa studio]: http://pwastudio.io -[`@magento/venia-concept`]: https://www.npmjs.com/package/@magento/venia-concept -[venia storefront]: https://pwastudio.io/venia-pwa-concept/ -[create a `package.json`]: https://docs.npmjs.com/cli/init - -[magento2-upward-connector]: https://github.com/magento-research/magento2-upward-connector -[upward-php]: https://github.com/magento-research/upward-php diff --git a/pwa-devdocs/src/tutorials/create-taglist-component/images/hard-coded-list.png b/pwa-devdocs/src/tutorials/create-taglist-component/images/hard-coded-list.png deleted file mode 100644 index 2989374909..0000000000 Binary files a/pwa-devdocs/src/tutorials/create-taglist-component/images/hard-coded-list.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/create-taglist-component/images/real-data-list.png b/pwa-devdocs/src/tutorials/create-taglist-component/images/real-data-list.png deleted file mode 100644 index d814cc9046..0000000000 Binary files a/pwa-devdocs/src/tutorials/create-taglist-component/images/real-data-list.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/create-taglist-component/images/styled-list.png b/pwa-devdocs/src/tutorials/create-taglist-component/images/styled-list.png deleted file mode 100644 index 3749601fc3..0000000000 Binary files a/pwa-devdocs/src/tutorials/create-taglist-component/images/styled-list.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/create-taglist-component/images/unstyled-list.png b/pwa-devdocs/src/tutorials/create-taglist-component/images/unstyled-list.png deleted file mode 100644 index 0a2de1d559..0000000000 Binary files a/pwa-devdocs/src/tutorials/create-taglist-component/images/unstyled-list.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/create-taglist-component/index.md b/pwa-devdocs/src/tutorials/create-taglist-component/index.md deleted file mode 100644 index e3d2778273..0000000000 --- a/pwa-devdocs/src/tutorials/create-taglist-component/index.md +++ /dev/null @@ -1,463 +0,0 @@ ---- -title: Create a tag list component ---- - -This tutorial provides the steps for creating a tag list component for a storefront. -For this tutorial, the tag list is added to the product details page in the Venia storefront. - -## Prerequisites - -Before you start this tutorial, make sure you have a storefront development environment set up. - -The general steps provided by this tutorial can apply to different kinds of setup, but -the specific details assumes that you followed the steps in the [Venia storefront setup][] topic to set up a storefront for development. - -## Step 1. Create component directory and files - -Inside your project's directory for components, create a new directory called **TagList**. -In the `pwa-studio` project, this directory is `packages/venia-ui/lib/components`. - -Inside the **TagList** directory, create empty files with the following names: - -- `index.js` -- `tag.css` -- `tag.js` -- `tagList.css` -- `tagList.js` - -{: .bs-callout .bs-callout-info} -These names follow the [naming conventions][] used in the `pwa-studio` project. - -## Step 2. Define the `Tag` module - -The `Tag` module is responible for rendering a single tag in the tag list. - -Open the `tag.js` file and add the following content: - -```jsx -import React from 'react'; - -// Use the prop-types module for type checking -import { string } from 'prop-types'; - -// This is a component responsible for rendering a single tag -const Tag = props => { - - // Destructure the props object into variables - const { value } = props; - - // Return the tag string inside a list item element - return {value} ; -} - -// Define the props this component accepts -Tag.propTypes = { - value: string -} - -// Make this function the default exported of this module -export default Tag; -``` - -## Step 3. Define the `TagList` module - -The `TagList` module accepts an array of strings and returns a `div` container with a list of tags. -This module is the default module exported by the `index.js` file. - -Open the `tagList.js` file and add the following content: - -```jsx -import React from 'react'; - -import { arrayOf, string } from 'prop-types'; - -// Import the previously defined Tag component -import Tag from './tag'; - -// This is the main tag list component -const TagList = props => { - - // Destructure the props object into variables - const { tagArray } = props; - - // Convert the array of tag strings into a list of Tag components - const tagList = tagArray.map(value => { - return; - }) - - // Returns the list of Tag components inside a ul container - return {tagList}
; -} - -TagList.propTypes = { - // tagArray is expected to be an array of strings - tagArray: arrayOf(string) -} - -export default TagList; -``` - -## Step 4. Expose the module's public API - -Open the component's `index.js` file and add the following content: - -```js -export { default } from './tagList'; -``` - -Exporting modules from your component's `index.js` file is a commond standard in a React project. -It allows a component to import this component using its directory name. - -## Step 5. Add component to the product details page - -Find the component that renders the product details page in your storefront project and insert the TagList component into the page. - -In the `pwa-studio` project, this component is defined in the following file: - -```text -packages/venia-ui/lib/components/ProductFullDetail/productFullDetail.js -``` - -At the top of this file, import the TagList component: - -```jsx -import TagList from '../TagList'; -``` - -If you are using the default Venia ProductFullDetail component you can insert TagList into the **Product Description** section: - -```diff -- -``` - -Now, when you visit a product detail page, it will show a list with the hard coded strings. - -![TagList with hard coded strings](images/hard-coded-list.png) - -## Step 6. Connect to real product data - -To make this component useful, it needs to show actual product-specific data. -Clicking each tag should display other similarly tagged items. - -For this tutorial, the TagList component will list the product's categories. - -### Edit the GraphQL query - -Venia's ProductFullDetail component gets the product data from the GraphQL query defined in: - -```text -packages/venia-ui/lib/queries/getProductDetail.graphql -``` - -Edit the `categories` entry for this query and add the following: - -```diff - categories { - id - breadcrumbs { - category_id - } -+ name -+ url_path - } -``` - -Appending this to the query adds a `categories` object to the returned data. -This object contains information on the name and URL paths for each category. - -### Pass the categories data into the TagList component - -Open the file for the product detail component and update the code: - -```diff -- Product Description -
--+ - - -``` - -This replaces the hard coded data with actual product-specific data, but -now, the `tagArray` prop has been replaced with a `categories` prop that the component does not know how to handle. - -### Update TagList - -Open `tagList.js` and update the component to accept the new `categories` prop: - -```diff - import React from 'react'; - --import { arrayOf, string } from 'prop-types'; -+import { arrayOf, shape, string } from 'prop-types'; - - // Import the previously defined Tag component - import Tag from './tag'; - - // This is the main tag list module - const TagList = props => { - - // Destructure the props object into variables -- const { tagArray } = props; -+ const { categories } = props; - -- // Convert the array of tag strings into a list of Tag components -- const tagList = tagArray.map(value => { -- return- Product Description -
--- -+ - ; -+ // Convert the array of category objects into a list of Tag components -+ const tagList = categories.map(keyword => { -+ return ; - }) - - // Returns the list of Tag components inside a div container - return {tagList}
; - } - - TagList.propTypes = { -- // tagArray is expected to be an array of strings -- tagArray: arrayOf(string) -+ // categories is expected to be an object with a name and url_path string properties -+ categories: arrayOf( -+ shape({ -+ name: string.isRequired, -+ url_path: string.isRequired -+ }) -+ ) - } - - export default TagList; -``` - -Now, when you load the product details page, it lists the categories for that specific product: - -![List with real category data](images/real-data-list.png) - -## Step 7. Incorporate other Venia components - -Tags often look like buttons and provide a way to view other items that have the same tag when clicked. -Use the components provided by the PWA Studio libraries to add this feature. - -### Update Tag component - -Open `tag.js` and update the component to use existing Venia components: - -```diff - import React from 'react'; -+import Button from '../Button'; -+import { Link } from '@magento/venia-drivers'; - - // Use the prop-types module for type checking --import { string } from 'prop-types'; -+import { string, shape } from 'prop-types'; - -+const categoryUrlSuffix = '.html'; - - // This is a module responsible for rendering a single tag - const Tag = props => { - - // Destructure the props object into variables - const { value } = props; - -+ const { name, url_path } = value; -+ const url = `/${url_path}${categoryUrlSuffix}`; - -- // Return the tag string inside a list item element -- return{value} ; -+ // Return the tag as a Link component wrapped around a Button -+ return ( -+ -+ -+ -+ ); - } - - // Define the props this component accepts - Tag.propTypes = { -- value: string -+ value: shape({ -+ name: string.isRequired, -+ url_path: string.isRequired -+ }) - } - - // Make this function the default exported module for this file - export default Tag; -``` - -This update imports existing PWA Studio components and uses them to compose a tag button that acts as a link. - -### Update TagList component - -Since the Tag component no longer returns the tag inside a list item element, the TagList component needs to be updated to pass in the keyword object and replace the `ul` container with a `div` container: - -```diff --const tagList = categories.map(keyword => { -- return; -+const tagList = categories.map(category => { -+ return ; - }); --return {tagList}
-+return{tagList}-``` - -Now, when you open the product detail page, you see the tags listed horizontally and clicking on one takes you to that category's page. - -![Unstyled list of tag buttons](images/unstyled-list.png) - -## Step 8. Style the components - -With the click functionality in place, the last step is to add custom styles to make the tags stand out. - -### Define the TagList style - -A product can fall into multiple categories, so -the TagList style must accomodate for any number of categories. - -#### `tagList.css` - -Open the `tagList.css` file and add the following content: - -```css -.root { - display: flex; - flex-wrap: wrap; -} -``` - -This entry defines the root container of a TagList component as a [flexbox][] that wraps. -This prevents the Tags from overflowing off the side of the page. - -#### `tagList.js` - -Open the `tagList.js` file and make the following changes to the component. - -**Change 1:** Import the `mergeClasses()` function and the `tagList.css` file: - -```diff - import { arrayOf, shape, string } from 'prop-types'; - -+import { mergeClasses } from '../../classify'; -+import defaultClasses from './tagList.css'; - - import Tag from './tag'; -``` - -**Change 2:** Use the `mergeClasses()` function to merge custom classes passed into the component: - -```diff - const { categories } = props; - -+const classes = mergeClasses(defaultClasses, props.classes); -``` - -{: .bs-callout .bs-callout-info} -The `mergeClasses()` function is used for merging a component's default classes with custom class overrides. - -**Change 3:** Set the `className` property of the `div` container to the `root` class: - -```diff --return{tagList}-+return{tagList}-``` - -**Change 4:** Update the prop types with classes: - -```diff - TagList.propTypes = { - // tagArray is expected to be an array of strings - tagArray: arrayOf(string) -+ classes: shape({ -+ root: string -+ }) - } -``` - -### Define the Tag styles - -Tags need to stand out from the surrounding text and look button-like. - -#### `tag.css` - -Open the `tag.css` file and add the following content: - -```css -.root { - border: solid 1px #2680eb; - padding: 3px 9px; - margin: 5px; - border-radius: 5px; -} - -.content { - color: #2680eb; - font-size: 0.875rem; -} -``` - -#### `tag.js` - -Open the `tag.js` file and make the following changes to the component. - -**Change 1:** Import the `mergeClasses()` function and the `tag.css` file: - -```diff - import Button from '../Button'; -+import { mergeClasses } from '../../classify'; -+import defaultClasses from './tag.css'; - import { Link } from '@magento/venia-drivers'; -``` - -**Change 2:** Use the `mergeClasses()` function to merge custom classes passed into the component and create a new `buttonClasses` object: - -```diff - const { value } = props; - -+const classes = mergeClasses(defaultClasses, props.classes); -+ -+const buttonClasses = { -+ root_lowPriority: classes.root, -+ content: classes.content -+}; -``` - -The `buttonClasses` object is used to override the styles in the Button component. -The component expects a specific shape for the `classes` prop that the `buttonClasses` object fits. - -**Change 3:** Set the styles for the Link and Button component: - -```diff - return ( -- -- -- -+ -+ -+ - ); -``` - -## Congratulations - -You just created a new storefront components using PWA Studio libraries and conventions. - -![Final styled tag list component](images/styled-list.png) - -[venia storefront setup]: <{%link venia-pwa-concept/setup/index.md %}> - -[naming conventions]: https://github.com/magento/pwa-studio/wiki/Project-coding-standards-and-conventions#file-naming-and-directory-structure - -[flexbox]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox diff --git a/pwa-devdocs/src/tutorials/enable-sass-less-support/index.md b/pwa-devdocs/src/tutorials/enable-sass-less-support/index.md deleted file mode 100644 index dd6dad33cf..0000000000 --- a/pwa-devdocs/src/tutorials/enable-sass-less-support/index.md +++ /dev/null @@ -1,187 +0,0 @@ ---- -title: Enable SASS or LESS support ---- - -This tutorial provides the steps to enable SASS or LESS support in your storefront project. - -Use these Webpack configurations to add support for SASS and LESS alongside [CSS Modules][]. - -## Add SASS support - -### Step 1. Install dependencies - -Use a package manager, such as `yarn` or `npm`, to install the SASS loader as a dev dependency. - -```sh -yarn add --dev sass-loader node-sass -``` - -### Step 2. Modify the Webpack configuration - -Edit `webpack.config.js` and add a new `config` rule entry: - -```diff - - config.plugins = [ - ...config.plugins, - new DefinePlugin({ - /** - * Make sure to add the same constants to - * the globals object in jest.config.js. - */ - UNION_AND_INTERFACE_TYPES: JSON.stringify(unionAndInterfaceTypes), - STORE_NAME: JSON.stringify('Venia') - }), - new HTMLWebpackPlugin({ - filename: 'index.html', - template: './template.html', - minify: { - collapseWhitespace: true, - removeComments: true - } - }) - ]; -+ -+ config.module.rules.push({ -+ test: /\.s[ca]ss$/, -+ use: [ -+ 'style-loader', -+ { -+ loader: 'css-loader', -+ options: { -+ modules: true, -+ sourceMap: true, -+ localIdentName: '[name]-[local]-[hash:base64:3]' -+ } -+ }, -+ 'sass-loader' -+ ] -+ }); -``` - -### Step 3. Create a SASS file and import it in a component - -Create the `myComponent.scss` file: - -```scss -$button-color: #ff495b; -$button-color-hover: #ff9c1a; - -.root { - padding: 15px; -} - -.button { - color: $button-color; - - &:hover { - color: $button-color-hover; - } -} -``` - -Create a component and import the SASS file: - -```jsx -import React from 'react'; -import defaultClasses from './myComponent.scss'; - -const MyComponent = () => ( -- --); - -export default MyComponent; -``` - -## Add LESS support - -### Step 1. Install dependencies - -Use a package manager, such as `yarn` or `npm`, to install the LESS loader as a dev dependency. - -```sh -yarn add --dev less-loader less -``` - -### Step 2. Modify the Webpack configuration - -Edit `webpack.config.js` and add a new `config` rule entry: - -```diff - - config.plugins = [ - ...config.plugins, - new DefinePlugin({ - /** - * Make sure to add the same constants to - * the globals object in jest.config.js. - */ - UNION_AND_INTERFACE_TYPES: JSON.stringify(unionAndInterfaceTypes), - STORE_NAME: JSON.stringify('Venia') - }), - new HTMLWebpackPlugin({ - filename: 'index.html', - template: './template.html', - minify: { - collapseWhitespace: true, - removeComments: true - } - }) - ]; -+ -+ config.module.rules.push({ -+ test: /\.less$/, -+ use: [ -+ 'style-loader', -+ { -+ loader: 'css-loader', -+ options: { -+ modules: true, -+ sourceMap: true, -+ localIdentName: '[name]-[local]-[hash:base64:3]' -+ } -+ }, -+ 'less-loader' -+ ] -+ }); -``` - -### Step 3. Create a LESS file and import it on your component - -Create the `myComponent.less` file: - -```less -@button-color: #ff495b; -@button-color-hover: #ff9c1a; - -.root { - padding: 15px; -} - -.button { - color: @button-color; - - &:hover { - color: @button-color-hover; - } -} -``` - -Create a component and import the LESS file: - -```jsx -import React from 'react'; -import defaultClasses from './myComponent.less'; - -const MyComponent = () => ( -- --); - -export default MyComponent; -``` - -[css modules]: <{%link technologies/basic-concepts/css-modules/index.md %}> diff --git a/pwa-devdocs/src/tutorials/hello-upward/adding-react/index.md b/pwa-devdocs/src/tutorials/hello-upward/adding-react/index.md deleted file mode 100644 index b3064769c5..0000000000 --- a/pwa-devdocs/src/tutorials/hello-upward/adding-react/index.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: Adding React ---- - -This tutorial teaches you how to add webpack to your UPWARD project and use it to create a React application. - -This tutorial builds on the project described in the previous [Using the TemplateResolver][] topic. - -## Install dependencies - -Add babel, webpack, and react dependencies to the project: - -```sh -yarn add @babel/core @babel/preset-env babel-loader webpack webpack-cli @babel/preset-react react react-dom -``` - -In addition to installing React, this command installs [babel][] configurations and [webpack][]. - -In general, React components are written using ES6([ECMAScript 2015][]) and [JSX][] syntax for the convenience and ease of readability they provide. -Using [babel][] and [webpack][] is a common way to incorporate ES6 and JSX into a React project. - -## Modify template - -Modify the `hello-world.mst` template to replace the original message with a "root" DOM node for the React application: - -{% raw %} - -```diff -{{> templates/open-document}} - -{{ title }} - - {{> templates/open-body}} - -- Hello Template World! -+Loading...-+ -+ - - {{> templates/close-document}} -``` - -{% endraw %} - -This update renders a loading message in the root DOM and executes the `app.js` script after the browser parses the HTML document. - -## Create webpack config - -Create a `webpack.config.js` file to configure webpack behavior: - -```js -const path = require('path'); - -module.exports = { - mode: 'development', - entry: './src/hello-world.js', - output: { - filename: 'app.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.js$/, - exclude: /node_modules/, - loader: 'babel-loader' - } - ] - } -}; -``` - -This configuration file tells webpack to transpile all JavaScript files using babel and bundle `src/hello-world.js` with its dependencies into `dist/app.js`. - -## Create babel config - -Create a `.babelrc` file to configure babel: - -```text -{ - "presets": ["@babel/preset-env","@babel/preset-react"] -} -``` - -This configuration file tells babel what presets to use during JavaScript transpilation. -The presets used in this example, `@babel/preset-env` and `@babel/preset-react`, are common React development presets. - -## Create the React application - -Create a `src` directory in your project's root directory and a `hello-world.js` file inside that directory with the following content: - -```jsx -import React from 'react'; -import ReactDOM from 'react-dom'; - -class App extends React.Component { - render() { - returnHello React World!
; - } -} - -ReactDOM.render(, document.getElementById('root')); -``` - -This file defines an `App` React component that returns a "Hello React World!" message wrapped inside `h1` tags. -It uses the `ReactDOM` module to inject the content of the application into the "root" DOM element in the document. - -## Make the application script publicly available - -Edit the `spec.yml` file to add a new URL pattern to check in the ConditionalResolver and a new `appScript` object. - -```diff -... - -response: - resolver: conditional - when: - - matches: request.url.pathname - pattern: '^/?$' - use: helloWorld - - matches: request.url.pathname - pattern: '^/hello-world/?$' - use: helloWorld -+ - matches: request.url.pathname -+ pattern: '^/js/app.js' -+ use: appScript - default: notFound - -helloWorld: -... - -notFound: -... - -+ appScript: -+ inline: -+ status: -+ resolver: inline -+ inline: 200 -+ headers: -+ resolver: inline -+ inline: -+ content-type: -+ resolver: inline -+ inline: 'application/javascript' -+ body: -+ resolver: file -+ file: -+ resolver: inline -+ inline: './dist/app.js' -+ encoding: -+ resolver: inline -+ inline: 'utf-8' -``` - -This update uses a [FileResolver][] which instructs the UPWARD server to respond with the contents of `dist/app.js` when there is a request for the `js/app.js` path. - -## Create the bundle and start the server - -Create the `dist/app.js` bundle from `src/hello-world.js` and start the UPWARD server: - -```sh -npx webpack && node server.js -``` - -When webpack bundles `src/hello-world.js` into `dist/app.js`, it includes its dependencies, such as React and ReactDOM. - -When you navigate to the server, you will see the React application render the "Hello React World!" message using the App component. - -[Using the TemplateResolver]: {%link tutorials/hello-upward/using-template-resolver/index.md %} - -[ecmascript 2015]: http://www.ecma-international.org/ecma-262/6.0/index.html -[jsx]: https://reactjs.org/docs/introducing-jsx.html -[babel]: https://babeljs.io/ -[webpack]: https://webpack.js.org/ -[FileResolver]: https://github.com/magento/pwa-studio/tree/develop/packages/upward-spec#fileresolver diff --git a/pwa-devdocs/src/tutorials/hello-upward/simple-server/index.md b/pwa-devdocs/src/tutorials/hello-upward/simple-server/index.md deleted file mode 100644 index c547099779..0000000000 --- a/pwa-devdocs/src/tutorials/hello-upward/simple-server/index.md +++ /dev/null @@ -1,214 +0,0 @@ ---- -title: Creating a simple server ---- - -This tutorial teaches the basics of reading and writing an UPWARD specification file by creating a simple web server that returns a "Hello World" string. - -## Prerequisites - -- [Node][] >= 10.14.1 -- [Yarn][] (recommended) or [NPM][] - -## Initial setup - -1. Create the project directory and navigate into it: - - ```sh - mkdir hello-upward && cd hello-upward - ``` - -1. Use Yarn or NPM to initialize the project's `package.json` file: - - ```sh - yarn init -y - ``` - - Running this command creates a `package.json` file in your current directory. - The `package.json` file contains information about your project, such as name, version, dependencies, and runnable commands. - - The `-y` parameter is used in this tutorial to skip the interactive session. - Omit this parameter if you want to fill out information about your project during initialization. - -1. Install the `@magento/upward-js` and `express` packages: - - ```sh - yarn add @magento/upward-js express - ``` - - The [`upward-js`][] package contains modules for deploying an UPWARD-compliant server. - - [Express][] is a web framework for Node.js. - It is a dependency for the `upward-js` modules used in this tutorial. - -## Create the initial UPWARD spec - -An UPWARD server requires an [UPWARD specification][] file to tell it how to respond to requests. -Create a new file called `spec.yml` with the following content: - -```yml -status: response.status -headers: response.headers -body: response.body - -response: - resolver: inline - inline: - status: - resolver: inline - inline: 200 - headers: - resolver: inline - inline: - content-type: - resolver: inline - inline: 'text/string' - body: - resolver: inline - inline: 'Hello World!' -``` - -The first three lines set the `status`, `headers`, and `body` values required for an UPWARD server response. -These values are set by traversing a decision tree defined in the specification file. - -In this example, they are set to the `response.status`, `response.headers`, and `response.body` values defined in the `response` object. -These values are set using an UPWARD [InlineResolver][], which resolves the value of the `inline` property to a literal value. - -When passed to an UPWARD server, this file instructs the server to respond with a `200 OK` status code, content of type `text/string`, and a value of `Hello World!` in the response body for every request. - -## Create and run the server - -Create a `server.js` file with logic for starting the Node implementation of an UPWARD server. - -```js -const { createUpwardServer } = require('@magento/upward-js'); - -createUpwardServer({ - upwardPath: 'spec.yml', - bindLocal: true, - logUrl: true, - port: 8080 -}); -``` - -This file imports the `createUpwardServer` module from the `@magento/upward-js` package and uses it to start a web server. - -The script specifies the location of the UPWARD specification file through the `upwardPath` configuration and sets the port number of the server to `8080`. -The `logUrl` configuration tells the script to display the URL of the server and `bindLocal` tells it to create and bind to local HTTP server. - -Use `node` to run the server script: - -```sh -node server.js -``` - -When the server starts, the URL for the server is displayed in the terminal. - -```sh -> node server.js - -http://0.0.0.0:8080/ -``` - -Navigate to this URL in your browser to see the "Hello World!" message. - -## Define a 404 response - -When you browse to the server, every path request returns the same message. -To restrict this message to a specific path, use a ConditionalResolver. - -Edit `spec.yml` and replace the InlineResolver content of the `response` object with a [ConditionalResolver][] to define which paths return "Hello World!". - -```diff -status: response.status -headers: response.headers -body: response.body - -response: -- resolver: inline -- inline: -- status: -- resolver: inline -- inline: 200 -- headers: -- resolver: inline -- inline: -- content-type: -- resolver: inline -- inline: 'text/string' -- body: -- resolver: inline -- inline: 'Hello World!' -+ resolver: conditional -+ when: -+ - matches: request.url.pathname -+ pattern: '^/?$' -+ use: helloWorld -+ - matches: request.url.pathname -+ pattern: '^/hello-world/?$' -+ use: helloWorld -+ default: notFound -``` - -This code tells the server to look at the requested URL path and check to see if it matches the root or `/hello-world` path. -If it matches, the server uses an object called `helloWorld` to resolve the response. -For all other paths, the server resolves the response using the `notFound` object. - -After the `response` object, define the following `helloWorld` and `notFound` objects in the `spec.yml` file: - -```yml -helloWorld: - inline: - status: - resolver: inline - inline: 200 - headers: - resolver: inline - inline: - content-type: - resolver: inline - inline: 'text/string' - body: - resolver: inline - inline: 'Hello World!' - -notFound: - inline: - status: - resolver: inline - inline: 404 - headers: - resolver: inline - inline: - content-type: - resolver: inline - inline: 'text/string' - body: - resolver: inline - inline: 'Page not found!' -``` - -Now, when you start the server and navigate to the application, only the root and `/hello-world` path return the "Hello World!" message. -All other paths return the `404` response. - -Valid URLS: - -* `http://0.0.0.0:8080/` -* `http://0.0.0.0:8080/hello-world` - -Examples of invalid URLS: - -* `http://0.0.0.0:8080/goodbye-world` -* `http://0.0.0.0:8080/something-else` - -**Next:** [Rendering web pages using the TemplateResolver][] - -[upward specification]: https://github.com/magento/pwa-studio/tree/master/packages/upward-spec -[node]: https://nodejs.org -[yarn]: https://yarnpkg.com/en/ -[npm]: https://www.npmjs.com/get-npm -[express]: https://expressjs.com/ - -[`upward-js`]: {% link technologies/upward/reference-implementation/index.md %} -[Rendering web pages using the TemplateResolver]: {% link tutorials/hello-upward/using-template-resolver/index.md %} -[InlineResolver]: https://github.com/magento/pwa-studio/tree/develop/packages/upward-spec#inlineresolver -[ConditionalResolver]: https://github.com/magento/pwa-studio/tree/develop/packages/upward-spec#conditionalresolver diff --git a/pwa-devdocs/src/tutorials/hello-upward/using-template-resolver/index.md b/pwa-devdocs/src/tutorials/hello-upward/using-template-resolver/index.md deleted file mode 100644 index 72874149dc..0000000000 --- a/pwa-devdocs/src/tutorials/hello-upward/using-template-resolver/index.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: Using the TemplateResolver ---- - -In this tutorial, you will learn how to use the [TemplateResolver][] in your UPWARD specification file to serve an HTML page rendered server-side. - -This tutorial builds on the project described in the previous [Creating a simple server][] tutorial. - -## Create web page templates - -In your project directory, create a `templates` directory. This directory will house [Mustache][] template files for the different pieces of the HTML page. - -**`open-document.mst`** - -```mustache - - - - - -``` - -This template partial creates the beginning of the HTML response. -The `head` tag is left open to allow custom metadata, such as title, scripts, and styles. - -**`open-body.mst`** - -```mustache - - -``` - -This template partial closes the `head` tag and begins the `body` tag of the HTML response. - -**`close-document.mst`** - -```mustache - - -``` - -This template partial closes the `body` and `html` tag for the HTML response. - -**`hello-world.mst`** - -{% raw %} - -```mustache -{{> templates/open-document}} - - {{ title }} - - {{> templates/open-body}} - - Hello Template World! - - {{> templates/close-document}} -``` - -{% endraw %} - -This template uses the previously defined template partials to create a complete HTML response. -The body contains the "Hello Template World!" message in bold and sets the page title to a `title` variable, which is available through the template context. - -## Add TemplateResolver - -Modify the `helloWorld` object in the `spec.yml` file and replace the simple text response to an actual HTML page. - -```diff -helloWorld: - inline: - status: - resolver: inline - inline: 200 - headers: - resolver: inline - inline: - content-type: - resolver: inline -- inline: 'text/string' -+ inline: 'text/html' - body: -- resolver: inline -- inline: 'Hello World!' -+ resolver: template -+ engine: mustache -+ template: './templates/hello-world.mst' -+ provide: -+ title: -+ resolver: inline -+ inline: 'This is the page title!' -``` - -This new code replaces the InlineResolver with a TemplateResolver in the response body. -This TemplateResolver configuration sets the rendering engine to `mustache`, since the templates created previously are in Mustache format. -It also provides the `title` variable to the context during template render. - -Now, when you start the server and navigate to the root or `/hello-world` path, you get an actual HTML webpage instead of text. -View the page source for the page to see the HTML rendered from the templates. - -**Next:** [Adding React to the server][] - -[Creating a simple server]: {%link tutorials/hello-upward/simple-server/index.md %} -[Adding React to the server]: {%link tutorials/hello-upward/adding-react/index.md %} - -[Mustache]: https://mustache.github.io/mustache.5.html -[TemplateResolver]: https://github.com/magento/pwa-studio/tree/develop/packages/upward-spec#templateresolver diff --git a/pwa-devdocs/src/tutorials/index.md b/pwa-devdocs/src/tutorials/index.md deleted file mode 100644 index bde89e5c52..0000000000 --- a/pwa-devdocs/src/tutorials/index.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Tutorials ---- - -This section contains links to tutorials that will help you become familiar with the different tools provided by PWA Studio. - -## Recommended tutorials - -### UPWARD - -This three part tutorial provides an introduction to the concepts introduced in the UPWARD spec. -By the end of this tutorial, you should have a simple React application running on top of an UPWARD server. - -1. [Creating a simple UPWARD server][] - Teaches the very basics of reading and writing an UPWARD specification file for your projects -2. [Using the TemplateResolver][] - Introduces the concept of using templates and the TemplateResolver to keep your UPWARD specification file lean -3. [Adding React][] - Add React and Webpack into your UPWARD project - -### Magento Cloud deployment - -[Magento Cloud deployment][] - Provides steps for deploying a PWA Studio storefront into the Magento Cloud. -This tutorial uses the Venia example storefront to illustrate the general process. - -[creating a simple upward server]: <{%link tutorials/hello-upward/simple-server/index.md%}> -[using the templateresolver]: <{%link tutorials/hello-upward/using-template-resolver/index.md%}> -[adding react]: <{%link tutorials/hello-upward/adding-react/index.md%}> -[magento cloud deployment]: <{%link tutorials/cloud-deploy/index.md %}> diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/add-a-static-route/images/hellow-world-jsx.png b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/add-a-static-route/images/hellow-world-jsx.png deleted file mode 100644 index dd41c14e82..0000000000 Binary files a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/add-a-static-route/images/hellow-world-jsx.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/add-a-static-route/index.md b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/add-a-static-route/index.md deleted file mode 100644 index bd277ce20d..0000000000 --- a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/add-a-static-route/index.md +++ /dev/null @@ -1,278 +0,0 @@ ---- -title: Add a static route ---- - -Magento's built in CMS system and [PageBuilder][] feature lets you create highly customized content pages for your storefront, but -sometimes you need a page that fulfills a specific function, such as a checkout or login page. - -This tutorial provides steps for creating a custom, static route for these types of functional pages. - -By the end of this tutorial, you will know how to: - -- Define a custom React component to render route content -- Override Venia components -- Add a new static route that renders the custom React component - -For more information on routing, see [Routing][]. - -{: .bs-callout .bs-callout-info} -This tutorial requires you to have a project set up using the steps provided in the [Project Setup][] tutorial. - -## Create a components directory - -If your project does not already have one, create a `components` directory under your `src` directory. -This directory will hold your project's custom components. - -```sh -mkdir -p src/components -``` - -## Define a custom React component - -Every route needs a component to render the content. -For this tutorial, you will define a component that renders a simple message on the page. -This component will be assigned a route in a later step. - -### Create component directory - -Create the directory to hold the code for a custom Foo component. - -```sh -mkdir -p src/components/Foo -``` - -### Create `foo.js` module - -Inside the Foo component directory, create a `foo.js` file with the following content: - -```jsx -/* src/components/Foo/foo.js */ - -import React, { useEffect } from 'react'; - -const Foo = () => { - - return ( -Hello World JSX
- ); -} - -export default Foo; -``` - -### Create `index.js` file - -Inside the Foo component directory, create an `index.js` file that exports the Foo component. -This pattern of exposing the module through the `index.js` file is the same pattern used in the Venia UI package. - -```js -/* src/components/Foo/index.js */ - -export {default} from './foo'; -``` - -## Overriding Venia components overview - -As described in the [Project Structure][] topic, a new project set up using the scaffolding command imports the entire Venia app as a single component. -To replace the [Routes][] component, which is imported and used in Venia's [App][] component, you need to: - -1. Define a new Routes component -2. Make a copy of the App component that imports your new Routes component -3. Import your project's App component in your `src/index.js` file - -Copies of the Routes and App components are found in your project's `node_modules` directory. - -## Override Routes component - -The Routes component is responsible for deciding which components to use for rendering non-Magento routes. -To override this component, you need to copy the source code into your project and make the necessary modifications. - -### Create Routes directory - -Create a Routes directory under components. This will hold your project's version of the Routes component. - -```sh -mkdir -p src/components/Routes -``` - -### Copy over Routes component code - -Get a copy of the `routes.js` file from the `node_modules` directory: - -```sh -cp node_modules/@magento/venia-ui/lib/components/Routes/routes.js src/components/Routes -``` - -### Update Routes's module imports - -Open the `routes.js` file and update the relative import statements to use components from the Venia UI package. - -```diff -- import { fullPageLoadingIndicator } from '../LoadingIndicator'; -- import MagentoRoute from '../MagentoRoute'; -+ import { fullPageLoadingIndicator } from '@magento/venia-ui/lib/components/LoadingIndicator'; -+ import MagentoRoute from '@magento/venia-ui/lib/components/MagentoRoute'; - -- const CartPage = lazy(() => import('../CartPage')); -- const CheckoutPage = lazy(() => import('../CheckoutPage')); -- const CreateAccountPage = lazy(() => import('../CreateAccountPage')); -- const Search = lazy(() => import('../../RootComponents/Search')); -+ const CartPage = lazy(() => import('@magento/venia-ui/lib/components/CartPage')); -+ const CheckoutPage = lazy(() => import('@magento/venia-ui/lib/components/CheckoutPage')); -+ const CreateAccountPage = lazy(() => import('@magento/venia-ui/lib/components/CreateAccountPage')); -+ const Search = lazy(() => import('@magento/venia-ui/lib/RootComponents/Search')); -``` - -### Import your custom component - -Import your custom Foo component in the `routes.js` file. -Use lazy loading to load your component only when it is needed. - -Since the module is exposed through it's `index.js` file, you only need to refer to the component directory in the import declaration. - -```diff - const Search = lazy(() => import('@magento/venia-ui/lib/RootComponents/Search')); -+ const Foo = lazy(() => import('../Foo')); -``` - -### Add custom route - -Add a new route entry inside the Switch component and assign the Foo component for rendering that route: - -```diff -- -``` - -### Create Routes component's `index.js` file - -Create an `index.js` file for your custom Routes component to expose your `routes.js` module using the directory name. - -```js -/* src/components/Routes/index.js */ - -export {default} from './routes'; -``` - -## Override the App component - -The App component is the project's main application entry point. -The steps for overriding this component is the same as the ones for overriding the Routes component. - -### Create App directory - -Create an **App** directory to hold your project's copy of Venia's App component code. - -```sh -mkdir -p src/components/App -``` - -### Copy over App component's modules - -The `app.js` file in Venia's App component imports and uses the Routes component, so copy this file into your project. - -```sh -cp node_modules/@magento/venia-ui/lib/components/App/app.js src/components/App -``` - -If you look at the [`index.js` file for Venia's App component][], its default export is not `app.js`. -The default export for this component is `container.js`, which is a container for the `app.js` module, so copy the `container.js` file into your project. - -```sh -cp node_modules/@magento/venia-ui/lib/components/App/container.js src/components/App -``` - -### Update App modules' imports - -Open the `app.js` file and update the relative import statements to use components from the Venia UI package. -Skip updating the Routes import to use this project's version of the Routes component. - -```diff -- import { HeadProvider, Title } from '../Head'; -- import Main from '../Main'; -- import Mask from '../Mask'; -- import Navigation from '../Navigation'; -+ import { HeadProvider, Title } from '@magento/venia-ui/lib/components/Head'; -+ import Main from '@magento/venia-ui/lib/components/Main'; -+ import Mask from '@magento/venia-ui/lib/components/Mask'; -+ import Navigation from '@magento/venia-ui/lib/components/Navigation'; - import Routes from '../Routes'; -- import { registerMessageHandler } from '../../util/swUtils'; -- import { HTML_UPDATE_AVAILABLE } from '../../constants/swMessageTypes'; -- import ToastContainer from '../ToastContainer'; -- import Icon from '../Icon'; -+ import { registerMessageHandler } from '@magento/venia-ui/lib/util/swUtils'; -+ import { HTML_UPDATE_AVAILABLE } from '@magento/venia-ui/lib/constants/swMessageTypes'; -+ import ToastContainer from '@magento/venia-ui/lib/components/ToastContainer'; -+ import Icon from '@magento/venia-ui/lib/components/Icon'; -``` - -Open the `container.js` file and update the relative import statements to use components from the Venia UI package. -Skip updating the App module from `app.js` to use this project's version of the that module. - -```diff - import App from './app'; -- import { useErrorBoundary } from './useErrorBoundary' -+ import { useErrorBoundary } from '@magento/venia-ui/lib/components/App/useErrorBoundary' -``` - -### Create App component's `index.js` file - -Create an `index.js` file for your custom App component and set your version of `container.js` as the default export. - -```js -/* src/components/App/index.js */ - -export {default} from './container'; -``` - -## Import new App component - -Open your project's `src/index.js` file and update the import for the App component to use your custom App component. - -```diff -- import App, { AppContextProvider } from '@magento/venia-ui/lib/components/App'; -+ import { AppContextProvider } from '@magento/venia-ui/lib/components/App'; -+ import App from './components/App`; -``` - -## View route content - -Start your dev server using `yarn start` or `yarn develop` and navigate to the `/foo` route. - -You should see the following content on the page: - -![hello world jsx][] - -## Congratulations - -You just created a static route in your storefront project! - -[routing]: <{%link peregrine/routing/index.md %}> -[project setup]: <{%link tutorials/pwa-studio-fundamentals/project-setup/index.md %}> -[hello world jsx]: <{%link tutorials/pwa-studio-fundamentals/add-a-static-route/images/hellow-world-jsx.png %}> -[pagebuilder]: <{%link pagebuilder/index.md %}> -[project structure]: <{%link tutorials/pwa-studio-fundamentals/index.md %}> -[routes]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/Routes/routes.js -[app]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/App/app.js -[`index.js` file for venia's app component]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/App/index.js diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/css-modules/index.md b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/css-modules/index.md deleted file mode 100644 index e25f4e0223..0000000000 --- a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/css-modules/index.md +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: CSS Modules ---- - -If you used the scaffolding tool to set up your PWA Studio storefront project, then [CSS Modules][] are supported out of the box without additional configuration. - -This tutorial provides some guidance on using CSS modules in your components. -If you require more in depth information on CSS modules, see the [CSS Modules][] topic or [specification repository][]. - -## Defining and using CSS modules - -CSS modules are CSS files which are imported and treated as JavaScript modules. - -The recommended naming convention for classes is camelCase naming because it looks cleaner when paired with dot notation(e.g. `style.className`). -Kebab-case naming can produce unexpected behavior when accessing the class name using dot notation. -Use bracket notation(e.g. `style['class-name']`) if you intend to use kebab-case. - -Example: `foo.css` - -```css -.root { - padding: 3rem 1rem 1rem; - text-align: center; -} - -.title { - text-transform: uppercase; -} - -.title, -.greeting { - padding-bottom: .5rem; -} - -.spacer { - max-width: 500px; - border-color: #ddd; - border-top: 0; - margin: 36px auto; -} - -.label { - color: #666; - padding-bottom: 8px; - font-style: italic; - font-size: 14px; -} -``` - -Import CSS files as you would a JavaScript module and use dot or bracket notation to access the file name. - -Example: `foo.js` - -```jsx -import React from 'react'; - -import classes from './foo.css'; - -const Foo = props => { - return ( --+ --+ --+ - -- - -- - -- - -- - -- -- ); -} - -export default Foo; -``` - -## CSS modules in Venia UI components - -Venia UI components let you pass in a `classes` prop with a specific [prop type shape][] to override the class names used to render its elements. - -Example: `myButtonWrapper.css` - -```css -.content { - /* content class style override */ -} - -.root { - /* root class style override */ -} - -.root_highPriority { - /* root_highPriority class style override */ -} - -.root_lowPriority { - /* root_lowPriority class style override */ -} - -.root_normalPriority { - /* root_normalPriority class style override */ -} -``` - -With the CSS modules feature, you can import a CSS file as an object and pass it in as a prop to Venia UI components. -This lets you override the style for the specific classes the component expects. -To find out what classes you can override on a component, see the reference documentation or prop type in the source code. - -For example, Venia's [Button][] component lets you override the classes specified in the `myButtonWrapper.css` exampe file. - -Example: `myButtonWrapper.js` - -```jsx -import React from 'react'; - -import Button from '@magento/venia-ui/lib/components/Button'; - -import buttonOverrides from './myButtonWrapper.css'; - -const MyButtonWrapper = props => { - return ; -} - -export default MyButtonWrapper; -``` - -This example defines a component that wraps around Venia's Button component and provides its own set of custom classes to override the default Button classes. - -### Adding the class name override feature - -The Venia UI library uses the `mergeClasses()` utility function in its `classify` module to add classname override functionality to its components. -Use this function to add this same feature to your own custom components. - -Example: `foo.js` - -```diff - import React from 'react'; -+ import { mergeClasses } from '@magento/venia-ui/lib/classify'; - -- import classes from './foo.css'; -+ import defaultClasses from './foo.css'; - - const Foo = props => { -+ const { classes: propClasses } = props; -+ -+ const classes = mergeClasses(defaultClasses, propClasses); -+ - return ( -Foo Component
-
-A child component with propTypes & CSS Modules:
-- -- ); - } - - export default Foo; -``` - -[css modules]: <{%link technologies/basic-concepts/css-modules/index.md %}> -[specification repository]: https://github.com/css-modules/css-modules -[prop type shape]: https://reactjs.org/docs/typechecking-with-proptypes.html -[button]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/Button/button.js diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/images/foo-screen-shot.png b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/images/foo-screen-shot.png deleted file mode 100644 index 4e30dfe7ca..0000000000 Binary files a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/images/foo-screen-shot.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/index.md b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/index.md deleted file mode 100644 index 58feb5c73a..0000000000 --- a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/index.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: PWA Studio fundamentals ---- - -## Overview - -This tutorial series guides you through setting up, working with, and deploying a [Magento PWA Studio][] storefront. - -These tutorials teach you how to use PWA Studio by providing recommended practices for storefront development. -During the course of the tutorials, you will create a new storefront application and work with the tools provided by PWA Studio to make basic changes to the initial site. - -![what we are building][] - -## Prerequisites - -- A basic understanding of [React][] -- Node >= 10.14.1 -- Yarn (recommended) or NPM - -### Node 12 deprecation warning - -If you are using Node 12, you may see the following deprecation warning in the log when you run `yarn watch:venia`. - -```sh -(node:89176) [DEP0066] DeprecationWarning: OutgoingMessage.prototype._headers is deprecated -``` - -This is caused by a project dependency used by PWA Studio and not by PWA Studio itself. - -## Tutorials available - -- [Project setup][] - Setup a local development environment using the scaffolding tool -- [Project Structure][] - Learn about the project structure of your new project -- [Add a static route][] - Add a static route to your PWA Studio app -- [Modify the site footer][] - Learn how to modify existing components by modifying the site footer -- [Using component props][] - Learn how to use props in your custom components -- [CSS modules][] - Learn how to use CSS modules in you custom components -- [Manage state][] - Learn how to manage internal and global state in your components -- [Work with GraphQL][] - Learn how to work with GraphQL from Magento -- [Production launch checklist][] - Make sure your storefront is production ready with this checklist - -## Related content - -- [Progressive Web Apps](https://developers.google.com/web/progressive-web-apps) -- [Introduction to React](https://reactjs.org/tutorial/tutorial.html) -- [Main React concepts](https://reactjs.org/docs/hello-world.html) - -[magento pwa studio]: {%link technologies/overview/index.md %} -[what we are building]: {%link tutorials/pwa-studio-fundamentals/images/foo-screen-shot.png %} -[project setup]: {%link tutorials/pwa-studio-fundamentals/project-setup/index.md %} -[project structure]: {%link tutorials/pwa-studio-fundamentals/project-structure/index.md %} -[add a static route]: {%link tutorials/pwa-studio-fundamentals/add-a-static-route/index.md %} -[modify the site footer]: {%link tutorials/pwa-studio-fundamentals/modify-site-footer/index.md %} -[using component props]: {%link tutorials/pwa-studio-fundamentals/using-component-props/index.md %} -[css modules]: {%link tutorials/pwa-studio-fundamentals/css-modules/index.md %} -[manage state]: {%link tutorials/pwa-studio-fundamentals/manage-state/index.md %} -[work with graphql]: {%link tutorials/pwa-studio-fundamentals/work-with-graphql/index.md %} -[production launch checklist]: {%link tutorials/pwa-studio-fundamentals/production-launch-checklist/index.md %} - -[react]: https://reactjs.org/ diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/manage-state/index.md b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/manage-state/index.md deleted file mode 100644 index 0358521f53..0000000000 --- a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/manage-state/index.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Manage component and application state ---- - -Your components can respond to dynamic events in your application by keeping track of internal or global state. -This tutorial provides the steps for creating a button that manages its own internal state and updating it to use data from the global application state. - -By the end of this tutorial, you will know how to add internal state to a component and use Peregrine's context hooks to access global state data. - -For more information on state management, read the [State management][] topic. - -{: .bs-callout .bs-callout-info} -This tutorial requires you to have a project set up using the steps provided in the [Project Setup][] tutorial. - -## Create a new component - -For this part of the tutorial, you will create a React functional component called _MyComponent_. -This component will render a button that toggles and displays an internal boolean state. - -### Create the component directory - -Create a new `MyComponent` directory under your project's `src/components` directory. - -```sh -mkdir -p src/components/MyComponent -``` - -### Create the component - -Under `src/components/MyComponent`, create a `myComponent.js` file with the following content: - -```jsx -import React, { useState, useCallback } from 'react'; - -import Button from "@magento/venia-ui/lib/components/Button"; - -const MyComponent = () => { - const [booleanStatus, setBooleanStatus] = useState(false); - - const toggleStatus = useCallback(() => { - setBooleanStatus(previousStatus => !previousStatus); - }); - - const text = booleanStatus ? 'On' : 'Off'; - - return ; -}; - -export default MyComponent; -``` - -This component uses the [`useState()` React hook][] to keep track of an internal boolean state value. -It defines a `toggleStatus()` function to toggle this boolean state, which is called when the user clicks the rendered Button component. -When the status value changes, the text on the button also changes. - -### Export component from the index file - -Create a `src/components/MyComponent/index.js` file with the following content to set the default component export for the `MyComponent` directory. - -```js -export {default} from './myComponent' -``` - -## Add component to the storefront - -Add this button to your application's Header component using steps similar to the steps described in the [Modify the site footer][] tutorial. - -## Access global state data - -Use Peregrine state context hooks to access and modify the global application state. -Peregrine provides access to the global application state in slices through its various [context hooks][]. - -For this tutorial, use the `useAppContext()` hook imported from `@magento/peregrine/lib/context/app`. - -When you call this hook, it returns an object containing application-specifc data and an API object containing functions for updating the data specific to this global state slice. - -```diff -- import React, { useState, useCallback } from 'react'; -+ import React, { useCallback } from 'react'; -+ import {useAppContext} from '@magento/peregrine/lib/context/app' - - import Button from "@magento/venia-ui/lib/components/Button"; - - const MyComponent = () => { -- const [booleanStatus, setBooleanStatus] = useState(false); -+ const [appState, appApi] = useAppContext(); -+ -+ const booleanStatus = appState.overlay; -+ -+ const { toggleDrawer } = appApi; - - const toggleStatus = useCallback(() => { -- setBooleanStatus(previousStatus => !previousStatus); -+ toggleDrawer('myComponent'); - }); - - const text = booleanStatus ? 'On' : 'Off'; - - return ; - }; - - export default MyComponent; -``` - -These change swaps the `booleanStatus` value from an internal value to the `overlay` value in the application state slice. -It also updates the `toggleStatus()` function to call `toggleDrawer()` from the application state API. -This function updates the `overlay` value, which is used when rendering the Mask component. - -When you go to your storefront, you will see the button rendered by your component in the header. -Click this button to activate the mask overlay and update the button text. - -Since the button text now depends on a global state value, other components can toggle the text value through global state updates. -Click on the shopping cart icon to activate the mask overlay and see the button text update from "Off" to "On". - -[project setup]: <{%link tutorials/pwa-studio-fundamentals/project-setup/index.md %}> -[state management]: <{%link technologies/basic-concepts/state-management/index.md %}> -[modify the site footer]: <{%link tutorials/pwa-studio-fundamentals/modify-site-footer/index.md %}> - -[`usestate()` react hook]: https://reactjs.org/docs/hooks-reference.html#usestate -[context hooks]: https://github.com/magento/pwa-studio/tree/develop/packages/peregrine/lib/context diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/foo-footer-link.png b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/foo-footer-link.png deleted file mode 100644 index 9c0579404f..0000000000 Binary files a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/foo-footer-link.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/footer-component-selected.png b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/footer-component-selected.png deleted file mode 100644 index efcb88262e..0000000000 Binary files a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/footer-component-selected.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/react-dev-tools.png b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/react-dev-tools.png deleted file mode 100644 index 49e3963c32..0000000000 Binary files a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/react-dev-tools.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/web-dev-tools.png b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/web-dev-tools.png deleted file mode 100644 index 726e72471e..0000000000 Binary files a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/web-dev-tools.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/index.md b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/index.md deleted file mode 100644 index 352e78a803..0000000000 --- a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/index.md +++ /dev/null @@ -1,277 +0,0 @@ ---- -title: Modify the Footer component ---- - -One way to customize a storefront is to modify its UI components. -This tutorial provides the steps for modifying Venia's **Footer** component by adding a link to the existing content. - -By the end of this tutorial, you will know how to override different pieces of Venia to add your customizations. - -{: .bs-callout .bs-callout-info} -This tutorial requires you to have a project set up using the steps provided in the [Project Setup][] tutorial. - -## Steps overview - -When modifying any storefront component from the default Venia storefront, follow these basic steps: - -1. Identify the component you want to update and its render chain -1. Make a copy of the target component and the components in its render chain in your project -1. Update dependencies in your project to use the new copies - -## Identify the target component - -The first step in modifying anything in the Venia storefront is to identify the component whose content you want to modify. - -### Using React DevTools - -[React DevTools][] is a browser plugin for React developers. -It gives you the ability to navigate and inspect component nodes in the React DOM tree. - -After you install React DevTools in your browser, open your storefront and your browser's web developer tools. - -{: .bs-callout .bs-callout-info} -For this tutorial, Chrome's web developer tools are used, but these steps can be generally applied to other browsers. - -![Chrome dev tools][] - -In Chrome, the React DevTools is accessed through a dropdown on the top right of the developer tools panel. -Read the React DevTools plugin documentation find out how to access this tool in your browser. - -![React DevTools in Chrome][] - -Use the React DevTools to select content in the footer element to see which component renders it. -For this tutorial, select the **Footer** component. - -![Footer component selected][] - -## Identify the render chain - -The render chain is the path in the React DOM tree that starts in the **App** or a **Root Component** and ends at the target component. -These are the components you need to copy into your project to make modifications. - -Use the React DevTools to navigate the React DOM tree and find the render chain of the target component. -Ignore React context providers and consumers because they are often just used as a content wrapper. - -For this tutorial, the render chain for the Footer component in the Venia storefront is `App -> Main -> Footer`. -You can verify this by looking at the source for the [Main][] and [App][] components. -Main imports and renders the Footer component, and App imports and renders the Main component. - -### Root components - -Static imported components, such as Header, Footer, and side Navigation, have render chains that begin in **App**, but content that is specific to a route have render chains that begin at a **Root Component**. - -Root components are dynamically loaded components associated with a Magento page type or route. -A list of Venia's root components can be found in the [RootComponent][] directory in the PWA Studio project. - -## Create component directories - -If your project does not already have one, create a `components` directory under your `src` directory. -This directory will hold your project's components. - -```sh -mkdir -p src/components -``` - -Next, create directories for each component in the render chain. -These directories will hold copies of the component source code from Venia. - -```sh -mkdir -p src/components/App && \ -mkdir -p src/components/Main && \ -mkdir -p src/components/Footer -``` - -## Copy components - -Make a copy of the components in the render chain from the `node_modules` directory. - -### Copy App component - -The App component is the main entry point for the storefront application. -It imports and renders the Main component, which renders the Footer component. - -```sh -cp node_modules/@magento/venia-ui/lib/components/App/app.js src/components/App -``` - -If you look at the [`index.js` file for Venia's App component][], its default export is not `app.js`. -The default export for this component is `container.js`, which is a container for the `app.js` module, so copy the `container.js` file into your project. - -```sh -cp node_modules/@magento/venia-ui/lib/components/App/container.js src/components/App -``` - -### Copy Main component - -The Main component imports and renders the Header, Footer, and route-specific components. -Copy this component from `node_modules` into your project. - -```sh -cp node_modules/@magento/venia-ui/lib/components/Main/main.js src/components/Main -``` - -### Copy Footer component - -The Footer component is the target component you will modify for this tutorial. -Copy this component from the `node_modules` directory into your project. - -```sh -cp node_modules/@magento/venia-ui/lib/components/Footer/footer.js src/components/Footer -``` - -## Add a link to the Footer - -Open `src/components/Footer/footer.js` and make the following modifications to add a link to the footer element. - -Import **Link** from Venia's driver component. - -```diff - import { useFooter } from '@magento/peregrine/lib/talons/Footer/useFooter'; -+ -+ import { Link } from '@magento/venia-ui/lib/drivers'; - - import { mergeClasses } from '../../classify'; -``` - -Use the Link component to create a link to an internal route defined in the [Add a static route tutorial][]: - -```diff -Foo Component
-
-A child component with propTypes & CSS Modules:
--