├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── SUPPORT.md ├── .gitignore ├── Gemfile ├── LICENSE.txt ├── README.md ├── _config-production.yml ├── gulpfile.js ├── package.json ├── scripts └── deploy.sh └── src ├── .editorconfig ├── 404.md ├── _config.yml ├── _data ├── peregrine.yml ├── pwa-buildpack.yml ├── technologies.yml ├── top-nav.yml ├── vars.yml └── venia-pwa-concept.yml ├── _drafts └── .gitkeep ├── _includes ├── content-not-available.md ├── layout │ ├── after-site-header.html │ ├── footer.html │ ├── header-scripts.html │ ├── header-styles.html │ ├── navigation.html │ ├── pre-release-banner.html │ ├── sidebar-nav-root-item.html │ └── toc.html └── peregrine │ └── reference │ └── list-selection-models.md ├── _js ├── collapsible.js └── index.js ├── _layouts └── default.html ├── _plugins └── sitemap_generator.rb ├── _posts └── .gitkeep ├── _scss ├── _variables.scss ├── main.scss ├── src │ ├── .gitkeep │ ├── _home.scss │ ├── _material-icons.scss │ ├── _message-banner.scss │ └── menu-section.scss └── var │ └── _syntax.scss ├── guides └── testing │ └── index.md ├── index.html ├── peregrine ├── index.md └── reference │ ├── container-child │ └── index.md │ ├── item │ └── index.md │ ├── items │ └── index.md │ ├── list │ └── index.md │ └── router │ └── index.md ├── pwa-buildpack ├── index.md ├── project-setup │ ├── create-configuration-files │ │ ├── index.md │ │ └── webpack-config-example │ │ │ └── index.md │ ├── create-simple-peregrine-app │ │ └── index.md │ ├── create-theme-files │ │ └── index.md │ ├── index.md │ ├── install-dependencies │ │ └── index.md │ └── link-project │ │ └── index.md ├── reference │ ├── layout-loader │ │ └── index.md │ ├── magento-resolver │ │ └── index.md │ ├── object-types │ │ └── index.md │ ├── pwa-dev-server │ │ └── index.md │ ├── root-components-plugin │ │ └── index.md │ └── serviceworker-plugin │ │ └── index.md └── troubleshooting │ └── index.md ├── reference └── ui-components │ └── index.md ├── search.md ├── static ├── fonts │ └── .gitkeep └── images │ ├── .gitkeep │ ├── contribute.png │ ├── getting-started.png │ ├── repos.png │ └── what-is-pwa.png ├── technologies ├── basic-concepts │ ├── app-shell │ │ └── index.md │ ├── client-state-reducers-actions │ │ └── index.md │ ├── component-data-binding │ │ └── index.md │ ├── container-extensibility │ │ └── index.md │ ├── critical-path │ │ └── index.md │ ├── css-modules │ │ └── index.md │ ├── graphql │ │ └── index.md │ ├── index.md │ ├── loading-offline-states │ │ └── index.md │ ├── performance-patterns │ │ └── index.md │ ├── root-components-routing │ │ └── index.md │ └── service-worker │ │ └── index.md ├── overview │ └── index.md └── tools-libraries │ └── index.md ├── tutorials └── index.md └── venia-pwa-concept ├── index.md └── setup └── index.md /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | education, socio-economic status, nationality, personal appearance, race, 10 | religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at pwa@magento.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for your interest in contributing to the pwa-devdocs project! Before you start contributing, please take a moment to read through the following guidelines: 4 | 5 | * [Code of Conduct] 6 | * [Support] 7 | 8 | To contribute to this repository, start by forking the [official repository] and following the Installation instructions in the README file. 9 | 10 | ## Submit changes 11 | 12 | All Pull Requests should be done against the `develop` branch. This allows us to review and merge your changes prior to publication. 13 | 14 | **Do not submit PR's against the `master` branch.** This branch reflects the published content on the documentation site. 15 | 16 | To help with reviews, your PR should only create/revise a single topic or fix a single issue. 17 | 18 | To maintain a clean URL structure, every topic file must be created in its own directory and named `index.md`. See the current directory structure for examples. 19 | 20 | It is okay to have multiple commits in your PR. These will be squashed by GitHub prior to merging with `develop`. 21 | 22 | If your PR addresses an existing issue, please reference that issue in the title or description. 23 | 24 | ### Style guide 25 | 26 | As much as possible, please follow the [Google Developer Documentation Style Guide] when you are writing content. 27 | 28 | Use [Kramdown]-flavored markdown wherever possible. HTML should be used only in the most dire of circumstances. 29 | 30 | For commit messages, follow the conventions described in [How to Write a Git Commit Message]. 31 | 32 | ## Report a bug 33 | 34 | Create a GitHub issue and put an **X** in the **Bug** box to report a bug found on the documentation website or with the project itself. 35 | 36 | Examples of bugs include: 37 | * Editorial mistakes (e.g. spelling, grammar, punctuation) 38 | * Incorrect information 39 | * Broken link 40 | * Missing image 41 | * Weird formatting 42 | 43 | **DO NOT** create GitHub issues asking for help on bugs in your project or other support-type questions. 44 | 45 | ## Request a topic/clarification 46 | 47 | If you feel that there is a gap in our documentation, create a GitHub issue and put an **X** in the **New Topic Request** or **Topic Clarification Request** box. 48 | 49 | Please provide as much detail and context in the description to help us understand the request. We will do our best to provide the appropriate content. 50 | 51 | ## Request a feature 52 | 53 | Is there a feature you would like to see in our documentation site? Maybe you saw a neat way of presenting information or code to the reader. 54 | 55 | Let us know, by creating a GitHub issue and marking **New Feature Request**. Provide a detailed description of what you would like to see on the docs site and we will see what we can do! 56 | 57 | [Code of Conduct]: CODE_OF_CONDUCT.md 58 | [Support]: SUPPORT.md 59 | [Google Developer Documentation Style Guide]: https://developers.google.com/style/ 60 | [official repository]: https://github.com/magento-research/pwa-devdocs 61 | [How to Write a Git Commit Message]: https://chris.beams.io/posts/git-commit/ 62 | [Kramdown]: https://kramdown.gettalong.org/ -------------------------------------------------------------------------------- /.github/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | # Contributors 2 | 3 | This project would not be where it is without the contributions of the following group of people. Thank you! 4 | 5 | ## The Core PWA Team 6 | 7 | [Eric Erway](https://github.com/ericerway) - Product Manager 8 | 9 | [James Zetlen](https://github.com/zetlen) - Lead Architect, Developer 10 | 11 | [Andrew Levine](https://github.com/DrewML) - Tooling Developer 12 | 13 | [Jimmy Sanford](https://github.com/jimbo) - View Framework Developer 14 | 15 | [Soumya Ashok](https://github.com/soumya-ashok) - User Experience Researcher 16 | 17 | [James Calcaben](https://github.com/jcalcaben) - Technical Documentation Scribbler -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | ## This issue is a: 15 | [ ] Bug 16 | [ ] New Topic Request 17 | [ ] Topic Clarification Request 18 | [ ] New Feature Request 19 | [ ] Other 20 | 21 | 22 | ## Description: 23 | 24 | 25 | ### Steps to Reproduce 26 | 27 | 1. First Step 28 | 2. Second Step 29 | 3. Etc. 30 | 31 | 32 | ## Expected Result: 33 | 34 | 35 | ## Possible Solutions: 36 | 37 | 38 | ## Additional Information: -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | ## This PR is a: 15 | [ ] Bug fix 16 | [ ] New topic 17 | [ ] Content rewrite 18 | 19 | 20 | ## Summary 21 | 22 | When this Pull Request is merged, it will... 23 | 24 | 25 | ## Additional Information -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | Need help with something? Please use the following resources to get the help you need: 4 | 5 | * Documentation website - [PWA DevDocs] 6 | * Chat with us on **Slack** - [#pwa channel] 7 | 8 | [PWA DevDocs]: https://magento-research.github.io/pwa-devdocs/ 9 | [#pwa channel]: https://magentocommeng.slack.com/messages/C71HNKYS2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _site/ 2 | .sass-cache/ 3 | .jekyll-metadata 4 | 5 | node_modules 6 | src/builds 7 | 8 | Gemfile.lock 9 | 10 | *.tar 11 | 12 | *.log 13 | *.lock -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'devdocs', :git => 'https://github.com/magento-devdocs/devdocs-theme.git', :branch => 'devdocs-stable' 4 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | Open Software License ("OSL") v. 3.0 4 | 5 | This Open Software License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: 6 | 7 | Licensed under the Open Software License version 3.0 8 | 9 | 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: 10 | 11 | 1. to reproduce the Original Work in copies, either alone or as part of a collective work; 12 | 13 | 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; 14 | 15 | 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software License; 16 | 17 | 4. to perform the Original Work publicly; and 18 | 19 | 5. to display the Original Work publicly. 20 | 21 | 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. 22 | 23 | 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. 24 | 25 | 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. 26 | 27 | 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). 28 | 29 | 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. 30 | 31 | 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. 32 | 33 | 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. 34 | 35 | 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including 'fair use' or 'fair dealing'). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). 36 | 37 | 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. 38 | 39 | 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. 40 | 41 | 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. 42 | 43 | 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. 44 | 45 | 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 46 | 47 | 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. 48 | 49 | 16. Modification of This License. This License is Copyright (C) 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Open Software License" or "OSL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pwa-devdocs 2 | 3 | This is the former source code and documentation repository for the PWA Studio documentation site. 4 | 5 | The source for the documentation site is now part of the [PWA Studio repository]. 6 | 7 | This project repository is deprecated and will be deleted soon. 8 | 9 | [PWA Studio repository]: https://github.com/magento-research/pwa-studio -------------------------------------------------------------------------------- /_config-production.yml: -------------------------------------------------------------------------------- 1 | baseurl: /pwa-devdocs 2 | environment: public 3 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | // Requires 2 | var gulp = require('gulp'); 3 | var jekyll = require('jekyll-tasks')(gulp); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pwa-devdocs", 3 | "version": "1.0.0", 4 | "description": "A documentation site for Magento PWA", 5 | "main": "gulpfile.js", 6 | "dependencies": { 7 | "broken-link-checker-local": "^0.1.1", 8 | "gulp": "^3.9.1", 9 | "jekyll-tasks": "^1.2.1", 10 | "jquery": "^3.3.1" 11 | }, 12 | "devDependencies": {}, 13 | "scripts": { 14 | "start": "gulp dev", 15 | "build": "gulp build", 16 | "package": "jekyll build --source src/ --config src/_config.yml,_config-production.yml", 17 | "deploy": "./scripts/deploy.sh", 18 | "tests": "npm run test-links", 19 | "test-links": "rm -fr _site && npm run build && node_modules/broken-link-checker-local/out/bin.js _site -rog" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/magento-research/pwa-devdocs.git" 24 | }, 25 | "author": "James Calcaben", 26 | "license": "OSL-3.0", 27 | "bugs": { 28 | "url": "https://github.com/magento-research/pwa-devdocs/issues" 29 | }, 30 | "homepage": "https://github.com/magento-research/pwa-devdocs#readme" 31 | } 32 | -------------------------------------------------------------------------------- /scripts/deploy.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # This script requires you to set TARGET_REPO and TARGET_BRANCH environment variables 4 | 5 | rm -fr /tmp/gh-pages 6 | git init /tmp/gh-pages 7 | 8 | mv _site/* /tmp/gh-pages 9 | 10 | cd /tmp/gh-pages 11 | git checkout -b $TARGET_BRANCH 12 | 13 | git remote add origin $TARGET_REPO 14 | git add . 15 | git commit -m "HTML Generated" 16 | 17 | git push -f origin $TARGET_BRANCH -------------------------------------------------------------------------------- /src/.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [*.py] 14 | indent_style = space 15 | indent_size = 4 -------------------------------------------------------------------------------- /src/404.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: full-width 3 | title: Page Not Found 4 | menu_order: 1 5 | permalink: /404.html 6 | --- 7 | 8 | The page you are looking for could not be found or the documentation does not exist. 9 | 10 | To report a missing page, please submit an issue in our public [GitHub]({{ site.github_repo }}) repo. 11 | 12 | [Return to main page]({{site.baseurl}}/) 13 | -------------------------------------------------------------------------------- /src/_config.yml: -------------------------------------------------------------------------------- 1 | title: Magento PWA Documentation 2 | description: Everything you need to build a Magento PWA. 3 | 4 | source: src 5 | 6 | theme: devdocs 7 | logo: PWA Docs 8 | 9 | 10 | github_link: true 11 | feedback_link: true 12 | github_repo: "https://github.com/magento-research/pwa-devdocs/" 13 | github_files: "https://github.com/magento-research/pwa-devdocs/tree/master/src/" 14 | 15 | 16 | defaults: 17 | - 18 | scope: 19 | path: "" 20 | values: 21 | layout: "default" 22 | - 23 | scope: 24 | path: "technologies" 25 | values: 26 | toc-group: "technologies" 27 | - 28 | scope: 29 | path: "pwa-buildpack" 30 | values: 31 | toc-group: "pwa-buildpack" 32 | - 33 | scope: 34 | path: "peregrine" 35 | values: 36 | toc-group: "peregrine" 37 | - 38 | scope: 39 | path: "venia-pwa-concept" 40 | values: 41 | toc-group: "venia-pwa-concept" 42 | 43 | 44 | algolia: 45 | application_id: 'E642SEDTHL' 46 | index_name: 'pwa-devdocs' 47 | api_key: 'd2d0f33ab73e291ef8d88d8b565e754c' 48 | lazy_update: true 49 | excluded_files: 50 | - vagrant 51 | - common 52 | - js 53 | - i 54 | - schemas 55 | - static 56 | 57 | google: 58 | analytics: 'UA-66243208-1' 59 | -------------------------------------------------------------------------------- /src/_data/peregrine.yml: -------------------------------------------------------------------------------- 1 | title: Peregrine 2 | entries: 3 | - label: Overview 4 | url: /peregrine/ 5 | 6 | - label: Component Reference 7 | entries: 8 | 9 | - label: ContainerChild 10 | url: /peregrine/reference/container-child/ 11 | 12 | - label: Item 13 | url: /peregrine/reference/item/ 14 | 15 | - label: Items 16 | url: /peregrine/reference/items/ 17 | 18 | - label: List 19 | url: /peregrine/reference/list/ 20 | 21 | - label: Router 22 | url: /peregrine/reference/router/ -------------------------------------------------------------------------------- /src/_data/pwa-buildpack.yml: -------------------------------------------------------------------------------- 1 | title: PWA Buildpack 2 | entries: 3 | - label: Overview 4 | url: /pwa-buildpack/ 5 | 6 | - label: Project setup tutorial 7 | url: /pwa-buildpack/project-setup/ 8 | entries: 9 | - label: Create initial theme files 10 | url: /pwa-buildpack/project-setup/create-theme-files/ 11 | - label: Install project dependencies 12 | url: /pwa-buildpack/project-setup/install-dependencies/ 13 | - label: Link project to the Magento backend 14 | url: /pwa-buildpack/project-setup/link-project/ 15 | - label: Create configuration files 16 | url: /pwa-buildpack/project-setup/create-configuration-files/ 17 | entries: 18 | - label: Example - webpack.config.js 19 | url: /pwa-buildpack/project-setup/create-configuration-files/webpack-config-example/ 20 | - label: Create a simple peregrine app 21 | url: /pwa-buildpack/project-setup/create-simple-peregrine-app/ 22 | 23 | - label: Tools reference 24 | entries: 25 | 26 | - label: magento-layout-loader 27 | url: /pwa-buildpack/reference/layout-loader/ 28 | 29 | - label: MagentoResolver 30 | url: /pwa-buildpack/reference/magento-resolver/ 31 | 32 | - label: MagentoRootComponentsPlugin 33 | url: /pwa-buildpack/reference/root-components-plugin/ 34 | 35 | - label: Object Types 36 | url: /pwa-buildpack/reference/object-types/ 37 | 38 | - label: PWADevServer 39 | url: /pwa-buildpack/reference/pwa-dev-server/ 40 | 41 | - label: ServiceWorkerPlugin 42 | url: /pwa-buildpack/reference/serviceworker-plugin/ 43 | 44 | - label: Troubleshooting 45 | url: /pwa-buildpack/troubleshooting/ 46 | 47 | -------------------------------------------------------------------------------- /src/_data/technologies.yml: -------------------------------------------------------------------------------- 1 | title: Technologies 2 | entries: 3 | - label: Overview 4 | url: /technologies/overview/ 5 | 6 | - label: Tools and libraries 7 | url: /technologies/tools-libraries/ 8 | 9 | - label: Basic concepts 10 | url: /technologies/basic-concepts/ 11 | entries: 12 | 13 | - label: Container extensibility 14 | url: /technologies/basic-concepts/container-extensibility/ 15 | -------------------------------------------------------------------------------- /src/_data/top-nav.yml: -------------------------------------------------------------------------------- 1 | - label: Overview 2 | url: /technologies/overview/ 3 | 4 | - label: PWA Buildpack 5 | url: /pwa-buildpack/ 6 | 7 | - label: UI Components 8 | url: /peregrine/ 9 | 10 | - label: Venia Theme 11 | url: /venia-pwa-concept/ 12 | -------------------------------------------------------------------------------- /src/_data/vars.yml: -------------------------------------------------------------------------------- 1 | # Site specific variables 2 | 3 | title: Magento PWA Studio Documentation 4 | description: Everything you need to build a Magento PWA. 5 | repo: https://github.com/magento-research/pwa-devdocs 6 | -------------------------------------------------------------------------------- /src/_data/venia-pwa-concept.yml: -------------------------------------------------------------------------------- 1 | title: Venia Theme (Concept) 2 | entries: 3 | - label: Overview 4 | url: /venia-pwa-concept/ 5 | 6 | - label: Setup 7 | url: /venia-pwa-concept/setup/ -------------------------------------------------------------------------------- /src/_drafts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magento-research/pwa-devdocs/6191acca66f83df2eb541907df4193d69701bc07/src/_drafts/.gitkeep -------------------------------------------------------------------------------- /src/_includes/content-not-available.md: -------------------------------------------------------------------------------- 1 | ## Sorry! 2 | 3 | The content for this page does not exist yet! 4 | 5 | {% if include.issue %} 6 | To contribute to this page, see the following [GitHub Issue]({{ site.data.vars.repo }}/issues/{{include.issue}}) for details. 7 | {% else %} 8 | If you would like to contribute content for this page, please visit our [Contribution Guide]. 9 | {% endif %} 10 | 11 | [Return to main page]({{site.baseurl}}/) 12 | 13 | [Contribution Guide]: {{ site.data.vars.repo }}/blob/master/.github/CONTRIBUTING.md -------------------------------------------------------------------------------- /src/_includes/layout/after-site-header.html: -------------------------------------------------------------------------------- 1 | {% include layout/pre-release-banner.html %} 2 | -------------------------------------------------------------------------------- /src/_includes/layout/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {% include layout/page-footer.html %} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {% if site.environment == "public" %} 19 | 29 | {% endif %} 30 | 31 | 32 | {% include layout/footer-scripts.html %} 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/_includes/layout/header-scripts.html: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | {% if site.environment == "public" %} 13 | 14 | 15 | 25 | 26 | 27 | 28 | 29 | 36 | 37 | 38 | {% endif %} 39 | -------------------------------------------------------------------------------- /src/_includes/layout/header-styles.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/_includes/layout/navigation.html: -------------------------------------------------------------------------------- 1 | 2 | 31 | -------------------------------------------------------------------------------- /src/_includes/layout/pre-release-banner.html: -------------------------------------------------------------------------------- 1 |
2 | We have moved! Please visit the new site at: https://magento-research.github.io/pwa-studio/ 3 |
4 | -------------------------------------------------------------------------------- /src/_includes/layout/sidebar-nav-root-item.html: -------------------------------------------------------------------------------- 1 | {% if page.toc-group == "technologies" %} 2 | {% assign toc = site.data.technologies %} 3 | 4 | {% elsif page.toc-group == "pwa-buildpack" %} 5 | {% assign toc = site.data.pwa-buildpack %} 6 | 7 | {% elsif page.toc-group == "peregrine" %} 8 | {% assign toc = site.data.peregrine %} 9 | 10 | {% elsif page.toc-group == "venia-pwa-concept" %} 11 | {% assign toc = site.data.venia-pwa-concept %} 12 | 13 | {% endif %} 14 | 15 | {% include layout/toc.html %} -------------------------------------------------------------------------------- /src/_includes/layout/toc.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/_includes/peregrine/reference/list-selection-models.md: -------------------------------------------------------------------------------- 1 | The `selectionModel` currently accepts the following values: 2 | 3 | * **radio** (default) 4 | * **check** 5 | -------------------------------------------------------------------------------- /src/_js/collapsible.js: -------------------------------------------------------------------------------- 1 | /* 2 | * A collapsible widget used in the left TOC 3 | */ 4 | 5 | define("collapsible", 6 | ["jquery/dist/jquery"], 7 | function(jquery) { 8 | 9 | let hide = (control, target, speed) => { 10 | jquery(control).html("arrow_drop_down"); 11 | jquery(target).slideUp(speed); 12 | } 13 | 14 | let show = (control, target, speed) => { 15 | jquery(control).html("arrow_drop_up"); 16 | jquery(target).slideDown(speed); 17 | 18 | } 19 | 20 | let toggle = (control, target, speed) => { 21 | if(jquery(control).html() === "arrow_drop_down") { 22 | show(control,target, speed); 23 | } 24 | else { 25 | hide(control,target, speed); 26 | } 27 | } 28 | 29 | let Collapsible = { 30 | 31 | /** 32 | * Applies the collapsible functionality 33 | * @control {DOM} The DOM element that controls the hide/show. 34 | * This element needs to have a material.io icon tag (). 35 | * @target {DOM} The DOM element to hide/show 36 | * @speed {int} The speed of the show/hide functionality 37 | */ 38 | apply: function(control, target, speed=200) { 39 | jquery(control).click(function(){ 40 | toggle(jquery(control).children('i'), target,speed); 41 | }) 42 | }, 43 | 44 | /** 45 | * Toggles the collapsible functionality 46 | */ 47 | toggle: toggle 48 | 49 | } 50 | 51 | return Collapsible; 52 | 53 | } 54 | ); -------------------------------------------------------------------------------- /src/_js/index.js: -------------------------------------------------------------------------------- 1 | // Javascript goes here -------------------------------------------------------------------------------- /src/_layouts/default.html: -------------------------------------------------------------------------------- 1 | {% include layout/header.html %} 2 | 3 |
4 | 5 | {% include layout/sidebar.html %} 6 | 7 |
8 |
9 |

We have moved!

10 |

The project repository for this documentation site is now part of the PWA Studio project.

11 |

As a result, the documentation site is now at:
12 | https://magento-research.github.io/pwa-studio/ 13 |

14 |

Please updated your bookmarks. Thanks!

15 |
16 | 17 |
18 | 19 | 20 |
21 | 22 | {% include layout/footer.html %} -------------------------------------------------------------------------------- /src/_plugins/sitemap_generator.rb: -------------------------------------------------------------------------------- 1 | # Sitemap.xml Generator is a Jekyll plugin that generates a sitemap.xml file by 2 | # traversing all of the available posts and pages. 3 | # 4 | # See readme file for documenation 5 | # 6 | # Updated to use config file for settings by Daniel Groves 7 | # Site: http://danielgroves.net 8 | # 9 | # Author: Michael Levin 10 | # Site: http://www.kinnetica.com 11 | # Distributed Under A Creative Commons License 12 | # - http://creativecommons.org/licenses/by/3.0/ 13 | require 'jekyll/document' 14 | require 'rexml/document' 15 | 16 | module Jekyll 17 | 18 | class Jekyll::Document 19 | attr_accessor :name 20 | 21 | def path_to_source 22 | File.join(*[@name].compact) 23 | end 24 | 25 | def location_on_server(my_url) 26 | "#{my_url}#{url}" 27 | end 28 | end 29 | 30 | class Page 31 | attr_accessor :name 32 | 33 | def path_to_source 34 | File.join(*[@dir, @name].compact) 35 | end 36 | 37 | def location_on_server(my_url) 38 | location = "#{my_url}#{url}" 39 | location.gsub(/index.html$/, "") 40 | end 41 | end 42 | 43 | # Recover from strange exception when starting server without --auto 44 | class SitemapFile < StaticFile 45 | def write(dest) 46 | true 47 | end 48 | end 49 | 50 | class SitemapGenerator < Generator 51 | priority :lowest 52 | 53 | # Config defaults 54 | SITEMAP_FILE_NAME = "/sitemap.xml" 55 | EXCLUDE = ["/atom.xml", "/feed.xml", "/feed/index.xml"] 56 | INCLUDE_POSTS = ["/index.html"] 57 | CHANGE_FREQUENCY_NAME = "change_frequency" 58 | PRIORITY_NAME = "priority" 59 | 60 | # Valid values allowed by sitemap.xml spec for change frequencies 61 | VALID_CHANGE_FREQUENCY_VALUES = ["always", "hourly", "daily", "weekly", 62 | "monthly", "yearly", "never"] 63 | 64 | # Goes through pages and posts and generates sitemap.xml file 65 | # 66 | # Returns nothing 67 | def generate(site) 68 | # Configuration 69 | sitemap_config = site.config['sitemap'] || {} 70 | @config = {} 71 | @config['filename'] = sitemap_config['filename'] || SITEMAP_FILE_NAME 72 | @config['change_frequency_name'] = sitemap_config['change_frequency_name'] || CHANGE_FREQUENCY_NAME 73 | @config['priority_name'] = sitemap_config['priority_name'] || PRIORITY_NAME 74 | @config['exclude'] = sitemap_config['exclude'] || EXCLUDE 75 | @config['include_posts'] = sitemap_config['include_posts'] || INCLUDE_POSTS 76 | 77 | sitemap = REXML::Document.new << REXML::XMLDecl.new("1.0", "UTF-8") 78 | 79 | urlset = REXML::Element.new "urlset" 80 | urlset.add_attribute("xmlns", 81 | "http://www.sitemaps.org/schemas/sitemap/0.9") 82 | 83 | @last_modified_post_date = fill_posts(site, urlset) 84 | fill_pages(site, urlset) 85 | 86 | sitemap.add_element(urlset) 87 | 88 | # Create destination directory if it doesn't exist yet. Otherwise, we cannot write our file there. 89 | Dir::mkdir(site.dest) if !File.directory? site.dest 90 | 91 | # File I/O: create sitemap.xml file and write out pretty-printed XML 92 | filename = @config['filename'] 93 | file = File.new(File.join(site.dest, filename), "w") 94 | formatter = REXML::Formatters::Pretty.new(4) 95 | formatter.compact = true 96 | formatter.write(sitemap, file) 97 | file.close 98 | 99 | # Keep the sitemap.xml file from being cleaned by Jekyll 100 | site.static_files << Jekyll::SitemapFile.new(site, site.dest, "/", filename) 101 | end 102 | 103 | # Create url elements for all the posts and find the date of the latest one 104 | # 105 | # Returns last_modified_date of latest post 106 | def fill_posts(site, urlset) 107 | 108 | last_modified_date = nil 109 | site.collections["posts"].docs.each do |post| 110 | if !excluded?(site, post.name) 111 | url = fill_url(site, post) 112 | urlset.add_element(url) 113 | end 114 | 115 | date = File.mtime(post.path) 116 | last_modified_date = date if last_modified_date == nil or date > last_modified_date 117 | end 118 | 119 | last_modified_date 120 | end 121 | 122 | # Create url elements for all the normal pages and find the date of the 123 | # index to use with the pagination pages 124 | # 125 | # Returns last_modified_date of index page 126 | def fill_pages(site, urlset) 127 | site.pages.each do |page| 128 | if !excluded?(site, page.path_to_source) 129 | if File.exists?(page.path) 130 | url = fill_url(site, page) 131 | urlset.add_element(url) 132 | end 133 | end 134 | end 135 | end 136 | 137 | # Fill data of each URL element: location, last modified, 138 | # change frequency (optional), and priority. 139 | # 140 | # Returns url REXML::Element 141 | def fill_url(site, page_or_post) 142 | url = REXML::Element.new "url" 143 | 144 | loc = fill_location(site, page_or_post) 145 | url.add_element(loc) 146 | 147 | lastmod = fill_last_modified(site, page_or_post) 148 | url.add_element(lastmod) if lastmod 149 | 150 | 151 | 152 | if (page_or_post.data[@config['change_frequency_name']]) 153 | change_frequency = 154 | page_or_post.data[@config['change_frequency_name']].downcase 155 | 156 | if (valid_change_frequency?(change_frequency)) 157 | changefreq = REXML::Element.new "changefreq" 158 | changefreq.text = change_frequency 159 | url.add_element(changefreq) 160 | else 161 | puts "ERROR: Invalid Change Frequency In #{page_or_post.name}" 162 | end 163 | end 164 | 165 | if (page_or_post.data[@config['priority_name']]) 166 | priority_value = page_or_post.data[@config['priority_name']] 167 | if valid_priority?(priority_value) 168 | priority = REXML::Element.new "priority" 169 | priority.text = page_or_post.data[@config['priority_name']] 170 | url.add_element(priority) 171 | else 172 | puts "ERROR: Invalid Priority In #{page_or_post.name}" 173 | end 174 | end 175 | 176 | url 177 | end 178 | 179 | # Get URL location of page or post 180 | # 181 | # Returns the location of the page or post 182 | def fill_location(site, page_or_post) 183 | loc = REXML::Element.new "loc" 184 | url = site.config['url'] + site.config['baseurl'] 185 | loc.text = page_or_post.location_on_server(url) 186 | 187 | loc 188 | end 189 | 190 | # Fill lastmod XML element with the last modified date for the page or post. 191 | # 192 | # Returns lastmod REXML::Element or nil 193 | def fill_last_modified(site, page_or_post) 194 | lastmod = REXML::Element.new "lastmod" 195 | date = File.mtime(page_or_post.path) 196 | latest_date = find_latest_date(date, site, page_or_post) 197 | 198 | if @last_modified_post_date == nil 199 | # This is a post 200 | lastmod.text = latest_date.iso8601 201 | else 202 | # This is a page 203 | if posts_included?(site, page_or_post.path_to_source) 204 | # We want to take into account the last post date 205 | final_date = greater_date(latest_date, @last_modified_post_date) 206 | lastmod.text = final_date.iso8601 207 | else 208 | lastmod.text = latest_date.iso8601 209 | end 210 | end 211 | lastmod 212 | end 213 | 214 | # Go through the page/post and any implemented layouts and get the latest 215 | # modified date 216 | # 217 | # Returns formatted output of latest date of page/post and any used layouts 218 | def find_latest_date(latest_date, site, page_or_post) 219 | layouts = site.layouts 220 | layout = layouts[page_or_post.data["layout"]] 221 | while layout 222 | date = File.mtime(layout.path) 223 | 224 | latest_date = date if (date > latest_date) 225 | 226 | layout = layouts[layout.data["layout"]] 227 | end 228 | 229 | latest_date 230 | end 231 | 232 | # Which of the two dates is later 233 | # 234 | # Returns latest of two dates 235 | def greater_date(date1, date2) 236 | if (date1 >= date2) 237 | date1 238 | else 239 | date2 240 | end 241 | end 242 | 243 | # Is the page or post listed as something we want to exclude? 244 | # 245 | # Returns boolean 246 | def excluded?(site, name) 247 | @config['exclude'].include? name 248 | end 249 | 250 | def posts_included?(site, name) 251 | @config['include_posts'].include? name 252 | end 253 | 254 | # Is the change frequency value provided valid according to the spec 255 | # 256 | # Returns boolean 257 | def valid_change_frequency?(change_frequency) 258 | VALID_CHANGE_FREQUENCY_VALUES.include? change_frequency 259 | end 260 | 261 | # Is the priority value provided valid according to the spec 262 | # 263 | # Returns boolean 264 | def valid_priority?(priority) 265 | begin 266 | priority_val = Float(priority) 267 | return true if priority_val >= 0.0 and priority_val <= 1.0 268 | rescue ArgumentError 269 | end 270 | 271 | false 272 | end 273 | end 274 | end 275 | -------------------------------------------------------------------------------- /src/_posts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magento-research/pwa-devdocs/6191acca66f83df2eb541907df4193d69701bc07/src/_posts/.gitkeep -------------------------------------------------------------------------------- /src/_scss/_variables.scss: -------------------------------------------------------------------------------- 1 | $body-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 2 | //$body-font-family: 'Open Sans', 'Helvetica', 'Arial', sans-serif; 3 | 4 | $font-size-base: 1rem; 5 | $font-size-lg: 1.25rem; 6 | $font-size-sm: .875rem; 7 | $font-size-xsm: .7rem; 8 | 9 | $font-weight-light: 300; 10 | $font-weight-normal: normal; 11 | $font-weight-medium: 500; 12 | $font-weight-bold: bold; 13 | 14 | $line-height-base: 1.5; 15 | 16 | $spacing: 5px; 17 | 18 | $sidebar-width: 270px; 19 | $page-info-width: 200px; 20 | 21 | $header-height: $spacing*11; 22 | 23 | 24 | // Breakpoints 25 | $small-screen: 'max-width: 768px'; 26 | $medium-screen: 'max-width: 1023px'; 27 | $medium-to-large-screen: 'max-width: 1200px'; 28 | $large-screen: 'min-width: 1500px'; 29 | 30 | 31 | 32 | 33 | 34 | // Colors 35 | $brand-color: #F26322; 36 | $body-font-color: #2b2b2c; 37 | $accent-color: #26A2AA; 38 | 39 | $light-gray-color: #F1F1F1; 40 | $dark-gray-color: #888; 41 | $beige-color: #CAC3B4; 42 | 43 | $footer-color: #A6ABB0; 44 | $footer-link-color: #D8D9DA; 45 | $footer-background-color: #31302B; 46 | 47 | 48 | $link-color: #1572D0; 49 | $link-hover-color: #cc0000; 50 | $link-active-color: #EC632E; 51 | $link-visited-color: #609; 52 | 53 | $border-color: #d2d2d2; 54 | 55 | 56 | // buttons 57 | $btn-color: $body-font-color; 58 | $btn-bg-color: #ccc; 59 | 60 | $btn-primary-color: #fff; 61 | $btn-primary-bg-color: $brand-color; 62 | 63 | 64 | 65 | 66 | 67 | 68 | // Dropdown 69 | 70 | $dropdown-bg: #fff; 71 | $dropdown-border-color: #ccc; 72 | $dropdown-border-width: 1px; 73 | $dropdown-divider-bg: #e5e5e5; 74 | 75 | $dropdown-link-color: $body-font-color; 76 | $dropdown-link-hover-color: $body-font-color; 77 | $dropdown-link-hover-bg: #f2f3f3; 78 | 79 | $dropdown-link-active-color: $link-color; 80 | $dropdown-link-active-bg: $link-color; 81 | 82 | $dropdown-link-disabled-color: #ccc; 83 | $dropdown-header-color: #ccc; 84 | 85 | $caret-width: .3em; 86 | $caret-width-lg: $caret-width; 87 | 88 | $border-radius: 0; 89 | $line-height: 1.3; 90 | 91 | 92 | 93 | 94 | $transition-duration: .2s; 95 | 96 | 97 | // Z Index 98 | 99 | $zindex-appbar: 1000; 100 | $zindex-nav-fader: 900; 101 | $zindex-dropdown: 9999; 102 | -------------------------------------------------------------------------------- /src/_scss/main.scss: -------------------------------------------------------------------------------- 1 | // Import theme variables 2 | @import "variables"; 3 | 4 | @import "var/syntax"; 5 | 6 | @import "src/home"; 7 | @import "src/message-banner"; 8 | @import "src/material-icons"; 9 | -------------------------------------------------------------------------------- /src/_scss/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magento-research/pwa-devdocs/6191acca66f83df2eb541907df4193d69701bc07/src/_scss/src/.gitkeep -------------------------------------------------------------------------------- /src/_scss/src/_home.scss: -------------------------------------------------------------------------------- 1 | // General tiles (TODO: move this to a theme) 2 | $column-gap: 0.75rem !default; 3 | 4 | .columns { 5 | display: flex; 6 | flex-wrap: wrap; 7 | margin-left: (-$column-gap); 8 | margin-right: (-$column-gap); 9 | margin-top: (-$column-gap); 10 | margin-bottom: (-$column-gap); 11 | } 12 | 13 | .column { 14 | display: flex; 15 | 16 | flex-basis: 0; 17 | flex-grow: 1; 18 | flex-shrink: 1; 19 | 20 | padding: $column-gap; 21 | } 22 | 23 | 24 | // TODO: Move this to a theme and make a component to reuse in other docs websites 25 | 26 | a.card { 27 | width: 100%; 28 | display: block; 29 | color: $body-font-color; 30 | background: #F2F3F3; 31 | border-radius: 2px; 32 | border: 2px solid transparent; 33 | 34 | padding: 30px 35px; 35 | 36 | transition: all .2s; 37 | 38 | & a { 39 | color: $body-font-color; 40 | } 41 | 42 | &:hover { 43 | color: $body-font-color; 44 | text-decoration: none; 45 | border-color: $brand-color; 46 | box-shadow: 0 3px 10px rgba(0,0,0,.2); 47 | transform: translateY(-3px); 48 | } 49 | 50 | &:active { 51 | transform: translateY(0); 52 | } 53 | 54 | p:last-child { 55 | margin-bottom: 0; 56 | } 57 | 58 | } 59 | 60 | 61 | 62 | // Home page sections 63 | 64 | 65 | .home-getting-started { 66 | 67 | .column { 68 | width: 50%; 69 | flex-basis: 50%; 70 | 71 | @media ($small-screen) { 72 | width: auto; 73 | flex-basis: auto; 74 | padding-left: 0; 75 | padding-right: 0; 76 | } 77 | } 78 | } 79 | 80 | 81 | 82 | 83 | 84 | .home-contribute { 85 | 86 | .intro { 87 | text-align: center; 88 | } 89 | 90 | h2 { 91 | font-size: 40px; 92 | font-weight: $font-weight-light; 93 | 94 | @media ($small-screen) { 95 | font-size: 34px; 96 | } 97 | } 98 | 99 | .column { 100 | flex-basis: 33%; 101 | flex-grow: 0; 102 | 103 | p:last-child { 104 | margin-bottom: 0; 105 | } 106 | 107 | @media ($medium-screen) { 108 | flex-basis: 50%; 109 | } 110 | 111 | @media ($small-screen) { 112 | width: auto; 113 | flex-basis: auto; 114 | padding: 0; 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/_scss/src/_material-icons.scss: -------------------------------------------------------------------------------- 1 | .material-icons { 2 | &.edit{ 3 | vertical-align: sub; 4 | } 5 | 6 | &.warning{ 7 | vertical-align: sub; 8 | color: #ffa500; 9 | } 10 | 11 | &.green{ 12 | color: #008000; 13 | } 14 | } -------------------------------------------------------------------------------- /src/_scss/src/_message-banner.scss: -------------------------------------------------------------------------------- 1 | .message-banner { 2 | margin: 0; 3 | padding: 10px 20px; 4 | border-left: none; 5 | border-right: none; 6 | } 7 | -------------------------------------------------------------------------------- /src/_scss/src/menu-section.scss: -------------------------------------------------------------------------------- 1 | .menu-section { 2 | padding-bottom: 5px; 3 | 4 | .toc-entry { 5 | display: flex; 6 | cursor: pointer; 7 | 8 | border-bottom: 1px solid #d2d2d2; 9 | 10 | h4 { 11 | flex-grow: 1; 12 | } 13 | 14 | .material-icons { 15 | font-size: 36px; 16 | color: #26A2AA; 17 | } 18 | } 19 | 20 | .table-of-contents { 21 | 22 | .stub { 23 | color: #626366; 24 | font-style: italic 25 | } 26 | 27 | } 28 | } 29 | 30 | .sidebar { 31 | 32 | ul ul a { 33 | padding-left: 30px; 34 | } 35 | 36 | .guide-title { 37 | color: #626366; 38 | border-bottom: none; 39 | } 40 | } -------------------------------------------------------------------------------- /src/_scss/var/_syntax.scss: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffc; } 2 | .highlight .c { color: #999; } /* Comment */ 3 | .highlight .err { color: #a00; background-color: #faa } /* Error */ 4 | .highlight .k { color: #069; } /* Keyword */ 5 | .highlight .o { color: #555 } /* Operator */ 6 | .highlight .cm { color: #09f; font-style: italic } /* Comment.Multiline */ 7 | .highlight .cp { color: #099 } /* Comment.Preproc */ 8 | .highlight .c1 { color: #999; } /* Comment.Single */ 9 | .highlight .cs { color: #999; } /* Comment.Special */ 10 | .highlight .gd { background-color: #fcc; border: 1px solid #c00 } /* Generic.Deleted */ 11 | .highlight .ge { font-style: italic } /* Generic.Emph */ 12 | .highlight .gr { color: #f00 } /* Generic.Error */ 13 | .highlight .gh { color: #030; } /* Generic.Heading */ 14 | .highlight .gi { background-color: #cfc; border: 1px solid #0c0 } /* Generic.Inserted */ 15 | .highlight .go { color: #aaa } /* Generic.Output */ 16 | .highlight .gp { color: #009; } /* Generic.Prompt */ 17 | .highlight .gs { } /* Generic.Strong */ 18 | .highlight .gu { color: #030; } /* Generic.Subheading */ 19 | .highlight .gt { color: #9c6 } /* Generic.Traceback */ 20 | .highlight .kc { color: #069; } /* Keyword.Constant */ 21 | .highlight .kd { color: #069; } /* Keyword.Declaration */ 22 | .highlight .kn { color: #069; } /* Keyword.Namespace */ 23 | .highlight .kp { color: #069 } /* Keyword.Pseudo */ 24 | .highlight .kr { color: #069; } /* Keyword.Reserved */ 25 | .highlight .kt { color: #078; } /* Keyword.Type */ 26 | .highlight .m { color: #f60 } /* Literal.Number */ 27 | .highlight .s { color: #d44950 } /* Literal.String */ 28 | .highlight .na { color: #4f9fcf } /* Name.Attribute */ 29 | .highlight .nb { color: #366 } /* Name.Builtin */ 30 | .highlight .nc { color: #0a8; } /* Name.Class */ 31 | .highlight .no { color: #360 } /* Name.Constant */ 32 | .highlight .nd { color: #99f } /* Name.Decorator */ 33 | .highlight .ni { color: #999; } /* Name.Entity */ 34 | .highlight .ne { color: #c00; } /* Name.Exception */ 35 | .highlight .nf { color: #c0f } /* Name.Function */ 36 | .highlight .nl { color: #99f } /* Name.Label */ 37 | .highlight .nn { color: #0cf; } /* Name.Namespace */ 38 | .highlight .nt { color: #2f6f9f; } /* Name.Tag */ 39 | .highlight .nv { color: #033 } /* Name.Variable */ 40 | .highlight .ow { color: #000; } /* Operator.Word */ 41 | .highlight .w { color: #bbb } /* Text.Whitespace */ 42 | .highlight .mf { color: #f60 } /* Literal.Number.Float */ 43 | .highlight .mh { color: #f60 } /* Literal.Number.Hex */ 44 | .highlight .mi { color: #f60 } /* Literal.Number.Integer */ 45 | .highlight .mo { color: #f60 } /* Literal.Number.Oct */ 46 | .highlight .sb { color: #c30 } /* Literal.String.Backtick */ 47 | .highlight .sc { color: #c30 } /* Literal.String.Char */ 48 | .highlight .sd { color: #c30; font-style: italic } /* Literal.String.Doc */ 49 | .highlight .s2 { color: #c30 } /* Literal.String.Double */ 50 | .highlight .se { color: #c30; } /* Literal.String.Escape */ 51 | .highlight .sh { color: #c30 } /* Literal.String.Heredoc */ 52 | .highlight .si { color: #a00 } /* Literal.String.Interpol */ 53 | .highlight .sx { color: #c30 } /* Literal.String.Other */ 54 | .highlight .sr { color: #3aa } /* Literal.String.Regex */ 55 | .highlight .s1 { color: #c30 } /* Literal.String.Single */ 56 | .highlight .ss { color: #fc3 } /* Literal.String.Symbol */ 57 | .highlight .bp { color: #366 } /* Name.Builtin.Pseudo */ 58 | .highlight .vc { color: #033 } /* Name.Variable.Class */ 59 | .highlight .vg { color: #033 } /* Name.Variable.Global */ 60 | .highlight .vi { color: #033 } /* Name.Variable.Instance */ 61 | .highlight .il { color: #f60 } /* Literal.Number.Integer.Long */ 62 | 63 | .css .o, 64 | .css .o + .nt, 65 | .css .nt + .nt { color: #999; } 66 | -------------------------------------------------------------------------------- /src/guides/testing/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md %} -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | --- 4 | 5 |
6 | 68 | 69 |
70 | 71 |
72 | 73 |
74 | 75 |
76 | 77 |

Contribute to the Project

78 | 79 |

80 | The Magento PWA Studio project is an open source project that welcomes community contributions and collaboration. 81 |

82 |

83 | All the tools listed below are available as separate packages in the PWA Studio repository. 84 |

85 |

86 | If you have any questions, please join the #pwa Slack channel at magentocommeng.slack.com. 87 |

88 | 89 |
90 | 91 | 92 |
93 | 94 |
95 |
96 |

97 | Buildpack 98 |

99 |

100 | Build and layout optimization tooling for Magento PWA projects. 101 |

102 |
103 |
104 | 105 |
106 |
107 |

108 | Peregrine 109 |

110 |

111 | A collection of UI components for the Magento PWA projects. 112 |

113 |
114 |
115 | 116 |
117 |
118 |

119 | Venia Theme (Concept) 120 |

121 |

122 | A conceptual PWA theme for Magento 2 built using the Peregrine component library and Buildpack tools. 123 |

124 |
125 |
126 | 127 |
128 | 129 |
130 | 131 |
132 | -------------------------------------------------------------------------------- /src/peregrine/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Peregrine 3 | --- 4 | 5 | The Peregrine project is a collection of UI components for Magento PWA projects. 6 | Use, extend, or remix these components to create a unique Magento PWA theme. 7 | 8 | Visit the [`peregrine`] repository to contribute to this project. 9 | 10 | [`peregrine`]: https://github.com/magento-research/pwa-studio/tree/master/packages/peregrine -------------------------------------------------------------------------------- /src/peregrine/reference/container-child/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ContainerChild 3 | --- 4 | 5 | The `ContainerChild` component is the only child allowed within a [Container] in Magento PWA theme. 6 | This component is responsible for rendering content. 7 | 8 | ## Props 9 | 10 | | Name | Required | Description | 11 | | -------- | :-------------------------------------------: | --------------------------------------------------------- | 12 | | `id` | check_box | A unique string identifier | 13 | | `render` | check_box | A [render prop] that should return the children to render | 14 | {:style="table-layout:auto"} 15 | 16 | ## Example 17 | 18 | ``` jsx 19 | import { ContainerChild } from '@magento/peregrine'; 20 | 21 |
22 |
Used just like a normal render() method
} 25 | /> 26 | ( 29 |
Can render anything a normal component can render
30 | )} 31 | /> 32 |
; 33 | ``` 34 | 35 | [render prop]: https://reactjs.org/docs/render-props.html 36 | [Container]: {{ site.baseurl }}{% link technologies/basic-concepts/container-extensibility/index.md %} -------------------------------------------------------------------------------- /src/peregrine/reference/item/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Item 3 | --- 4 | 5 | 6 | The `Item` component takes a data object and renders it using a [render prop] or wraps it in an HTML element. 7 | 8 | This component is used as a direct child of the [`Items`] fragment. 9 | 10 | ## Props 11 | 12 | | Name | Required | Default | Description | 13 | | ------------ | :-------------------------------------------: | ------- | ------------------------------------------------------------- | 14 | | `classes` | | `{}` | A classname hash | 15 | | `hasFocus` | | `false` | Set to `true` if the browser is currently focused on the item | 16 | | `isSelected` | | `false` | Set to `true` if the item is currently selected | 17 | | `item` | check_box | | A data object. If this is a string, it is rendered as a child | 18 | | `render` | check_box | `'div'` | A render prop or HTML tagname string, such as `"div"`. | 19 | {:style="table-layout:auto"} 20 | 21 | ## Example 22 | 23 | ``` jsx 24 | {% raw %} 25 | import Item from '@magento/peregrine'; 26 | 27 | 32 | {% endraw %} 33 | ``` 34 | 35 | [render prop]: https://reactjs.org/docs/render-props.html 36 | [`Items`]: {{ site.baseurl }}{% link peregrine/reference/items/index.md %} 37 | [`List`]: {{ site.baseurl }}{% link peregrine/reference/list/index.md %} -------------------------------------------------------------------------------- /src/peregrine/reference/items/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Items 3 | --- 4 | 5 | The `Items` component uses content in a data object to render a list of [`Item`] components. 6 | 7 | It follows the [Fragments] pattern and returns its children without a wrapping element. 8 | This allows you to decide how you want to wrap your list of items. 9 | 10 | The `Items` component is used as a direct child of the [`List`] component. 11 | 12 | ## Props 13 | 14 | | Name | Required | Description | 15 | | ---------------- | :-------------------------------------------: | ------------------------------------------------------------------- | 16 | | `items` | check_box | An iterable that yields `[key, item]` pairs such as an ES2015 [Map] | 17 | | `renderItem` | | A [render prop] or HTML tagname string. | 18 | | `selectionModel` | | A string corresponding to a selection model. | 19 | {:style="table-layout:auto"} 20 | 21 | ### Selection models 22 | 23 | {% include peregrine/reference/list-selection-models.md %} 24 | 25 | ## Example 26 | 27 | ``` jsx 28 | import Items from '@magento/peregrine'; 29 | 30 | const data = { 31 | s: { id: 's', value: 'Small' }, 32 | m: { id: 'm', value: 'Medium' }, 33 | l: { id: 'l', value: 'Large' } 34 | }; 35 | 36 | 41 | ``` 42 | 43 | [`List`]: {{ site.baseurl }}{% link peregrine/reference/list/index.md %} 44 | [render prop]: https://reactjs.org/docs/render-props.html 45 | [Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map 46 | [Fragments]: https://reactjs.org/docs/fragments.html 47 | [`Item`]: {{ site.baseurl }}{% link peregrine/reference/item/index.md %} -------------------------------------------------------------------------------- /src/peregrine/reference/list/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: List 3 | --- 4 | 5 | The `List` component maps a collection of data objects into an array of elements. 6 | It also manages the selection and focus of those elements. 7 | 8 | ## Props 9 | 10 | | Name | Required | Description | 11 | | ------------------- | :-------------------------------------------: | --------------------------------------------------------------------------------------------- | 12 | | `classes` | | A classname object | 13 | | `items` | check_box | An iterable that yields `[key, item]` pairs such as an ES2015 [Map] | 14 | | `render` | check_box | A [render prop] for the list element. A tagname string, such as `"div"`, is also valid. | 15 | | `renderItem` | | A [render prop] for the list item elements. A tagname string, such as `"div"`, is also valid. | 16 | | `onSelectionChange` | | A callback that fires when the selection state changes. | 17 | | `selectionModel` | | A string corresponding to a selection model. | 18 | {:style="table-layout:auto"} 19 | 20 | ### Selection models 21 | 22 | {% include peregrine/reference/list-selection-models.md %} 23 | 24 | ## Example 25 | 26 | ``` jsx 27 | {% raw %} 28 | import { List } from '@magento/peregrine'; 29 | 30 | const simpleData = new Map() 31 | .set('s', 'Small') 32 | .set('m', 'Medium') 33 | .set('l', 'Large') 34 | 35 | 41 | 42 | const complexData = new Map() 43 | .set('s', { id: 's', value: 'Small' }) 44 | .set('m', { id: 'm', value: 'Medium' }) 45 | .set('l', { id: 'l', value: 'Large' }) 46 | 47 | (
    {props.children}
)} 51 | renderItem={props => (
  • {props.value}
  • )} 52 | /> 53 | {% endraw %} 54 | ``` 55 | 56 | [render prop]: https://reactjs.org/docs/render-props.html 57 | [Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map -------------------------------------------------------------------------------- /src/peregrine/reference/router/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Router 3 | --- 4 | 5 | The Peregrine Router is a client-side router that is designed to understand the different storefront routes within Magento 2. 6 | If using Peregrine to bootstrap your PWA, it is configured automatically. If not, the Router can be manually consumed. 7 | 8 | ## Props 9 | 10 | | Name | Required | Description | 11 | | ------------- | :-------------------------------------------: | ------------------------------------------------------------------------------------------------------- | 12 | | `apiBase` | check_box | Root URL of the Magento store (including protocol and hostname) | 13 | | `using` | | Router implementation from React-Router. Possible values: `BrowserRouter`, `HashRouter`, `MemoryRouter` | 14 | | `routerProps` | | Any additional props to pass to React-Router | 15 | {:style="table-layout:auto"} 16 | 17 | ## Example 18 | 19 | The following example shows the manual usage of the Router component: 20 | 21 | ``` jsx 22 | import ReactDOM from 'react-dom'; 23 | import { Router } from '@magento/peregrine'; 24 | 25 | ReactDOM.render( 26 | , 27 | document.querySelector('main') 28 | ); 29 | ``` -------------------------------------------------------------------------------- /src/pwa-buildpack/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: PWA Buildpack 3 | --- 4 | 5 | PWA Buildpack is a build and development tool and library for Magento Progressive Web Apps. 6 | Use the PWA Buildpack project to set up and configure your local environment for PWA development. 7 | 8 | ## Setup 9 | 10 | Follow the [Project setup tutorial] to set up a PWA development environment. 11 | 12 | If you are having trouble setting up your environment, see the [Troubleshooting page]. 13 | 14 | ## Contribute 15 | 16 | Visit the [`pwa-buildpack`] package in the PWA Studio repository to contribute to this project. 17 | 18 | [`pwa-buildpack`]: https://github.com/magento-research/pwa-studio/tree/master/packages/pwa-buildpack 19 | [Project setup tutorial]: {{ site.baseurl }}{% link pwa-buildpack/project-setup/index.md %} 20 | [Troubleshooting page]: {{ site.baseurl }}{% link pwa-buildpack/troubleshooting/index.md %} -------------------------------------------------------------------------------- /src/pwa-buildpack/project-setup/create-configuration-files/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Create configuration files 3 | --- 4 | 5 | In the [previous topic], you linked your project to the Magento backend store. 6 | In this topic, you will create the configuration files for your development environment. 7 | 8 | ## Create the Babel configuration file 9 | 10 | Create a `.babelrc` file in your theme’s root directory with the following content: 11 | 12 | ``` javascript 13 | { 14 | "plugins": [ 15 | "syntax-jsx", 16 | "transform-class-properties", 17 | "transform-object-rest-spread", 18 | "transform-react-jsx" 19 | ] 20 | } 21 | ``` 22 | 23 | This configuration installs the following [Babel] plugins: 24 | 25 | * [`syntax-jsx`] and [`transform-react-jsx`] - Transform [JSX] code into backwards-compatible JavaScript. 26 | JSX allows you to write React components using a syntax structure similar to HTML. 27 | 28 | See [Introducing JSX] for more information. 29 | * [`transform-class-properties`] - Transforms class properties and lets you use the following syntax: 30 | ``` javascript 31 | class Example { 32 | anInstanceProperty = 52; 33 | } 34 | ``` 35 | * [`transform-object-rest-spread`] - Transforms the rest and spread properties for objects to let you use the following syntax: 36 | ``` javascript 37 | const config = { ...defaultConfig, ...passedConfig }; 38 | ``` 39 | 40 | In general, these plugins provide convenience and produce cleaner code in your project. 41 | 42 | ## Create the local environment variables file 43 | 44 | Create a `.env` file and assign values to the following environment variables: 45 | 46 | * `MAGENTO_BACKEND_DOMAIN` - Your local Magento store’s host and port. 47 | * `MAGENTO_BACKEND_PUBLIC_PATH` - PWA files are served from root during development, but 48 | this environment variable can later be used to simulate a deployed static path. 49 | * `SERVICE_WORKER_FILE_NAME` - Set this value to `"sw.js"`. 50 | 51 | Your file should look like the following: 52 | 53 | ``` text 54 | MAGENTO_BACKEND_DOMAIN=https://localhost.magento:8008 55 | 56 | MAGENTO_BACKEND_PUBLIC_PATH=/ 57 | 58 | SERVICE_WORKER_FILE_NAME="sw.js" 59 | ``` 60 | 61 | ## Create the webpack configuration file 62 | 63 | Create a `webpack.config.js` file in your theme’s root directory. 64 | This file exports a configuration object that tells Webpack how to build your theme. 65 | 66 | Webpack configuration is a complicated topic, so the following sections explain what each piece does in the configuration file. 67 | To see the fully assembled file, see the example [webpack.config.js]. 68 | 69 | ### Import environment variables 70 | 71 | At the top of the webpack.config.js file add the following: 72 | 73 | ``` javascript 74 | require('dotenv').config(); 75 | ``` 76 | 77 | This imports the the contents of the `.env` file as environment variables using the `dotenv` module. 78 | These environment variables are accessed using the `process.env` global object. 79 | 80 | For example, the following code outputs the value of the `MAGENTO_BACKEND_DOMAIN` environment variable: 81 | 82 | ``` javascript 83 | console.log(process.env.MAGENTO_BACKEND_DOMAIN); 84 | ``` 85 | 86 | ### Import Webpack and pwa-buildpack libraries 87 | 88 | Append the following content to `webpack.config.js` to import the Webpack and pwa-buildpack libraries: 89 | 90 | ``` javascript 91 | const webpack = require('webpack'); 92 | const { 93 | WebpackTools: { 94 | MagentoRootComponentsPlugin, 95 | ServiceWorkerPlugin, 96 | MagentoResolver, 97 | PWADevServer 98 | } 99 | } = require('@magento/pwa-buildpack'); 100 | ``` 101 | 102 | ### Define paths to theme resources 103 | 104 | Add the following content to `webpack.config.js` to define the paths to your theme resources: 105 | 106 | ``` javascript 107 | const path = require('path'); 108 | 109 | const themePaths = { 110 | src: path.resolve(__dirname, 'src'), 111 | assets: path.resolve(__dirname, 'web'), 112 | output: path.resolve(__dirname, 'web/js'), 113 | }; 114 | ``` 115 | 116 | This snippet uses the `path` module to format and normalize the file paths. 117 | It also uses the special Node variable `__dirname` because it always resolves to the directory of the current executing script file. 118 | 119 | The locations specified in the snippet are the standard locations of source code, static assets, and build output in a [Peregrine] app. 120 | 121 | ### Export the Webpack configuration object 122 | 123 | Append the following content to webpack.config.js to export the configuration object for Webpack: 124 | 125 | ``` javascript 126 | module.exports = async function(env) { 127 | const config = { 128 | context: __dirname, // Node global for the running script's directory 129 | entry: { 130 | client: path.resolve(themePaths.src, 'index.js') 131 | }, 132 | output: { 133 | path: themePaths.output, 134 | publicPath: process.env.MAGENTO_BACKEND_PUBLIC_PATH, 135 | filename: '[name].js', 136 | chunkFilename: '[name].js' 137 | }, 138 | module: { 139 | rules: [ 140 | { 141 | include: [themePaths.src], 142 | test: /\.js$/, 143 | use: [ 144 | { 145 | loader: 'babel-loader', 146 | options: { cacheDirectory: true } 147 | } 148 | ] 149 | }, 150 | { 151 | test: /\.css$/, 152 | use: [ 153 | 'style-loader', 154 | { 155 | loader: 'css-loader', 156 | options: { 157 | importLoaders: 1 158 | } 159 | } 160 | ] 161 | } 162 | ] 163 | }, 164 | resolve: await MagentoResolver.configure({ 165 | paths: { 166 | root: __dirname 167 | } 168 | }), 169 | plugins: [ 170 | new MagentoRootComponentsPlugin(), 171 | new webpack.NoEmitOnErrorsPlugin(), 172 | new webpack.EnvironmentPlugin({ 173 | NODE_ENV: env.phase, 174 | SERVICE_WORKER_FILE_NAME: 'sw.js' 175 | }) 176 | ] 177 | 178 | }; 179 | 180 | return config; 181 | } 182 | ``` 183 | 184 | This configuration sets up Webpack for your development environment. 185 | Some important things to note in this configuration: 186 | 187 | * How it configures the `MagentoResolver` service 188 | * The inclusion of the `MagentoRootComponent` as a plugin 189 | * The use of `webpack.EnvironmentPlugin` to pass environment variables 190 | 191 | ### Add development mode configuration 192 | 193 | Add the following development mode configuration before returning the `config` object: 194 | 195 | ``` javascript 196 | if (env.phase === "development") { 197 | config.devServer = await PWADevServer.configure({ 198 | publicPath: process.env.MAGENTO_BACKEND_PUBLIC_PATH, 199 | backendDomain: process.env.MAGENTO_BACKEND_DOMAIN, 200 | serviceWorkerFileName: process.env.SERVICE_WORKER_FILE_NAME, 201 | paths: themePaths, 202 | id: path.basename(__dirname) // Defaults to theme directory name 203 | }); 204 | 205 | // A DevServer generates its own unique output path at startup. It needs 206 | // to assign the main outputPath to this value as well. 207 | 208 | config.output.publicPath = config.devServer.publicPath; 209 | 210 | config.plugins.push( 211 | new ServiceWorkerPlugin({ 212 | env, 213 | paths: themePaths, 214 | enableServiceWorkerDebugging: false, 215 | serviceWorkerFileName: process.env.SERVICE_WORKER_FILE_NAME 216 | }) 217 | ); 218 | 219 | config.plugins.push( 220 | new webpack.HotModuleReplacementPlugin() 221 | ); 222 | } else { 223 | throw Error('Only "development" mode is currently supported. Please pass "--env.phase development" on the command line.'); 224 | } 225 | ``` 226 | 227 | This code block does the following: 228 | 229 | * Create a `PWADevServer` confgiuration object and attach it to the Webpack configuration object. 230 | * Create a `ServiceWorkerPlugin` and attach it to the Webpack configuration object. 231 | * Add a `webpack.HotModuleReplacementPlugin` to enable fast workflow. 232 | * Configure Webpack to throw an error if you are not in development mode. 233 | 234 | ### Add start script 235 | 236 | Edit the `scripts` section of your `package.json file` so it looks like the following: 237 | 238 | ``` javascript 239 | "scripts": { 240 | "start" : "webpack-dev-server --progress --color --env.phase development", 241 | "test": "echo \"Error: no test specified\" && exit 1" 242 | } 243 | ``` 244 | 245 | This allows you to start a development server using the `npm start` command. 246 | The `--env.phase development` argument sets the `mode` property to `development` in the configuration function exported from `webpack.config.js`. 247 | 248 | {: .bs-callout .bs-callout-info} 249 | **Note:** 250 | When you run npm start for the first time or after a long period of time, PWA Studio may ask for your password. 251 | This is required to set the local host and SSL trust settings on your system. 252 | It will not retain broad permissions on your system. 253 | 254 | Now that you have created your project configuration files, you can create a [simple peregrine app]. 255 | 256 | [previous topic]: {{ site.baseurl }}{% link pwa-buildpack/project-setup/link-project/index.md %} 257 | [JSX]: https://facebook.github.io/jsx/ 258 | [Introducing JSX]: https://reactjs.org/docs/introducing-jsx.html 259 | [webpack.config.js]: {{ site.baseurl }}{% link pwa-buildpack/project-setup/create-configuration-files/webpack-config-example/index.md %} 260 | [Peregrine]: {{ site.baseurl }}{% link peregrine/index.md %} 261 | [simple peregrine app]: {{ site.baseurl }}{% link pwa-buildpack/project-setup/create-simple-peregrine-app/index.md %} 262 | [Babel]: https://babeljs.io/ 263 | [`syntax-jsx`]: https://babeljs.io/docs/plugins/syntax-jsx 264 | [`transform-react-jsx`]: https://babeljs.io/docs/plugins/transform-react-jsx 265 | [`transform-class-properties`]: https://babeljs.io/docs/plugins/transform-class-properties/ 266 | [`transform-object-rest-spread`]: https://babeljs.io/docs/plugins/transform-object-rest-spread/ -------------------------------------------------------------------------------- /src/pwa-buildpack/project-setup/create-configuration-files/webpack-config-example/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Example webpack.config.js file 3 | --- 4 | 5 | The following is an example of the `webpack.config.js` file described in the [Create configuration files] topic: 6 | 7 | ``` javascript 8 | require('dotenv').config(); 9 | 10 | const webpack = require('webpack'); 11 | const { 12 | WebpackTools: { 13 | MagentoRootComponentsPlugin, 14 | ServiceWorkerPlugin, 15 | MagentoResolver, 16 | PWADevServer 17 | } 18 | } = require('@magento/pwa-buildpack'); 19 | 20 | const path = require('path'); 21 | 22 | const themePaths = { 23 | src: path.resolve(__dirname, 'src'), 24 | assets: path.resolve(__dirname, 'web'), 25 | output: path.resolve(__dirname, 'web/js'), 26 | }; 27 | 28 | module.exports = async function(env) { 29 | const config = { 30 | mode: env.phase, // passed on the command line via the '--env' flag 31 | context: __dirname, // Node global for the running script's directory 32 | entry: { 33 | client: path.resolve(themePaths.src, 'index.js') 34 | }, 35 | output: { 36 | path: themePaths.output, 37 | publicPath: process.env.MAGENTO_BACKEND_PUBLIC_PATH, 38 | filename: '[name].js', 39 | chunkFilename: '[name].js' 40 | }, 41 | module: { 42 | rules: [ 43 | { 44 | include: [themePaths.src], 45 | test: /\.js$/, 46 | use: [ 47 | { 48 | loader: 'babel-loader', 49 | options: { cacheDirectory: true } 50 | } 51 | ] 52 | }, 53 | { 54 | test: /\.css$/, 55 | use: [ 56 | 'style-loader', 57 | { 58 | loader: 'css-loader', 59 | options: { 60 | importLoaders: 1 61 | } 62 | } 63 | ] 64 | } 65 | ] 66 | }, 67 | resolve: await MagentoResolver.configure({ 68 | paths: { 69 | root: __dirname 70 | } 71 | }), 72 | plugins: [ 73 | new MagentoRootComponentsPlugin(), 74 | new webpack.NoEmitOnErrorsPlugin(), 75 | new webpack.EnvironmentPlugin({ 76 | NODE_ENV: env.phase, 77 | SERVICE_WORKER_FILE_NAME: 'sw.js' 78 | }) 79 | ] 80 | 81 | }; 82 | 83 | if (env.phase === "development") { 84 | config.devServer = await PWADevServer.configure({ 85 | publicPath: process.env.MAGENTO_BACKEND_PUBLIC_PATH, 86 | backendDomain: process.env.MAGENTO_BACKEND_DOMAIN, 87 | serviceWorkerFileName: process.env.SERVICE_WORKER_FILE_NAME, 88 | paths: themePaths, 89 | id: path.basename(__dirname) // Defaults to theme directory name 90 | }); 91 | 92 | // A DevServer generates its own unique output path at startup. It needs 93 | // to assign the main outputPath to this value as well. 94 | 95 | config.output.publicPath = config.devServer.publicPath; 96 | 97 | config.plugins.push( 98 | new ServiceWorkerPlugin({ 99 | env, 100 | paths: themePaths, 101 | enableServiceWorkerDebugging: false, 102 | serviceWorkerFileName: process.env.SERVICE_WORKER_FILE_NAME 103 | }) 104 | ); 105 | 106 | config.plugins.push( 107 | new webpack.HotModuleReplacementPlugin() 108 | ); 109 | 110 | } else { 111 | throw Error('Only "development" mode is currently supported. Please pass "--env.phase development" on the command line.'); 112 | } 113 | 114 | return config; 115 | } 116 | ``` 117 | 118 | [Create configuration files]: {{ site.baseurl }}{% link pwa-buildpack/project-setup/create-configuration-files/index.md %} -------------------------------------------------------------------------------- /src/pwa-buildpack/project-setup/create-simple-peregrine-app/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Create simple peregrine app 3 | --- 4 | 5 | In the [previous topic], you created configuration files for your theme project. 6 | In this topic, you will create a simple app that follows the [Peregrine] pattern. 7 | 8 | ## Create app.js 9 | 10 | 1. Create the `src` and `src/components` directories in your theme's root directory using the following command: 11 | ``` sh 12 | mkdir -p src/components 13 | ``` 14 | 1. Inside the `components` directory, create an `app.js` file with the following content: 15 | 16 | ``` jsx 17 | import React from 'react'; 18 | 19 | export default class App extends React.Component { 20 | render() { 21 | return ( 22 |

    23 | Hello, Studio! 24 |

    25 | ); 26 | } 27 | } 28 | 29 | ``` 30 | 31 | This code defines a React component that returns "Hello, Studio!" inside `h1` tags. 32 | 33 | ## Create index.js 34 | 35 | Inside `src` create an `index.js` file with the following content: 36 | 37 | ``` javascript 38 | import Peregrine from '@magento/peregrine'; 39 | import App from './components/app'; 40 | 41 | const app = new Peregrine(); 42 | const container = document.getElementById('root'); 43 | 44 | app.component = App; 45 | app.mount(container); 46 | 47 | if ('serviceWorker' in navigator) { 48 | window.addEventListener('load', () => { 49 | navigator.serviceWorker 50 | .register(process.env.SERVICE_WORKER_FILE_NAME); 51 | }); 52 | } 53 | 54 | export default app; 55 | ``` 56 | 57 | This imports the previously-defined `app` component and incorporates it into Peregrine before adding it to an HTML `root` element. 58 | 59 | ## Create RootComponents directory 60 | 61 | Inside `src`, create a `RootComponents` directory. 62 | This directory will contain code for your root components. 63 | For now, leave this directory empty. 64 | 65 | ## Congratulations! 66 | 67 | You have created a Peregrine app skeleton! 68 | 69 | If you followed the [Project setup tutorial] from the beginning, you can now run the following command in the root of your theme directory to finish setting up your development environment: 70 | 71 | ``` sh 72 | npm start 73 | ``` 74 | 75 | If you experience problems with the project setup, see [Troubleshooting]. 76 | 77 | [previous topic]: {{ site.baseurl }}{% link pwa-buildpack/project-setup/create-configuration-files/index.md %} 78 | [Peregrine]: {{ site.baseurl }}{% link peregrine/index.md %} 79 | [Project setup tutorial]: {{ site.baseurl }}{% link pwa-buildpack/project-setup/index.md %} 80 | [Troubleshooting]: {{ site.baseurl }}{% link pwa-buildpack/troubleshooting/index.md %} -------------------------------------------------------------------------------- /src/pwa-buildpack/project-setup/create-theme-files/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Create the initial theme files 3 | 4 | --- 5 | 6 | Unlike regular [Magento Themes], Magento Progressive Web Apps are built on top of the [PWA base theme]. 7 | They are also *decoupled* from the backing Magento stores, so they no longer need to be developed under `app/design/frontend`. 8 | 9 | It is still possible to develop your project under `app/design/frontend`, but 10 | the recommended approach is to use Composer to manage the connection between your project and the backend store. 11 | 12 | In this part of the [Project setup tutorial], you will create the initial files and directories for a Magento PWA theme using the recommended Composer approach. 13 | 14 | ## Create theme directory and files 15 | 16 | 17 | 1. For this tutorial, **orange-theme** will be the name of the theme directory. 18 | Run the following command to create this directory and `cd` into it: 19 | 20 | ``` bash 21 | mkdir orange-theme && cd orange-theme 22 | ``` 23 | 24 | {: .bs-callout .bs-callout-info} 25 | **Note:** 26 | Your theme directory does not need to be created inside a Magento application directory. 27 | 28 | 1. Create a `media` directory and place a `preview.jpg` image file inside. 29 | This image is used as the preview image for your theme. 30 | 1. Create a `theme.xml` file. 31 | 32 | ``` xml 33 | 34 | 35 | 36 | Orange Theme 37 | Magento/pwa 38 | 39 | media/preview.jpg 40 | 41 | 42 | ``` 43 | 44 | This file provides the name of theme, the required PWA parent theme, and the location of the preview image to Magento. 45 | 46 | 1. Create a `composer.json` file. 47 | 48 | ``` json 49 | { 50 | "name": "orangecompany/orange-theme", 51 | "description": "The inimitable Orange Theme.", 52 | "version": "1.0.0", 53 | "require": { 54 | "php": "~7.1.0|~7.2.0", 55 | "magento/framework": "100.3.*", 56 | "magento-research/theme-frontend-pwa": "*" 57 | }, 58 | "type": "magento2-theme", 59 | "license": "OSL-3.0", 60 | "autoload": { 61 | "files": ["registration.php"] 62 | } 63 | } 64 | ``` 65 | 66 | This file makes your theme a composer package for easy distribution in the [Magento Marketplace]. 67 | 1. Create a `registration.php` file to register your theme with Magento. 68 | 69 | ``` php 70 | path/to/orange-theme 37 | ``` 38 | 39 | Since the theme project is installed using a symlink, any edits made in the original location appear on the store without re-installing the plugin. 40 | 41 | ### Admin 42 | 43 | Log into the Admin section of your Magento installation and select **Themes** in the **Content** tab. 44 | 45 | You should see Orange Theme listed as one of the available themes in Magento. 46 | 47 | To install the theme, select **Configuration** in the **Content** tab and set your storefront to use the Orange Theme. 48 | 49 | The next step is to [create the configuration files]. 50 | 51 | 52 | [previous topic]: {{ site.baseurl }}{% link pwa-buildpack/project-setup/install-dependencies/index.md %} 53 | [create the configuration files]: {{ site.baseurl }}{% link pwa-buildpack/project-setup/create-configuration-files/index.md %} -------------------------------------------------------------------------------- /src/pwa-buildpack/reference/layout-loader/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: magento-layout-loader 3 | --- 4 | 5 | {: .bs-callout .bs-callout-warning} 6 | **Warning:** This is a very early implementation. This API should be considered unstable. 7 | 8 | 9 | The `magento-layout-loader` is a [webpack loader] that transforms [JSX] during compilation. 10 | It gives Magento modules and extensions the ability to inject or remove content blocks in a layout without modifying the theme source files. 11 | 12 | ## Properties 13 | 14 | | Name | Description | 15 | | ----------------- | ----------------------------------------------------------------------------------------- | 16 | | `operation` | One of the supported types of operations. | 17 | | `targetContainer` | The `data-mid` value of the `Container` to target. | 18 | | `targetChild` | The `id` value of the [`ContainerChild`] to target within `targetContainer`. | 19 | | `componentPath` | An absolute path pointing to a file containing a React component as the `default` export. | 20 | 21 | ## Supported operations 22 | 23 | The following `operation` configuration values are supported: 24 | 25 | * `removeContainer` - removes a specific `Container` 26 | * `removeChild` - removes a specific `ContainerChild` in a specific `Container` 27 | * `insertBefore` - inserts a component before a specific `ContainerChild` in a `Container` 28 | * `insertAfter` - inserts a component after a specific `ContainerChild` in a `Container` 29 | 30 | ## Examples 31 | 32 | ### `removeContainer` 33 | 34 | **Example configuration:** 35 | 36 | ``` json 37 | { 38 | "operation": "removeContainer", 39 | "targetContainer": "any.container.id" 40 | } 41 | ``` 42 | 43 | **Affected code:** 44 | ``` jsx 45 | import React from 'react'; 46 | 47 | function render() { 48 | return ( 49 |
    50 | The div below will be removed 51 |
    52 |
    53 | ); 54 | } 55 | ``` 56 | 57 | ### `removeChild` 58 | 59 | **Example configuration:** 60 | 61 | ``` json 62 | { 63 | "operation": "removeChild", 64 | "targetContainer": "any.container.id", 65 | "targetChild": "container.child.id" 66 | } 67 | ``` 68 | 69 | **Affected code:** 70 | ``` jsx 71 | import React from 'react'; 72 | import { ContainerChild } from '@magento/peregrine'; 73 | 74 | function render() { 75 | return ( 76 |
    77 | The container below will be removed 78 |
    This content will be removed
    } 81 | /> 82 |
    83 | ); 84 | } 85 | ``` 86 | 87 | ### `insertBefore` 88 | 89 | **Example configuration:** 90 | 91 | ``` json 92 | { 93 | "operation": "insertBefore", 94 | "targetContainer": "any.container.id", 95 | "targetChild": "container.child.id", 96 | "componentPath": "/Absolute/path/to/a/component.js" 97 | } 98 | ``` 99 | 100 | **Affected code:** 101 | ``` jsx 102 | import React from 'react'; 103 | import { ContainerChild } from '@magento/peregrine'; 104 | 105 | function render() { 106 | return ( 107 |
    108 |
    Some Content
    } 111 | /> 112 |
    113 | ); 114 | } 115 | ``` 116 | 117 | ### `insertAfter` 118 | 119 | **Example configuration:** 120 | ``` json 121 | { 122 | "operation": "insertAfter", 123 | "targetContainer": "any.container.id", 124 | "targetChild": "container.child.id", 125 | "componentPath": "/Absolute/path/to/a/component.js" 126 | } 127 | ``` 128 | 129 | **Affected code:** 130 | ``` jsx 131 | import React from 'react'; 132 | import { ContainerChild } from '@magento/peregrine'; 133 | 134 | function render() { 135 | return ( 136 |
    137 |
    Some Content
    } 140 | /> 141 |
    142 | ); 143 | } 144 | ``` 145 | 146 | [webpack loader]: https://webpack.js.org/concepts/loaders/ 147 | [JSX]: https://reactjs.org/docs/introducing-jsx.html 148 | [`ContainerChild`]: {{ site.baseurl }}{% link peregrine/reference/container-child/index.md %} 149 | -------------------------------------------------------------------------------- /src/pwa-buildpack/reference/magento-resolver/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: MagentoResolver 3 | --- 4 | 5 | An adapter that configures Webpack to resolve assets using Magento PWA conventions. 6 | 7 | This module generates a configuration object used in the [`resolve`] property of a Webpack config. 8 | The configuration object tells Webpack how to traverse the filesystem structure for assets required in source files. 9 | 10 | 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. 11 | 12 | ## API 13 | 14 | ### `configure(options)` 15 | 16 | **Parameters:** 17 | 18 | * `options:`[`LocalProjectLocation`] - Configuration object that describes where the theme folders are located. 19 | 20 | **Return:** 21 | 22 | A [Promise] configuration type for webpack. 23 | 24 | {: .bs-callout .bs-callout-info} 25 | **Note:** 26 | `MagentoResolver.configure()` is asynchronous. 27 | 28 | ## Example 29 | 30 | In `webpack.config.js`: 31 | 32 | ``` js 33 | const buildpack = require('@magento/pwa-buildpack'); 34 | const MagentoResolver = buildpack.Webpack.MagentoResolver; 35 | 36 | module.exports = async env => { 37 | const config { 38 | /* webpack entry, output, rules, etc */ 39 | 40 | 41 | resolve: await MagentoResolver.configure({ 42 | paths: { 43 | root: __dirname 44 | } 45 | }) 46 | 47 | }; 48 | 49 | return config; 50 | } 51 | ``` 52 | 53 | 54 | 55 | {: .bs-callout .bs-callout-tip} 56 | The special `__dirname` variable in Node always refers to the directory containing the currently executing script file. 57 | This is different from the "working directory", which is the current directory of the shell when the current process was started. 58 | 59 | {: .bs-callout .bs-callout-info} 60 | **Note:** 61 | The example provided uses the newer, cleaner `async/await` syntax instead of using Promises directly. 62 | 63 | 64 | [`resolve`]: https://webpack.js.org/configuration/resolve/ 65 | [Promise]: https://webpack.js.org/configuration/configuration-types/#exporting-a-promise 66 | [`LocalProjectLocation`]: {{ site.baseurl }}{%link pwa-buildpack/reference/object-types/index.md %}#localprojectlocation -------------------------------------------------------------------------------- /src/pwa-buildpack/reference/object-types/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Object types 3 | --- 4 | 5 | This is a list of common object types shared between the PWA-Buildpack modules. 6 | 7 | ## `LocalProjectLocation` 8 | 9 | | Property: Type | Description | 10 | | ---------------- | ---------------------------------------------------------------------------- | 11 | | `root: string` | The absolute path of the project's root directory on the working filesystem. | 12 | | `output: string` | The directory where webpack should output any built assets. | 13 | | `assets: string` | The directory where any assets not explicityl build by webpack is found. | 14 | {:style="table-layout:auto"} 15 | 16 | ### Output location 17 | 18 | If the value for `LocalProjectLocation.output` is relative, the location is resolved from `root`. -------------------------------------------------------------------------------- /src/pwa-buildpack/reference/pwa-dev-server/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: PWADevServer 3 | --- 4 | 5 | A utility for configuring a development OS and a `webpack-dev-server` for PWA development. 6 | 7 | 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. 8 | 9 | PWA development requires the following: 10 | 11 | * A *secure* and *trusted* host for ServiceWorker operations 12 | * A *unique* host to prevent ServiceWorker collisions 13 | * A customize-able way to proxy backend request to a Magento 2 backing store 14 | 15 | PWADevServer performs the following during setup: 16 | 17 | * Creates and caches a custom local hostname for the current theme 18 | * Adds the custom local hostname to `/etc/hosts` 19 | *(requires elevated permissions, so you may be asked for a password)* 20 | * Creates and caches an SSL certificate for the custom local hostname 21 | * Adds the certificate to the OS-level keychain for browser trust 22 | *(requires elevated permissions, so you may be asked for a password)* 23 | * Customizes the `webpack-dev-server` instance to: 24 | * Proxy all asset requests not managed by webpack to the Magento store 25 | * Emulate the public path settings of the Magento store 26 | * Automatically switch domain names in HTML attributes 27 | * Debug or disable ServiceWorkers 28 | 29 | ## API 30 | 31 | ### `configure(options)` 32 | 33 | #### Parameters 34 | 35 | * `options: PWADevServerOptions` - Configuration object for the PWADevserver module 36 | 37 | The `PWADevServerOptions` object contains the following properties: 38 | 39 | | Property: Type | Description | 40 | | -------------------------------- | ---------------------------------------------------------------------------------------------------------------- | 41 | | `id: string` | **Required.** A [unique ID] for this project. | 42 | | `publicPath: string` | **Required.** The public path to the theme assets in the backend server. | 43 | | `backendDomain: string` | **Required.** The URL of the backend store. | 44 | | `paths:`[`LocalProjectLocation`] | **Required.** Describes the location of the public static assets directory and where to deploy JavaScript files. | 45 | | `serviceWorkerFileName: string` | **Required.** The name of the ServiceWorker file this theme creates, such as `sw.js`. | 46 | | `changeOrigin: boolean` | **Experimental.** Toggles the [change origin feature]. Defaults to `false`. | 47 | {:style="table-layout:auto"} 48 | 49 | **Return:** 50 | 51 | A [Promise] configuration type for webpack. 52 | 53 | {: .bs-callout .bs-callout-info} 54 | **Note:** 55 | `PWADevServer.configure()` is asynchronous. 56 | 57 | 58 | ## Example 59 | 60 | In `webpack.config.js`: 61 | 62 | ``` js 63 | const path = require('path'); 64 | const buildpack = require('@magento/pwa-buildpack'); 65 | const PWADevServer = buildpack.Webpack.PWADevServer; 66 | 67 | module.exports = async env => { 68 | const config { 69 | /* webpack entry, output, rules, etc */ 70 | 71 | devServer: await PWADevServer.configure({ 72 | publicPath: '/pub/static/frontend/Vendor/theme/en_US/', 73 | backendDomain: 'https://magento2.localdomain', 74 | serviceWorkerFileName: 'sw.js', 75 | paths: { 76 | output: path.resolve(__dirname, 'web/js'), 77 | assets: path.resolve(__dirname, 'web') 78 | }, 79 | id: 'magento-venia' 80 | }) 81 | }; 82 | 83 | config.output.publicPath = config.devServer.publicPath; 84 | 85 | return config; 86 | } 87 | ``` 88 | 89 | {: .bs-callout .bs-callout-info} 90 | **Note:** 91 | The example provided uses the newer, cleaner `async/await` syntax instead of using Promises directly 92 | 93 | {: .bs-callout .bs-callout-info} 94 | **Note:** 95 | The emitted `devServer` object may have a custom `publicPath`. 96 | To get the best performance from the ServiceWorker, set `config.output.publicpath` to the `publicPath` value once the `devServer` is created but before creating a ServiceWorker plugin. 97 | 98 | 99 | ## Choosing an ID 100 | 101 | The `PWADevServerOptions.id` property is used to create the dev domain name. 102 | We recommend using the theme name for this value, but you can use any domain-name-safe string. 103 | 104 | If you are developing several copies of a theme simultaneously, use this ID to distinguish them in the internal tooling. 105 | 106 | ## Change origin feature 107 | 108 | The `PWADevServerOptions.changeOrigin` property toggles an experimental feature that tries to parse HTML responses from the proxied Magento backend and replaces its domain name with the dev server domain name. 109 | 110 | [change origin feature]: #change-origin-feature 111 | [unique ID]: #choosing-an-id 112 | [`devServer`]: https://webpack.js.org/configuration/dev-server/ 113 | [Promise]: https://webpack.js.org/configuration/configuration-types/#exporting-a-promise 114 | [`LocalProjectLocation`]: {{ site.baseurl }}{%link pwa-buildpack/reference/object-types/index.md %}#localprojectlocation -------------------------------------------------------------------------------- /src/pwa-buildpack/reference/root-components-plugin/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: MagentoRootComponentsPlugin 3 | --- 4 | 5 | This plugin creates [unique chunks] for each Root Component in a Magento PWA theme and extension. 6 | 7 | For example, given a `RootComponents` directory in a theme with the following structure: 8 | 9 | ``` sh 10 | ├── Page1 11 | │ └── index.js 12 | ├── Page2 13 | │ └── index.js 14 | └── Page3 15 | └── index.js 16 | ``` 17 | 18 | The plugin creates unique chunks for `Page1`, `Page2`, and `Page3`. 19 | Further webpack optimization techiniques, such as [`CommonsChunkPlugin`], can be applied as usual. 20 | 21 | ## Example usage 22 | 23 | ``` javascript 24 | // webpack.config.js 25 | 26 | const path = require('path'); 27 | const { MagentoRootComponentsPlugin } = require('@magento/pwa-buildpack'); 28 | 29 | module.exports = { 30 | entry: { 31 | main: path.join(__dirname, 'src') 32 | }, 33 | output: { 34 | path: path.join(__dirname, 'dist'), 35 | filename: '[name].js', 36 | chunkFilename: '[name].chunk.js' 37 | }, 38 | plugins: [ 39 | new MagentoRootComponentsPlugin({ 40 | rootComponentsDirs: [path.join(__dirname, 'src/RootComponents')], // optional 41 | manifestFileName: 'roots-manifest.json' // optional 42 | }) 43 | ] 44 | }; 45 | ``` 46 | 47 | [unique chunks]: https://webpack.js.org/guides/code-splitting/ 48 | [`CommonsChunkPlugin`]: https://webpack.js.org/plugins/commons-chunk-plugin/ -------------------------------------------------------------------------------- /src/pwa-buildpack/reference/serviceworker-plugin/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ServiceWorkerPlugin 3 | --- 4 | 5 | A webpack plugin for configuring a ServiceWorker for different PWA development scenarios. 6 | 7 | This plugin is a wrapper around the [Google Workbox Webpack Plugin]. 8 | It generates a caching ServiceWorker based on assets emitted by webpack. 9 | 10 | The following configurations are available for this plugin: 11 | 12 | * **normal development** - the ServiceWorker is disabled 13 | * **service worker debugging** - the ServiceWorker and hot-reloading are enabled. 14 | 15 | ## API 16 | 17 | ### `ServiceWorker(options)` 18 | 19 | Plugin constructor for the `ServiceWorkerPlugin` class. 20 | 21 | #### Parameters 22 | 23 | * **`options: PluginOptions`** - Configuration object for the ServiceWorkerPlugin 24 | 25 | The `PluginOptions` object contains the following properties: 26 | 27 | | Property: Type | Description | 28 | | --------------------------------------- | ---------------------------------------------------------------------------------- | 29 | | `env:`[`EnvironmentObject`] | **Required.** An object that represents the current environment. | 30 | | `paths:`[`LocalProjectLocation`] | **Required.** Configuration object that describes where public assets are located. | 31 | | `enableServiceWorkerDebugging: boolean` | Toggles [service worker debugging]. | 32 | | `serviceWorkerFilename: string` | **Required.** The name of the ServiceWorker file this theme creates. | 33 | | `runtimeCacheAssetPath: string` | A remote URL or root path to assets the ServiceWorker should cache during runtime. | 34 | {:style="table-layout:auto"} 35 | 36 | The `EnvironmentObject` contains the following properties: 37 | {:#environmentobject} 38 | 39 | | Property: Type | Description | 40 | | --------------- | ------------------------------------------ | 41 | | `phase: string` | Must be **development** or **production**. | 42 | {:style="table-layout:auto"} 43 | 44 | ## Example 45 | 46 | In `webpack.config.js`: 47 | 48 | ``` js 49 | const path = require('path'); 50 | const buildpack = require('@magento/pwa-buildpack'); 51 | const ServiceWorkerPlugin = buildpack.Webpack.ServiceWorkerPlugin; 52 | 53 | module.exports = async env => { 54 | const config = { 55 | /* webpack config, i.e. entry, output, etc. */ 56 | plugins: [ 57 | /* other plugins */ 58 | new ServiceWorkerPlugin({ 59 | env: { 60 | mode: 'development' 61 | }, 62 | 63 | paths: { 64 | output: path.resolve(__dirname, 'web/js'), 65 | assets: path.resolve(__dirname, 'web') 66 | }, 67 | enableServiceWorkerDebugging: true, 68 | serviceWorkerFileName: 'sw.js', 69 | runtimeCacheAssetPath: 'https://cdn.url' 70 | }) 71 | ] 72 | }; 73 | 74 | return config; 75 | 76 | }; 77 | 78 | ``` 79 | 80 | ## Service worker debugging 81 | 82 | When `PluginOptions.enableServiceWorkerDebugging` is set to `true`, hot reloading is enabled and the ServiceWorker is active in the document root. 83 | 84 | When this value is set to `false`, the ServiceWorker is disabled to prevent cache interruptions when hot reloading assets. 85 | 86 | 87 | [Google Workbox Webpack Plugin]: https://developers.google.com/web/tools/workbox/guides/generate-service-worker/ 88 | [`LocalProjectLocation`]: {{ site.baseurl }}{%link pwa-buildpack/reference/object-types/index.md %}#localprojectlocation 89 | [`EnvironmentObject`]: #environmentobject 90 | [service worker debugging]: #service-worker-debugging -------------------------------------------------------------------------------- /src/pwa-buildpack/troubleshooting/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Troubleshooting 3 | --- 4 | 5 | This page lists solutions for common issues reported by community members for the PWA Buildpack project. 6 | If you run into any other problems please [create an issue] or let us know in our [Slack channel]. 7 | 8 | To provide more details for your issue, enable verbose console logging. 9 | Instead of `npm start` run the following command to set a debugging environment variable: 10 | 11 | ``` sh 12 | DEBUG=pwa-buildpack:* npm start 13 | ``` 14 | 15 | Paste the result console output into the issue. Thank you! 16 | 17 | ## Common issues 18 | 19 | * [Browser displays "Cannot proxy to " error and the console displays `ENOTFOUND`](#cannot-proxy) 20 | * [Webpack hangs for a long time before beginning compilation](#webpack-hangs) 21 | * [Browser cannot resolve the `.local.pwadev` site](#cannot-resolve-site) 22 | * [Browser does not trust the generated SSL certificate](#untrusted-ssl-cert) 23 | 24 | ## Resolutions 25 | 26 | **Browser displays "Cannot proxy to " error and the console displays `ENOTFOUND`**{:#cannot-proxy} 27 | 28 | Make sure your Magento store loads in more than one browser. 29 | 30 | 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. 31 | 32 | **Webpack hangs for a long time before beginning compilation**{:#webpack-hangs} 33 | 34 | You may have an old version of the `pwa-buildpack` project. 35 | Update your project using the following command: 36 | 37 | ``` sh 38 | npm upgrade 39 | ``` 40 | 41 | Make sure you have a current version of openssl on your system using the following command: 42 | 43 | ``` sh 44 | openssl version 45 | ``` 46 | 47 | The version should be 1.0 or above (or LibreSSL 2, in the case of OSX High Sierra.) 48 | 49 | You can install higher versions of OpenSSL with [Homebrew] on OSX, [Chocolatey] on Windows, or your Linux distribution's package manager. 50 | 51 | **Browser cannot resolve the `.local.pwadev` site**{:#cannot-resolve-site} 52 | 53 | Something has edited your hostfile, and the local PWA Studio dev database is out of sync. 54 | Regenerate the database file by deleting it with the following command: 55 | ``` sh 56 | rm ~/.config/pwa-buildpack.db 57 | ``` 58 | 59 | **Browser does not trust the generated SSL certificate**{:#untrusted-ssl-cert} 60 | 61 | Make sure you have a current version of openssl on your system using the following command: 62 | 63 | ``` sh 64 | openssl version 65 | ``` 66 | 67 | The version should be 1.0 or above (or LibreSSL 2, in the case of OSX High Sierra.) 68 | 69 | You can install higher versions of OpenSSL with [Homebrew] on OSX, [Chocolatey] on Windows, or your Linux distribution's package manager. 70 | 71 | [create an issue]: https://github.com/magento-research/pwa-buildpack/issues 72 | [Slack channel]: https://magentocommeng.slack.com/messages/C71HNKYS2/team/UAFV915FB/ 73 | [Homebrew]: https://brew.sh/ 74 | [Chocolatey]: https://chocolatey.org/ -------------------------------------------------------------------------------- /src/reference/ui-components/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md %} -------------------------------------------------------------------------------- /src/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: search 3 | title: Search Results 4 | menu_title: Search 5 | permalink: /search/ 6 | --- 7 | -------------------------------------------------------------------------------- /src/static/fonts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magento-research/pwa-devdocs/6191acca66f83df2eb541907df4193d69701bc07/src/static/fonts/.gitkeep -------------------------------------------------------------------------------- /src/static/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magento-research/pwa-devdocs/6191acca66f83df2eb541907df4193d69701bc07/src/static/images/.gitkeep -------------------------------------------------------------------------------- /src/static/images/contribute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magento-research/pwa-devdocs/6191acca66f83df2eb541907df4193d69701bc07/src/static/images/contribute.png -------------------------------------------------------------------------------- /src/static/images/getting-started.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magento-research/pwa-devdocs/6191acca66f83df2eb541907df4193d69701bc07/src/static/images/getting-started.png -------------------------------------------------------------------------------- /src/static/images/repos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magento-research/pwa-devdocs/6191acca66f83df2eb541907df4193d69701bc07/src/static/images/repos.png -------------------------------------------------------------------------------- /src/static/images/what-is-pwa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magento-research/pwa-devdocs/6191acca66f83df2eb541907df4193d69701bc07/src/static/images/what-is-pwa.png -------------------------------------------------------------------------------- /src/technologies/basic-concepts/app-shell/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md issue=8 %} 6 | -------------------------------------------------------------------------------- /src/technologies/basic-concepts/client-state-reducers-actions/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md issue=12 %} 6 | -------------------------------------------------------------------------------- /src/technologies/basic-concepts/component-data-binding/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md issue=9 %} 6 | -------------------------------------------------------------------------------- /src/technologies/basic-concepts/container-extensibility/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Container extensibility 3 | --- 4 | 5 | A **Container** is an HTML element that contains 0 or more [`ContainerChild`] components. 6 | It acts as the target for [`magento-loader-layout`] operations. 7 | 8 | ## Creating a Container 9 | 10 | To create a Container in a React component, add a `data-mid` prop to any DOM element, such as a `div`, `span`, etc. 11 | The value of the `data-mid` prop *must* be a literal string value. 12 | It cannot be a dynamic value or a variable reference. 13 | 14 | **Example:** 15 | ``` jsx 16 |
    17 | ``` 18 | 19 | **Note:** 20 | *Composite components, such as a class or function, cannot be used as a Container.* 21 | 22 | 23 | ## Extending a Container 24 | 25 | [`ContainerChild`] components are the only allowed children of a Container. 26 | This makes it possible to extend a Container using the `magento-loader-layout` tool from the [PWA Buildpack]. 27 | 28 | `magento-loader-layout` supports the following operations: 29 | 30 | * Remove a container 31 | * Remove a child component in a container 32 | * Insert content before a child component in a container 33 | * Insert content after a child component in a container 34 | 35 | See: [Code examples] 36 | 37 | [`ContainerChild`]: {{ site.baseurl }}{% link peregrine/reference/container-child/index.md %} 38 | [`magento-loader-layout`]: {{ site.baseurl }}{% link pwa-buildpack/reference/layout-loader/index.md %} 39 | [PWA Buildpack]: {{ site.baseurl }}{% link pwa-buildpack/index.md %} 40 | [Code examples]: {{ site.baseurl }}{% link pwa-buildpack/reference/layout-loader/index.md %}#examples -------------------------------------------------------------------------------- /src/technologies/basic-concepts/critical-path/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md issue=18 %} 6 | -------------------------------------------------------------------------------- /src/technologies/basic-concepts/css-modules/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md issue=11 %} 6 | -------------------------------------------------------------------------------- /src/technologies/basic-concepts/graphql/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md issue=10 %} 6 | -------------------------------------------------------------------------------- /src/technologies/basic-concepts/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Basic Concepts 3 | --- 4 | 5 | The tools provided by the Magento PWA Studio project allows you to create websites that are fast, mobile-friendly, and reliable. 6 | This topic lists the basic concepts you need to know to work with the Magento PWA Studio tools. 7 | 8 | ## Application shell 9 | 10 | An application shell provides the basic user interface structure for a progressive web application. 11 | [ *[Help write this topic][Application shell]* ] 12 | 13 | ## Service worker 14 | 15 | A service worker is a script that runs in the background. 16 | Progressive web applications use service workers for caching and resource retrieval. 17 | [ *[Help write this topic][Service Worker]* ] 18 | 19 | ## Component data binding 20 | 21 | Component data binding refers to the way data flows between the source and a UI component. 22 | Progressive web applications use data binding patterns to connect dynamic data with the user interface. 23 | [ *[Help write this topic][Component data binding]* ] 24 | 25 | ## GraphQL 26 | 27 | GraphQL is a specification for a data query language client side and a service layer on the server side. 28 | It is used to request and push data in a progressive web application. 29 | [ *[Help write this topic][GraphQL]* ] 30 | 31 | ## CSS modules 32 | 33 | CSS modules are modular and reusable CSS styles. 34 | This allows you to develop components with styles that do not conflict with external style definitions. 35 | [ *[Help write this topic][CSS modules]* ] 36 | 37 | ## Client state, reducers, and actions 38 | 39 | Client state, reducers, and actions are [Redux] concepts used to manage and handle the state of a web application. 40 | [ *[Help write this topic][Client state, reducers, and actions]* ] 41 | 42 | ## Loading and offline states 43 | 44 | Loading and offline are both states that must be handled by progressive web applications. 45 | [ *[Help write this topic][Loading and offline states]* ] 46 | 47 | ## Container extensibility 48 | 49 | Writing extensible containers allow others to re-use and alter your container without modifying the source. 50 | 51 | For more information, see [Container extensibility]. 52 | 53 | ## Performance patterns 54 | 55 | Performance is an important feature for a progressive web app. 56 | There are many strategies and patterns available to help boost the performance of a PWA. 57 | [ *[Help write this topic][Performance patterns]* ] 58 | 59 | ## Root components and routing 60 | 61 | The root component of an application is the DOM node under which all other nodes are managed by React. 62 | Routing is the ability to map a URL pattern to the appropriate handler. 63 | [ *[Help write this topic][Performance patterns]* ] 64 | 65 | ## Critical path 66 | 67 | The critical path for rendering refers to the steps the browser takes to process the HTML, CSS, and JavaScript files to display a website. 68 | Optimizing the critical path is important to get the best performance out of a progressive web application. 69 | [ *[Help write this topic][Critical path]* ] 70 | 71 | [Redux]: https://redux.js.org/introduction/core-concepts 72 | 73 | [Application shell]: {{ site.data.vars.repo }}/issues/8 74 | [Service worker]: {{ site.data.vars.repo }}/issues/14 75 | [Component data binding]: {{ site.data.vars.repo }}/issues/9 76 | [GraphQL]: {{ site.data.vars.repo }}/issues/10 77 | [CSS modules]: {{ site.data.vars.repo }}/issues/11 78 | [Client state, reducers, and actions]: {{ site.data.vars.repo }}/issues/12 79 | [Loading and offline states]: {{ site.data.vars.repo }}/issues/13 80 | [Container extensibility]: {{ site.baseurl }}{%link technologies/basic-concepts/container-extensibility/index.md %} 81 | [Performance patterns]: {{ site.data.vars.repo }}/issues/16 82 | [Root components and routing]: {{ site.data.vars.repo }}/issues/17 83 | [Critical path]: {{ site.data.vars.repo }}/issues/18 -------------------------------------------------------------------------------- /src/technologies/basic-concepts/loading-offline-states/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md issue=13 %} 6 | -------------------------------------------------------------------------------- /src/technologies/basic-concepts/performance-patterns/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md issue=16 %} 6 | -------------------------------------------------------------------------------- /src/technologies/basic-concepts/root-components-routing/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md issue=17 %} 6 | -------------------------------------------------------------------------------- /src/technologies/basic-concepts/service-worker/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md issue=14 %} 6 | -------------------------------------------------------------------------------- /src/technologies/overview/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Overview 3 | --- 4 | 5 | This page provides a brief description of a Progressive Web App (PWA) and its relationship to the Magento PWA Studio project. 6 | 7 | ## What is a Progressive Web App 8 | 9 | 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. 10 | 11 | The following features define a basic PWA website: 12 | 13 | * **Fast** - PWA sites use a variety of performance optimization strategies to provide a responsive experience or load content fast, even on slow networks. 14 | * **Secure** - PWA sites use HTTPS connections for enhanced security. 15 | * **Responsive** - PWA sites implement responsive design strategies to provide a consistent experience on desktops, tablets, and mobile devices. 16 | * **Cross-browser compatible** - PWA sites work equally well on all modern browsers, such as Chrome, Edge, Firefox, Safari. 17 | * **Offline Mode** - PWA sites cache content to ensure that some content can be served when a user is offline. 18 | * **Mobile "Install"** - Mobile users can add PWA sites to their home screens and even recieve Push notifications from the site. 19 | * **Shareable content** - Each page in a PWA site has a unique URL that can be shared with other apps or social media. 20 | 21 | ## What is the Magento PWA Studio project 22 | 23 | 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. 24 | It uses modern [tools and libraries] to create a build system and framework that adheres to the Magento principle of extensibility. 25 | 26 | The Magento PWA Studio project provides the following tools: 27 | 28 | * **[pwa-buildpack]** - Contains the main build and development tools for a Magento PWA. 29 | * **[peregrine]** - Contains a collection of UI components for a Magento PWA. 30 | * **[Venia theme]** - A proof of concept Magento 2 theme built using the PWA Studio tools. 31 | 32 | [tools and libraries]: {{ site.baseurl }}{% link technologies/tools-libraries/index.md %} 33 | [pwa-buildpack]: {{ site.baseurl }}{% link pwa-buildpack/index.md %} 34 | [peregrine]: {{ site.baseurl }}{% link peregrine/index.md %} 35 | [Venia theme]: {{ site.baseurl }}{% link venia-pwa-concept/index.md %} -------------------------------------------------------------------------------- /src/technologies/tools-libraries/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tools and libraries 3 | --- 4 | 5 | To work with the utilities provided by the Magento PWA Studio project, you should be familiar with the tools and libraries described on this page. 6 | 7 | ## webpack 8 | 9 | [webpack] is a configuration-driven asset bundler and optimizer for JavaScript applications. 10 | 11 | webpack's primary function is to create one or more bundles from the dependencies in your project's modules. 12 | webpack is also able to transform, package, or optimize resources and assets using plugins. 13 | This allows you to extend webpack's functionality beyond JavaScript bundling. 14 | 15 | The [pwa-buildpack] tool uses webpack to set up your development environment. 16 | It uses your local environment variables and the configuration in the `webpack.config.js` file to generate a development environment for your system. 17 | 18 | ## React 19 | 20 | [React] officially describes itself as a *JavaScript library for building user interfaces*. 21 | The library provides the following features that make PWA development easier: 22 | 23 | * **Simple** - The React library does one thing: build a user interface. 24 | It does this without making assumptions about the underlying technology stack. 25 | This flexibility gives you the freedom to choose the appropriate solutions for the rest of your project. 26 | 27 | * **Declarative** - Creating a complex user interface is difficult when working directly with the DOM API. 28 | React allows you to describe how your interface should look for a specific application state, and 29 | the library takes care of rendering the UI correctly when the state changes. 30 | 31 | * **Modular** - React encourages developers to create modular and reusable UI components. 32 | Taking a modular approach to development makes your code easier to debug and maintain. 33 | 34 | ## Redux 35 | 36 | [Redux] is a JavaScript library used for managing state in a web application. 37 | 38 | It provides a global store object that holds application state that multiple components depend on. 39 | Components that plug into the store have direct access to the specific state data they need. 40 | 41 | This library is often paired with React to alleviate the problem of passing data down multiple component layers. 42 | 43 | ## GraphQL 44 | 45 | [GraphQL] is a specification for a data query language on the client side and a service layer on the server side. 46 | It is often seen as an alternative to using [REST] endpoints. 47 | 48 | One of the main advantages GraphQL has over REST is that a single GraphQL endpoint can accomodate requests for any combination of X, Y, and Z pieces of data, 49 | whereas REST requires specialized endpoints for different data request combinations. 50 | Unlike REST, which can require multiple server requests to aggregate data, 51 | a single GraphQL request returns only the data needed and nothing more. 52 | 53 | Performance is an important metric for PWAs. 54 | Using GraphQL improves this by reducing the number of server calls and the amount of data returned. 55 | 56 | 57 | [webpack]: https://webpack.js.org/ 58 | [pwa-buildpack]: {{ site.baseurl }}{% link pwa-buildpack/index.md %} 59 | [React]: https://reactjs.org/ 60 | [Redux]: https://redux.js.org/ 61 | [GraphQL]: https://graphql.org/ 62 | [REST]: https://en.wikipedia.org/wiki/REST 63 | -------------------------------------------------------------------------------- /src/tutorials/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | --- 4 | 5 | {% include content-not-available.md %} -------------------------------------------------------------------------------- /src/venia-pwa-concept/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Venia Theme (Concept) 3 | --- 4 | 5 | The Venia theme is a proof-of-concept Magento theme built using [PWA Buildpack] tools and [Peregrine] components. 6 | In its current, experimental state, the theme contains examples for Product Details and Category pages. 7 | 8 | ## Setup development environment 9 | 10 | Follow the directions on the [Setup page] to set up development environment for the Venia Theme. 11 | 12 | ## Module and theme directories 13 | 14 | The [`venia-pwa-concept`] project itself contains a module and theme. 15 | 16 | ### PWA module 17 | 18 | The `module` directory contains the code for a helper module for all Magento PWA Studio themes. 19 | This module provides the following server-side functionality: 20 | 21 | * Renders an app shell with the proper meta information in the `` of each page. 22 | * Assigns a `RootComponent` to an entity or group of entities without requiring a deployment. (**In development**) 23 | * Embeds GraphQL payloads into the initial server render without requiring a round trip to the API after the web app has initialized on the client side. (**In development**) 24 | 25 | ### Venia theme 26 | 27 | The `theme-frontend-venia` directory contains the code for the Venia theme itself. 28 | This directory contains the files required for a Magento theme along with files that define pages and components. 29 | 30 | ## Contribute 31 | 32 | Visit the [`venia-pwa-concept`] package in the PWA Studio repository to contribute to the development of this project. 33 | 34 | [`venia-pwa-concept`]: https://github.com/magento-research/pwa-studio/tree/master/packages/venia-concept 35 | [PWA Buildpack]: {{ site.baseurl }}{% link pwa-buildpack/index.md %} 36 | [Peregrine]: {{ site.baseurl }}{% link peregrine/index.md %} 37 | 38 | [Setup page]: {{ site.baseurl }}{% link venia-pwa-concept/setup/index.md %} -------------------------------------------------------------------------------- /src/venia-pwa-concept/setup/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setup 3 | --- 4 | 5 | Follow the instructions on this page to setup the [Venia PWA concept theme] for Magento 2. 6 | At the end of this tutorial, you will have the Venia theme project installed in Magento 2 and a local development environment set up. 7 | 8 | If you experience problems with the project setup, see [Troubleshooting] in the PWA Buildpack section. 9 | 10 | ## Prerequisites 11 | 12 | * A local development instance of Magento 2.3 or above. 13 | * [Node Package Manager] (NPM) 14 | * [NodeJS 8.x LTS] 15 | 16 | ## Clone repository 17 | 18 | Clone the [PWA Studio] repository into your development environment. 19 | 20 | ``` sh 21 | git clone git@github.com:magento-research/pwa-studio.git 22 | ``` 23 | 24 | {: .bs-callout .bs-callout-info} 25 | **Note:** 26 | For this tutorial, the project location is the `/Users/magedev/pwa-studio` directory. 27 | 28 | ### Vagrant Box instructions 29 | 30 | If you are using a virtual machine, make sure it can access the new project directory and runs Magento 2.3. 31 | 32 | For example, if you are using the [Vagrant Box for Magento 2 developers], use the following steps to add a synced folder to the virtual machine and configure it to use Magento 2.3. 33 | 34 |
    35 | Show steps 36 | 37 | {: .bs-callout .bs-callout-tip} 38 | **Tip:** 39 | If you clone the PWA Studio project repo into the `magento2ce` directory of the Vagrant project, the project folder will already be visible to the Vagrant box and you can skip ahead to Step 3. 40 | 41 | 1. In the Vagrant box project directory, open the `Vagrantfile` and locate the following line: 42 | ``` 43 | config.vm.synced_folder '.', '/vagrant', disabled: true 44 | ``` 45 | 2. Above this line, add the following entry (substituting the project directory path with your own): 46 | ``` 47 | config.vm.synced_folder '/Users/magedev/pwa-studio', '/Users/magedev/pwa-studio', type: "nfs", create: true 48 | ``` 49 | 3. If your environment does not already use Magento 2.3, copy `etc/config.yaml.dist` as `etc/config.yml` and update the following line: 50 | ``` yml 51 | ce: "git@github.com:magento/magento2.git" 52 | ``` 53 | to 54 | ``` yml 55 | ce: "git@github.com:magento/magento2.git::2.3-develop" 56 | ``` 57 | 4. In that same file, update the PHP version to 7.1 by updating the following line: 58 | ``` yml 59 | php_version: "7.0" 60 | ``` 61 | to 62 | ``` yml 63 | php_version: "7.1" 64 | ``` 65 | 5. Init or reset the Vagrant environment: 66 | ``` 67 | bash init-project 68 | ``` 69 | OR 70 | ``` 71 | bash init_project.sh -f 72 | ``` 73 |
    74 | 75 | ## Install PWA Studio dependencies 76 | 77 | In the PWA Studio project's root directory, run the following command to install the project dependencies: 78 | 79 | ``` sh 80 | npm install 81 | ``` 82 | 83 | ## Link module 84 | 85 | Navigate to your Magento installation's `app/code/Magento` directory and create a `Pwa` symlink folder linking to the project's `module` directory. 86 | 87 | **Example command:** 88 | ``` sh 89 | ln -s /Users/magedev/pwa-studio/packages/pwa-module Pwa 90 | ``` 91 | 92 | ### Enable and install 93 | 94 | Navigate to your Magento installation's root director and run the following command to enable the module: 95 | 96 | ``` sh 97 | bin/magento module:enable Magento_Pwa 98 | ``` 99 | 100 | Install the module using the following command: 101 | ``` sh 102 | bin/magento setup:upgrade 103 | ``` 104 | 105 | ## Link theme directory 106 | 107 | Navigate to your Magento installation's `app/design/frontend/Magento` directory and create a `venia` symlink folder linking to the project's `theme-frontend-venia` directory. 108 | 109 | **Example command:** 110 | ``` sh 111 | ln -s /Users/magedev/pwa-studio/packages/venia-concept venia 112 | ``` 113 | 114 | ## Activate the Venia theme 115 | 116 | Browse to the Admin section of your Magento store and configure it to use the **Magento Venia** theme. 117 | You can find this configuration using the **Configuration** link in the **Content** tab. 118 | 119 | ## Set environment variables 120 | 121 | Under the Venia project's `theme-frontend-venia` directory, copy `.env.dist` into a new `.env` file and update the variables with the URL to your Magento development store. 122 | 123 | ## Start the development server 124 | 125 | Use the following command to start the development server: 126 | 127 | ``` sh 128 | npm start 129 | ``` 130 | 131 | After the development server is up and running, look for a similar line in the terminal output (the port will differ for your instance): 132 | 133 | ``` sh 134 | Project is running at https://magento-venia.local.pwadev:8000/ 135 | ``` 136 | 137 | This is the new address for your PWA frontend. 138 | You can still use the old address to access the Admin section of Magento, but 139 | for PWA development on the frontend, use this new address. 140 | 141 | {: .bs-callout .bs-callout-info} 142 | **Note:** 143 | This project is still in development and only supports the `/home` route. 144 | 145 | Congratulations! You have set up your development environment for the Venia theme project. 146 | 147 | [Venia PWA concept theme]: https://github.com/magento-research/pwa-studio/tree/master/packages/venia-concept 148 | [Node Package Manager]: https://www.npmjs.com/ 149 | [NodeJS 8.x LTS]: https://nodejs.org/en/ 150 | [Vagrant Box for Magento 2 developers]: https://github.com/paliarush/magento2-vagrant-for-developers 151 | [Troubleshooting]: {{ site.baseurl }}{% link pwa-buildpack/troubleshooting/index.md %} 152 | [PWA Studio]: https://github.com/magento-research/pwa-studio 153 | --------------------------------------------------------------------------------