diff --git a/pwa-devdocs/.gitignore b/pwa-devdocs/.gitignore deleted file mode 100644 index de1f69ecae..0000000000 --- a/pwa-devdocs/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -_site/ -.sass-cache/ -.jekyll-metadata -.jekyll-cache - -node_modules -src/builds - - - -*.tar - -*.log - -**/auto-generated diff --git a/pwa-devdocs/CHANGELOG.md b/pwa-devdocs/CHANGELOG.md deleted file mode 100644 index 8a2328626c..0000000000 --- a/pwa-devdocs/CHANGELOG.md +++ /dev/null @@ -1,12 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - - -## 1.0.1 (2018-08-13) - - -### Bug Fixes - -* **dev:** merge 'assets' and 'output' paths ([36d8157](https://github.com/magento/pwa-studio/commit/36d8157)) diff --git a/pwa-devdocs/Gemfile b/pwa-devdocs/Gemfile deleted file mode 100644 index 396bd9146d..0000000000 --- a/pwa-devdocs/Gemfile +++ /dev/null @@ -1,5 +0,0 @@ -source 'https://rubygems.org' - -gem 'jekyll-redirect-from' - -gem 'devdocs', :git => 'https://github.com/magento-devdocs/devdocs-theme.git' diff --git a/pwa-devdocs/Gemfile.lock b/pwa-devdocs/Gemfile.lock deleted file mode 100644 index 65080973f3..0000000000 --- a/pwa-devdocs/Gemfile.lock +++ /dev/null @@ -1,77 +0,0 @@ -GIT - remote: https://github.com/magento-devdocs/devdocs-theme.git - revision: ab43ba7fd03f5ff5021e0542a86ed6e5c13793fe - specs: - devdocs (9) - jekyll (>= 4.0) - -GEM - remote: https://rubygems.org/ - specs: - addressable (2.7.0) - public_suffix (>= 2.0.2, < 5.0) - colorator (1.1.0) - concurrent-ruby (1.1.6) - em-websocket (0.5.1) - eventmachine (>= 0.12.9) - http_parser.rb (~> 0.6.0) - eventmachine (1.2.7) - ffi (1.12.2) - forwardable-extended (2.6.0) - http_parser.rb (0.6.0) - i18n (1.8.2) - concurrent-ruby (~> 1.0) - jekyll (4.0.1) - addressable (~> 2.4) - colorator (~> 1.0) - em-websocket (~> 0.5) - i18n (>= 0.9.5, < 2) - jekyll-sass-converter (~> 2.0) - jekyll-watch (~> 2.0) - kramdown (~> 2.1) - kramdown-parser-gfm (~> 1.0) - liquid (~> 4.0) - mercenary (~> 0.3.3) - pathutil (~> 0.9) - rouge (~> 3.0) - safe_yaml (~> 1.0) - terminal-table (~> 1.8) - jekyll-redirect-from (0.16.0) - jekyll (>= 3.3, < 5.0) - jekyll-sass-converter (2.1.0) - sassc (> 2.0.1, < 3.0) - jekyll-watch (2.2.1) - listen (~> 3.0) - kramdown (2.2.1) - rexml - kramdown-parser-gfm (1.1.0) - kramdown (~> 2.0) - liquid (4.0.3) - listen (3.2.1) - rb-fsevent (~> 0.10, >= 0.10.3) - rb-inotify (~> 0.9, >= 0.9.10) - mercenary (0.3.6) - pathutil (0.16.2) - forwardable-extended (~> 2.6) - public_suffix (4.0.5) - rb-fsevent (0.10.4) - rb-inotify (0.10.1) - ffi (~> 1.0) - rexml (3.2.4) - rouge (3.19.0) - safe_yaml (1.0.5) - sassc (2.3.0) - ffi (~> 1.9) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) - unicode-display_width (1.7.0) - -PLATFORMS - ruby - -DEPENDENCIES - devdocs! - jekyll-redirect-from - -BUNDLED WITH - 2.1.4 diff --git a/pwa-devdocs/LICENSE.txt b/pwa-devdocs/LICENSE.txt deleted file mode 100644 index 578b438fb8..0000000000 --- a/pwa-devdocs/LICENSE.txt +++ /dev/null @@ -1,49 +0,0 @@ - - -Open Software License ("OSL") v. 3.0 - -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: - -Licensed under the Open Software License version 3.0 - - 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: - - 1. to reproduce the Original Work in copies, either alone or as part of a collective work; - - 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; - - 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; - - 4. to perform the Original Work publicly; and - - 5. to display the Original Work publicly. - - 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. - - 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. - - 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. - - 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). - - 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. - - 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. - - 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. - - 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). - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. diff --git a/pwa-devdocs/README.md b/pwa-devdocs/README.md deleted file mode 100644 index a99ba48639..0000000000 --- a/pwa-devdocs/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# pwa-devdocs - -This is the source code and documentation repository for the PWA Studios [documentation site]. - -The PWA DevDocs site is build using [Jekyll] and hosted using [GitHub Pages]. - -## Getting Started - -Use the following instructions to build a local instance of the documentation. - -### Prerequisites - -- [Git] -- [Node.JS] -- [Ruby] -- [Bundler] -- [npm] - -### Installation - -1. Clone the PWA Studio repository. If you want to contribute, fork the repository and clone from your fork. -2. Change into the PWA Studio project root using the following command: - ``` - cd pwa-studio - ``` -3. Change into the **pwa-devdocs** directory using the following command: - ``` - cd pwa-devdocs - ``` -4. Run the following command to install the required node modules for the project: - ``` - npm install - ``` -5. Run the following command to install the required Ruby libraries: - ``` - bundle install - ``` - -### Build site - -In the **pwa-devdocs** directory, run the following command to build and run the site locally: - -``` -npm start -``` - -If you just want to generate the HTML pages in the `_site` folder, run the following command: - -``` -npm run build -``` - -### Testing - -``` -npm run lint -``` - -This command runs linting on the documentation to make sure it meets our standards. - -To test a single file append the markdown file at the end of the lint command. - -Example: - -``` -npm run lint -- src/technologies/versioning/index.md -``` - -## Contributing - -This is an open source project that welcomes contributors of all skill levels. - -If you want to contribute, please review the [contribution guidelines] and follow our [code of conduct]. - -## License - -This project is licensed under OSL-3.0 - see the [LICENSE.txt] file for details. - -[contribution guidelines]: https://magento.github.io/pwa-studio/technologies/contribute/ -[code of conduct]: https://github.com/magento/pwa-studio/blob/develop/.github/CODE_OF_CONDUCT.md -[license.txt]: LICENSE.txt -[documentation site]: https://pwastudio.io -[node.js]: https://nodejs.org -[ruby]: https://www.ruby-lang.org/ -[bundler]: http://bundler.io/ -[npm]: https://www.npmjs.com/ -[jekyll]: https://jekyllrb.com/ -[github pages]: https://pages.github.com/ -[git]: https://git-scm.com/ diff --git a/pwa-devdocs/_config-production.yml b/pwa-devdocs/_config-production.yml deleted file mode 100644 index 9d010638a5..0000000000 --- a/pwa-devdocs/_config-production.yml +++ /dev/null @@ -1,2 +0,0 @@ -baseurl: /pwa-studio -environment: public diff --git a/pwa-devdocs/_drafts/.gitkeep b/pwa-devdocs/_drafts/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pwa-devdocs/_drafts/docker-setup.md b/pwa-devdocs/_drafts/docker-setup.md deleted file mode 100644 index 0978868b76..0000000000 --- a/pwa-devdocs/_drafts/docker-setup.md +++ /dev/null @@ -1,37 +0,0 @@ -# Run PWA with Docker - -1. Install Docker for your system: https://docs.docker.com/install -2. Clone the repository: - ``` - git clone https://github.com/magento/pwa-studio - ``` - *Note*: Windows users will want to ensure that [shared drives](https://docs.docker.com/docker-for-windows/#shared-drives) are enabled. -3. In the root of the repository, run - ``` - docker/run-docker - ``` -4. Once the script completes, a locally running instance of pwa will be available at `https://pwa-docker.localhost`. - -## Configure a custom domain - -The domain is configurable. Just set `PWA_STUDIO_PUBLIC_PATH` key to the new domain under `docker/.env.docker`, or pass a custom .env file with the `PWA_STUDIO_PUBLIC_PATH` key set. All required fields can be found in `docker/.env.docker`. See how to pass the custom .env file below. - -## Pass custom .env file configuration through cli args (optional) - -To use a custom .env file for configuration, pass it to the `run-docker` script like so: `docker/run-docker -e path-from-project-root`. This file will take the place of the default `.env.docker` file. - -## Service Workers and Hot Reloading - -Service workers are disabled by default when running the `docker/run-docker` script, but they can easily be turned on by changing the default value of `DEV_SERVER_SERVICE_WORKER_ENABLED=false` to `DEV_SERVER_SERVICE_WORKER_ENABLED=true` in `.env.docker`. - -Hot reloading is enabled by default when running the `docker/run-docker` script and automatically refreshes the browser on changes made in the container as well as on the host machine, ie your local file system. - -If service workers are enabled during development, then service worker caching will affect the hot reloading and will require a manual refresh after the cached assets have fully reloaded. - -In order to avoid manual page refreshing and have hot reloading work as expected with service workers enabled, it is recommended for developers to click the `Update on reload` checkbox in the `Service Workers` panel in Chrome developer tools. This feature in Chrome is helpful when developing with service workers because it ensures that the service worker is updated on every page reload and you will see changes immediately, avoiding the service worker cache. - -For more details check out the [dev tools docs](https://bit.ly/2tTGWc0). - -### Hot Reloading is not working - -If you find that hot reloading is not working for you the webpack docs recommend using [polling](https://webpack.js.org/configuration/watch/#watchoptionspoll) as watching does not work with network file systems and machines in VirtualBox. To enable polling, set `DEV_SERVER_WATCH_OPTIONS_USE_POLLING=1` in `.env.docker`. diff --git a/pwa-devdocs/_drafts/graphql-cli-validate-queries/notes.md b/pwa-devdocs/_drafts/graphql-cli-validate-queries/notes.md deleted file mode 100644 index 6814d2f6dd..0000000000 --- a/pwa-devdocs/_drafts/graphql-cli-validate-queries/notes.md +++ /dev/null @@ -1,13 +0,0 @@ -# GraphQL Validation Support - -We created a `graphql-cli` plugin called `validate-magento-pwa-queries` that lives at `packages/graphql-cli-validate-magento-pwa-queries`. - -Venia depends on `graphql-cli` and this `validate-magento-pwa-queries` plugin to do the work of validating the queries, -replacing the need for `validate-queries.js` in `packages/venia-concept/` itself. - -Venia's `package.json` includes a script called `validate-queries` that runs our plugin. - -### New Tools / Dependencies / Further Reading - -* [graphql-config](https://github.com/prisma/graphql-config) -* [graphql-cli](https://github.com/graphql-cli/graphql-cli) diff --git a/pwa-devdocs/_drafts/project-setup/create-configuration-files/index.md b/pwa-devdocs/_drafts/project-setup/create-configuration-files/index.md deleted file mode 100644 index c1c0d98efa..0000000000 --- a/pwa-devdocs/_drafts/project-setup/create-configuration-files/index.md +++ /dev/null @@ -1,267 +0,0 @@ -# :x: :bangbang: THIS DOCUMENT IS DEPRECATED. MUCH OF IT IS OUT OF DATE. USE A SCAFFOLDING GENERATOR INSTEAD OF BUILDING A PROJECT FROM SCRATCH. :bangbang: :x: - ---- -title: Create configuration files ---- - -In the [previous topic], you linked your project to the Magento backend store. -In this topic, you will create the configuration files for your development environment. - -## Create the Babel configuration file - -Create a `.babelrc` file in your theme’s root directory with the following content: - -``` javascript -{ - "plugins": [ - "syntax-jsx", - "transform-class-properties", - "transform-object-rest-spread", - "transform-react-jsx" - ] -} -``` - -This configuration installs the following [Babel] plugins: - -* [`syntax-jsx`] and [`transform-react-jsx`] - Transform [JSX] code into backwards-compatible JavaScript. - JSX allows you to write React components using a syntax structure similar to HTML. - - See [Introducing JSX] for more information. -* [`transform-class-properties`] - Transforms class properties and lets you use the following syntax: - ``` javascript - class Example { - anInstanceProperty = 52; - } - ``` -* [`transform-object-rest-spread`] - Transforms the rest and spread properties for objects to let you use the following syntax: - ``` javascript - const config = { ...defaultConfig, ...passedConfig }; - ``` - -In general, these plugins provide convenience and produce cleaner code in your project. - -## Create the local environment variables file - -Create a `.env` file and assign values to the following environment variables: - -* `MAGENTO_BACKEND_URL` - Your local Magento store’s host and port. -* `MAGENTO_BACKEND_PUBLIC_PATH` - PWA files are served from root during development, but - this environment variable can later be used to simulate a deployed static path. -* `SERVICE_WORKER_FILE_NAME` - Set this value to `"sw.js"`. - -Your file should look like the following: - -``` text -MAGENTO_BACKEND_URL=https://localhost.magento:8008 - -MAGENTO_BACKEND_PUBLIC_PATH=/ - -SERVICE_WORKER_FILE_NAME="sw.js" -``` - -## Create the webpack configuration file - -Create a `webpack.config.js` file in your theme’s root directory. -This file exports a configuration object that tells Webpack how to build your theme. - -Webpack configuration is a complicated topic, so the following sections explain what each piece does in the configuration file. -To see the fully assembled file, see the example [webpack.config.js]. - -### Import environment variables - -At the top of the webpack.config.js file add the following: - -``` javascript -require('dotenv').config(); -``` - -This imports the contents of the `.env` file as environment variables using the `dotenv` module. -These environment variables are accessed using the `process.env` global object. - -For example, the following code outputs the value of the `MAGENTO_BACKEND_URL` environment variable: - -``` javascript -console.log(process.env.MAGENTO_BACKEND_URL); -``` - -### Import Webpack and pwa-buildpack libraries - -Append the following content to `webpack.config.js` to import the Webpack and pwa-buildpack libraries: - -``` javascript -const webpack = require('webpack'); -const { - WebpackTools: { - MagentoRootComponentsPlugin, - ServiceWorkerPlugin, - MagentoResolver, - PWADevServer - } -} = require('@magento/pwa-buildpack'); -``` - -### Define paths to theme resources - -Add the following content to `webpack.config.js` to define the paths to your theme resources: - -``` javascript -const path = require('path'); - -const themePaths = { - src: path.resolve(__dirname, 'src'), - output: path.resolve(__dirname, 'web'), -}; -``` - -This snippet uses the `path` module to format and normalize the file paths. -It also uses the special Node variable `__dirname` because it always resolves to the directory of the current executing script file. - -The locations specified in the snippet are the standard locations of source code, static assets, and build output in a [Peregrine] app. - -### Export the Webpack configuration object - -Append the following content to webpack.config.js to export the configuration object for Webpack: - -``` javascript -module.exports = async function(env) { - const config = { - context: __dirname, // Node global for the running script's directory - entry: { - client: path.resolve(themePaths.src, 'index.js') - }, - output: { - path: themePaths.output, - publicPath: process.env.MAGENTO_BACKEND_PUBLIC_PATH, - filename: 'js/[name].js', - chunkFilename: 'js/[name]-[chunkhash].js' - }, - module: { - rules: [ - { - include: [themePaths.src], - test: /\.js$/, - use: [ - { - loader: 'babel-loader', - options: { cacheDirectory: true } - } - ] - }, - { - test: /\.css$/, - use: [ - 'style-loader', - { - loader: 'css-loader', - options: { - importLoaders: 1 - } - } - ] - } - ] - }, - resolve: await MagentoResolver.configure({ - paths: { - root: __dirname - } - }), - plugins: [ - new MagentoRootComponentsPlugin(), - new webpack.NoEmitOnErrorsPlugin(), - new webpack.EnvironmentPlugin({ - NODE_ENV: env.mode, - SERVICE_WORKER_FILE_NAME: 'sw.js' - }) - ] - - }; - - return config; -} -``` - -This configuration sets up Webpack for your development environment. -Some important things to note in this configuration: - -* How it configures the `MagentoResolver` service -* The inclusion of the `MagentoRootComponent` as a plugin -* The use of `webpack.EnvironmentPlugin` to pass environment variables - -### Add development mode configuration - -Add the following development mode configuration before returning the `config` object: - -``` javascript -if (env.mode === "development") { - config.devServer = await PWADevServer.configure({ - publicPath: process.env.MAGENTO_BACKEND_PUBLIC_PATH, - backendDomain: process.env.MAGENTO_BACKEND_URL, - serviceWorkerFileName: process.env.SERVICE_WORKER_FILE_NAME, - paths: themePaths, - id: path.basename(__dirname) // Defaults to theme directory name - }); - - // A DevServer generates its own unique output path at startup. It needs - // to assign the main outputPath to this value as well. - - config.output.publicPath = config.devServer.publicPath; - - config.plugins.push( - new ServiceWorkerPlugin({ - env, - paths: themePaths, - enableServiceWorkerDebugging: false, - serviceWorkerFileName: process.env.SERVICE_WORKER_FILE_NAME - }) - ); - - config.plugins.push( - new webpack.HotModuleReplacementPlugin() - ); -} else { - throw Error('Only "development" mode is currently supported. Please pass "--env.mode development" on the command line.'); -} -``` - -This code block does the following: - -* Create a `PWADevServer` configuration object and attach it to the Webpack configuration object. -* Create a `ServiceWorkerPlugin` and attach it to the Webpack configuration object. -* Add a `webpack.HotModuleReplacementPlugin` to enable fast workflow. -* Configure Webpack to throw an error if you are not in development mode. - -### Add start script - -Edit the `scripts` section of your `package.json file` so it looks like the following: - -``` javascript -"scripts": { - "start" : "webpack-dev-server --progress --color --env.mode development", - "test": "echo \"Error: no test specified\" && exit 1" -} -``` - -This allows you to start a development server using the `npm start` command. -The `--env.mode development` argument sets the `mode` property to `development` in the configuration function exported from `webpack.config.js`. - -{: .bs-callout .bs-callout-info} -**Note:** -When you run npm start for the first time or after a long period of time, PWA Studio may ask for your password. -This is required to set the local host and SSL trust settings on your system. -It will not retain broad permissions on your system. - -Now that you have created your project configuration files, you can create a [simple peregrine app]. - -[previous topic]: {% link pwa-buildpack/project-setup/link-project/index.md %} -[JSX]: https://facebook.github.io/jsx/ -[Introducing JSX]: https://reactjs.org/docs/introducing-jsx.html -[webpack.config.js]: {% link pwa-buildpack/project-setup/create-configuration-files/webpack-config-example/index.md %} -[Peregrine]: {% link peregrine/index.md %} -[simple peregrine app]: {% link pwa-buildpack/project-setup/create-simple-peregrine-app/index.md %} -[Babel]: https://babeljs.io/ -[`syntax-jsx`]: https://babeljs.io/docs/plugins/syntax-jsx -[`transform-react-jsx`]: https://babeljs.io/docs/plugins/transform-react-jsx -[`transform-class-properties`]: https://babeljs.io/docs/plugins/transform-class-properties/ -[`transform-object-rest-spread`]: https://babeljs.io/docs/plugins/transform-object-rest-spread/ diff --git a/pwa-devdocs/_drafts/project-setup/create-configuration-files/webpack-config-example/index.md b/pwa-devdocs/_drafts/project-setup/create-configuration-files/webpack-config-example/index.md deleted file mode 100644 index 9e53719382..0000000000 --- a/pwa-devdocs/_drafts/project-setup/create-configuration-files/webpack-config-example/index.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Example webpack.config.js file ---- - -The following is an example of the `webpack.config.js` file described in the [Create configuration files] topic: - -``` javascript -require('dotenv').config(); - -const webpack = require('webpack'); -const { - WebpackTools: { - MagentoRootComponentsPlugin, - ServiceWorkerPlugin, - MagentoResolver, - PWADevServer - } -} = require('@magento/pwa-buildpack'); - -const path = require('path'); - -const themePaths = { - src: path.resolve(__dirname, 'src'), - output: path.resolve(__dirname, 'web') -}; - -module.exports = async function(env) { - const config = { - context: __dirname, // Node global for the running script's directory - entry: { - client: path.resolve(themePaths.src, 'index.js') - }, - output: { - path: themePaths.output, - publicPath: process.env.MAGENTO_BACKEND_PUBLIC_PATH, - filename: 'js/[name].js', - chunkFilename: 'js/[name]-[chunkhash].js' - }, - module: { - rules: [ - { - include: [themePaths.src], - test: /\.js$/, - use: [ - { - loader: 'babel-loader', - options: { cacheDirectory: true } - } - ] - }, - { - test: /\.css$/, - use: [ - 'style-loader', - { - loader: 'css-loader', - options: { - importLoaders: 1 - } - } - ] - } - ] - }, - resolve: await MagentoResolver.configure({ - paths: { - root: __dirname - } - }), - plugins: [ - new MagentoRootComponentsPlugin(), - new webpack.NoEmitOnErrorsPlugin(), - new webpack.EnvironmentPlugin({ - NODE_ENV: env.mode, - SERVICE_WORKER_FILE_NAME: 'sw.js' - }) - ] - - }; - - if (env.mode === "development") { - config.devServer = await PWADevServer.configure({ - publicPath: process.env.MAGENTO_BACKEND_PUBLIC_PATH, - backendDomain: process.env.MAGENTO_BACKEND_URL, - serviceWorkerFileName: process.env.SERVICE_WORKER_FILE_NAME, - paths: themePaths, - id: path.basename(__dirname) // Defaults to theme directory name - }); - - // A DevServer generates its own unique output path at startup. It needs - // to assign the main outputPath to this value as well. - - config.output.publicPath = config.devServer.publicPath; - - config.plugins.push( - new ServiceWorkerPlugin({ - env, - paths: themePaths, - enableServiceWorkerDebugging: false, - serviceWorkerFileName: process.env.SERVICE_WORKER_FILE_NAME - }) - ); - - config.plugins.push( - new webpack.HotModuleReplacementPlugin() - ); - - } else { - throw Error('Only "development" mode is currently supported. Please pass "--env.mode development" on the command line.'); - } - - return config; -} -``` - -[Create configuration files]: {% link pwa-buildpack/project-setup/create-configuration-files/index.md %} diff --git a/pwa-devdocs/_drafts/project-setup/create-simple-peregrine-app/index.md b/pwa-devdocs/_drafts/project-setup/create-simple-peregrine-app/index.md deleted file mode 100644 index 959cd13c43..0000000000 --- a/pwa-devdocs/_drafts/project-setup/create-simple-peregrine-app/index.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Create a simple peregrine app ---- - -In the [previous topic], you created configuration files for your theme project. -In this topic, you will create a simple app that follows the [Peregrine] pattern. - -## Create app.js - -1. Create the `src` and `src/components` directories in your theme's root directory using the following command: - ``` sh - mkdir -p src/components - ``` -1. Inside the `components` directory, create an `app.js` file with the following content: - - ``` jsx - import React from 'react'; - - export default class App extends React.Component { - render() { - return ( -

- Hello, Studio! -

- ); - } - } - - ``` - - This code defines a React component that returns "Hello, Studio!" inside `h1` tags. - -## Create index.js - -Inside `src` create an `index.js` file with the following content: - -``` javascript -import Peregrine from '@magento/peregrine'; -import App from './components/app'; - -const app = new Peregrine(); -const container = document.getElementById('root'); - -app.component = App; -app.mount(container); - -if ('serviceWorker' in navigator) { - window.addEventListener('load', () => { - navigator.serviceWorker - .register(process.env.SERVICE_WORKER_FILE_NAME); - }); -} - -export default app; -``` - -This imports the previously-defined `app` component and incorporates it into Peregrine before adding it to an HTML `root` element. - -## Create RootComponents directory - -Inside `src`, create a `RootComponents` directory. -This directory will contain code for your root components. -For now, leave this directory empty. - -## Congratulations! - -You have created a Peregrine app skeleton! - -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: - -``` sh -npm start -``` - -If you experience problems with the project setup, see [Troubleshooting]. - -[previous topic]: {% link pwa-buildpack/project-setup/create-configuration-files/index.md %} -[Peregrine]: {% link peregrine/index.md %} -[Project setup tutorial]: {% link pwa-buildpack/project-setup/index.md %} -[Troubleshooting]: {% link pwa-buildpack/troubleshooting/index.md %} diff --git a/pwa-devdocs/_drafts/project-setup/create-theme-files/index.md b/pwa-devdocs/_drafts/project-setup/create-theme-files/index.md deleted file mode 100644 index 30f472e80f..0000000000 --- a/pwa-devdocs/_drafts/project-setup/create-theme-files/index.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Create the initial theme files - ---- - -Unlike regular [Magento Themes], Magento Progressive Web Apps are built on top of the [PWA base theme]. -They are also *decoupled* from the backing Magento stores, so they no longer need to be developed under `app/design/frontend`. - -It is still possible to develop your project under `app/design/frontend`, but -the recommended approach is to use Composer to manage the connection between your project and the backend store. - -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. - -## Create theme directory and files - - -1. For this tutorial, **orange-theme** will be the name of the theme directory. - Run the following command to create this directory and `cd` into it: - - ``` bash - mkdir orange-theme && cd orange-theme - ``` - - {: .bs-callout .bs-callout-info} - **Note:** - Your theme directory does not need to be created inside a Magento application directory. - -1. Create a `media` directory and place a `preview.jpg` image file inside. - This image is used as the preview image for your theme. -1. Create a `theme.xml` file. - - ``` xml - - - - Orange Theme - Magento/pwa - - media/preview.jpg - - - ``` - - This file provides the name of theme, the required PWA parent theme, and the location of the preview image to Magento. - -1. Create a `composer.json` file. - - ``` json - { - "name": "orangecompany/orange-theme", - "description": "The inimitable Orange Theme.", - "version": "1.0.0", - "require": { - "php": "~7.1.0|~7.2.0", - "magento/framework": "100.3.*", - "magento-research/theme-frontend-pwa": "*" - }, - "type": "magento2-theme", - "license": "OSL-3.0", - "autoload": { - "files": ["registration.php"] - } - } - ``` - - This file makes your theme a composer package for easy distribution in the [Magento Marketplace]. -1. Create a `registration.php` file to register your theme with Magento. - - ``` php - path/to/orange-theme -``` - -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. - -### Admin - -Log into the Admin section of your Magento installation and select **Themes** in the **Content** tab. - -You should see Orange Theme listed as one of the available themes in Magento. - -To install the theme, select **Configuration** in the **Content** tab and set your storefront to use the Orange Theme. - -The next step is to [create the configuration files]. - - -[previous topic]: {% link pwa-buildpack/project-setup/install-dependencies/index.md %} -[create the configuration files]: {% link pwa-buildpack/project-setup/create-configuration-files/index.md %} \ No newline at end of file diff --git a/pwa-devdocs/_drafts/pwa-studio-fundamentals/explore-graphql-with-graphiql/images/graphql-network-screenshot.png b/pwa-devdocs/_drafts/pwa-studio-fundamentals/explore-graphql-with-graphiql/images/graphql-network-screenshot.png deleted file mode 100644 index ddfa84338f..0000000000 Binary files a/pwa-devdocs/_drafts/pwa-studio-fundamentals/explore-graphql-with-graphiql/images/graphql-network-screenshot.png and /dev/null differ diff --git a/pwa-devdocs/_drafts/pwa-studio-fundamentals/explore-graphql-with-graphiql/index.md b/pwa-devdocs/_drafts/pwa-studio-fundamentals/explore-graphql-with-graphiql/index.md deleted file mode 100644 index e17f556687..0000000000 --- a/pwa-devdocs/_drafts/pwa-studio-fundamentals/explore-graphql-with-graphiql/index.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Explore Magento's GraphQL with GraphiQL ---- - -## Overview - -To work with Magento and PWA Studio you need be familiar with their GraphQL API. -Below step by step instructions to introduce you to Magento's GraphQL. - -1. If you're not familiar with GraphQL or GraphiQL read this short [article on medium][]. -1. Install the [ChromeiQL][] browser extension. -1. Set it to use a public Magento GraphQL endpoint. -[https://master-7rqtwti-mfwmkrjfqvbjk.us-4.magentosite.cloud/graphql][] -1. Explore the docs section to see what [queries and mutations][] are currently available in Magento's GraphQL API. -1. Run the following query: - -```graphql -{ - category( - id: 10 - ) { - url_key - products{ - items { - name - } - } - } -} -``` -6. Compare Magento's GraphiQL docs to their [Swagger REST docs][]. -1. Check to see what GraphQL queries the [venia storefront demo][] is using by looking at the chrome network tab. -![chrome network tab][] -1. Try using one of these queries in GraphiQL. - -## Learn more - -- [Learn GraphQL](https://graphql.org/learn) -- [PWA Studio: GraphQL][] -- [How to GraphQL](https://www.howtographql.com/) - -[PWA Studio: GraphQL]: {%link technologies/basic-concepts/graphql/index.md %} -[chrome network tab]: ./images/graphql-network-screenshot.png -[article on medium]: https://medium.com/the-graphqlhub/graphiql-graphql-s-killer-app-9896242b2125 -[ChromeiQL]: https://chrome.google.com/webstore/detail/chromeiql/fkkiamalmpiidkljmicmjfbieiclmeij -[queries and mutations]: https://graphql.org/learn/queries/ -[Swagger REST docs]: https://devdocs.magento.com/swagger/ -[venia storefront demo]: https://venia.magento.com/ -[https://master-7rqtwti-mfwmkrjfqvbjk.us-4.magentosite.cloud/graphql]: https://master-7rqtwti-mfwmkrjfqvbjk.us-4.magentosite.cloud/graphql diff --git a/pwa-devdocs/_drafts/pwa-studio-fundamentals/extensibility-with-targets/index.md b/pwa-devdocs/_drafts/pwa-studio-fundamentals/extensibility-with-targets/index.md deleted file mode 100644 index 42e2800ac2..0000000000 --- a/pwa-devdocs/_drafts/pwa-studio-fundamentals/extensibility-with-targets/index.md +++ /dev/null @@ -1,838 +0,0 @@ ---- -title: Modular Extensibility in PWA Studio with Targets ---- - -The new extensibility system for PWA Studio turns your storefront project into a self-organizing app, built by modules you can install, and hand-tuned by as much or as little customization code as you like. - -A few simple new concepts—the network of **Targets**, the **BuildBus**, and the [**Interceptor pattern**](https://web.archive.org/web/20170912094101/http://www.cs.wustl.edu/~schmidt/POSA/POSA2/access-patterns.html)—enable your chosen third-party code to enhance the build toolchain, add new functionality to the storefront, and even _rewrite the code of your published PWA on-the-fly_. - -- [Quick Start](#quick-start) - - [Project Setup](#project-setup) - - [Watch it work](#watch-it-work) - - [Production efficiency](#production-efficiency) -- [Concepts](#concepts) - - [Building a PWA from installed extensions](#building-a-pwa-from-installed-extensions) - - [Intercept files](#intercept-files) - - [How and when intercept files run](#how-and-when-intercept-files-run) - - [Target dependency management](#target-dependency-management) - - [TargetProviders](#targetproviders) - - [Targets](#targets) - - [Targets as Public API](#targets-as-public-api) - - [Declaring targets](#declaring-targets) -- [API](#api) - - [`Target`](#target) - - [Target names](#target-names) - - [Target Reference API](#target-reference-api) - - [Advanced Target API](#advanced-target-api) - - [TargetProvider](#targetprovider) - - [TargetProvider Reference API](#targetprovider-reference-api) - - [BuildBus](#buildbus) - - [BuildBus Reference API](#buildbus-reference-api) - - [Builtin Targets and their APIs](#builtin-targets-and-their-apis) - - [Buildpack](#buildpack) - - [Peregrine](#peregrine) - - [VeniaUI](#veniaui) -- [Development](#development) - - [Extension development](#extension-development) - - [Initial phase: in-project interceptors](#initial-phase-in-project-interceptors) - - [Move the code](#move-the-code) - - [Manage dependencies](#manage-dependencies) - - [Simulate install](#simulate-install) - - [Testing](#testing) - - [Unit Testing Targets](#unit-testing-targets) - - [Testing Webpack Loaders](#testing-webpack-loaders) - - [Integration Testing: Full Builds](#integration-testing-full-builds) - - [Contributing](#contributing) - - [Help Wanted](#help-wanted) - -# Quick Start - -Use Targets to add a new custom route to a Venia-based store, without editing any VeniaUI code. - -## Project Setup - -1. Clone the PWA Studio repository. - - -2. Edit `packages/venia-concept/package.json`. Add a new top-level section: - ```diff - "module": "src/index.js", - "es2015": "src/index.js", - "esnext": "src/index.js", - + "pwa-studio": { - + "targets": { - + "intercept": "targets/local-intercept" - + } - + } - } - ``` - -3. Create `packages/venia-concept/targets/local-intercept.js`: - ```js - module.exports = targets => { - targets.of('@magento/venia-ui').routes.tap(routes => { - routes.push({ - name: 'Greeting', - pattern: '/greeting/:who?', - path: require.resolve('../src/GreetingPage.js') - }); - return routes; - }); - }; - ``` - -4. Create `packages/venia-concept/src/GreetingPage.js`: - ```js - import React from 'react'; - import { useParams } from 'react-router'; - - const hi = { - textAlign: 'center', - margin: '1rem' - }; - const wave = { - ...hi, - fontSize: '5rem' - }; - - export default function GreetingPage() { - const { who = 'nobody' } = useParams(); - return ( -
-

Hello, {who}!

-

{'\uD83D\uDC4B'}

-
- ); - } - ``` - -That's it! -You've registered your project to use BuildBus, created an interceptor file to add to VeniaUI's routes, and created a new React component to use as a custom route. - -## Watch it work - -1. Run `yarn run watch:venia`. Open the dev-mode storefront in your browser. - -1. Go to `/greeting`. Observe as your `GreetingPage` component is displayed! - -1. Your `GreetingPage` is a React Router `Route`, so it can use route parameters. Go to `/greeting/world`. - -1. Congratulations. Now, your `GreetingPage` has accomplished the [fundamental task of computer programs](https://en.wikipedia.org/wiki/%22Hello,_World!%22_program#/media/File:Hello_World_Brian_Kernighan_1978.jpg). - -## Production efficiency - -Targets that change your storefront only need to run once, at build time. -They affect the build process that generates static application bundles, changing the code it outputs. -That way, there need be _no storefront performance cost_ to augmenting your PWA with Targets. -Prove it to yourself! - -1. Run a full Venia production build: `yarn run build`. - -1. Remove the `"pwa-studio"` section from `packages/venia-concept/package.json`. - -1. Delete `packages/venia-concept/targets`. - -1. Run the staging server: `yarn run stage:venia`. - -1. Visit your staging site and navigate to `/greeting/production`. - -1. It still works, even though your server-side interceptor code is gone! - -Contrast this with a plugin architecture which detects and dispatches plugins as the storefront runs in the shopper's device. -If VeniaUI had to scan extensions for custom routes inside the React app, then the extension system itself would bloat the application. -"Runtime" extension systems can only give developers convenience and customization by sacrificing some performance and shopper experience. -The Targets system is flexible enough to give developers any extension point they can envision, yet it produces a PWA site as fast as hand-optimized code. - -# Concepts - -## Building a PWA from installed extensions - -Magento PWA Studio follows the Magento way of building Web functionality on a simple platform by intelligently merging third-party code. -As the third-party ecosystem grows, a PWA project may contain less and less first-party source code. -A developer can then: - -1. Create a PWA based on VeniaUI -2. Install several third-party modules to automatically enhance VeniaUI -3. Intercept targets to customize those modules -4. Maintain only a minimal "index" component and configuration files in their own source code - -This helps developers 'spin up' new stores and mix in functionality with minimal boilerplate. -In this structure, a developer can manage dependency upgrades and compatibility issues using semantic versioning, by managing the `package.json` file in their project. - -## Intercept files - -Directly interact with Target objects by creating and registering an intercept file. -The file's default export must be a function which receives one argument. -That argument will be a [TargetProvider][]. - -`./targets/intercept.js`: -```js -module.exports = targets => { - // interceptors go here -} -``` - -Intercept files run in NodeJS during the build and other lifecycle scripts. -Write them as CommonJS modules and organize them in another folder, like `./targets` above, alongside your frontend source code. - -_All intercept and target paths are changeable; the recommended paths are for convention and organization only. In the above examples, the project-level intercept file is named `local-intercept.js`, to denote that this intercept file is for the local project and is not associated with any extension._ - -To register `./targets/intercept.js` as intercept file, add its path to `package.json` under the `pwa-studio.targets.intercept` section: - ```diff - "module": "src/index.js", - "es2015": "src/index.js", - "esnext": "src/index.js", - + "pwa-studio": { - + "targets": { - + "intercept": "./targets/intercept.js" - + } - + } - } - ``` - -This declaration will alert Buildpack that the package wants to intercept targets. - -Inside its main function, an intercept file uses the `TargetProvider` to retrieve Targets from the various installed modules. -It then runs tap methods on the Target to register interceptor callbacks. -When the module that declared the target chooses to invoke the target, the interceptor callbacks will be invoked. -In those interceptor callbacks, the intercept file can make customizations, gather data, modify the build itself, or implement and call its own declared targets. - -### How and when intercept files run - -PWA Studio's build process, using the `@magento/pwa-buildpack` module, calls intercept files by creating a `BuildBus` and running it. -It looks for intercept files _only in the **named** direct dependencies of the project._ -It does not traverse the whole dependency tree, running intercept files from second-level transitive dependencies and beyond. -Only the modules listed in the project's `package.json` under `dependencies` and `devDependencies` can use Targets in the project. -See [Target dependency management][] below. - -The `BuildBus` will load the `targets/intercept.js` module when running targets and call the exported function. - -It runs the intercept files in dependency order. If your module declares another module with Targets in `peerDependencies` (see below), the other module will intercept first. - -The PWA project itself can register an intercept file. -This file should contain specific customizations for this project only. -It runs last, after all dependent modules have declared and intercepted targets. - -### Target dependency management - -A project only runs Targets from its first-level dependencies. - -This means that if you're writing a third-party module which uses Targets from another module, like `@magento/peregrine`, then it shouldn't list Peregrine in its own `dependencies` list. -That does not guarantee that Peregrine will be a first-level dependency of the project. -To use those Targets, your module needs its _host PWA project_ to also list a direct dependency on Peregrine. -So it must add `@magento/peregrine` to the package.json `peerDependencies` collection. -This instructs NPM to make sure that the top-level project installing your module is also installing `@magento/peregrine`. -It warns the user strongly if that dependency is missing. -Using `peerDependencies` for frontend libraries is a good practice anyway; it's a safeguard against including multiple copies of the same library in your built PWA. - -## TargetProviders - -A **TargetProvider** is an object that manages the connections between different modules and their Targets. -It is the API that intercept files use to acquire Targets and intercept them. - -Use `targets.of(moduleName)` to get the targets of another module. -This method returns a simple object whose keys are target names, and whose values are Target objects. - -```js -module.exports = targets => { - const builtins = targets.of('@magento/pwa-buildpack'); - builtins.webpackCompiler.tap(compiler => { - // do fun stuff to the compiler using the familiar Tapable interface! - compiler.emit.tap('MyExtension', compilation => { - }); - }); - // use higher-level targets with the same interface if you want! - builtins.transformModules.tap('MyExtension', addTransform => { - }); -} -``` - -Use `targets.own` to get the targets that the current module (whose interceptor file is running right now!) has declared. -The intercept file is a typical place to _implement_ the actual functionality of module's own targets. -Almost all target functionality comes from intercepting other targets, as in the below example. - -```js -module.exports = targets => { - const builtins = targets.of('@magento/pwa-buildpack'); - builtins.webpackCompiler.tap(compiler => { - compiler.emit.tap(targets.name, compilation => { - const totalSize = compilation.getStats().chunks.reduce((sum, chunk) => - sum + chunk.size, - 0 - ); - targets.own.perfReport.call({ totalSize }); - }) - }); - builtins.transformModules.tap('MyExtension', addTransform => { - type: 'source', - fileToTransform: require.resolve('../components/SocialShare'), - transformModule: '@my-extension/targets/codegen-social-icons.js', - options: { - icons: targets.own.socialIcons.call([]) - } - }); -} -``` - -In the example, `MyExtension` implements its own `perfReport` hook by tapping Webpack hooks, building an info object, and invoking the `perfReport` hook inside the Webpack interceptor callback. -It also implements its own `socialIcons` hook by configuring the build process to pass the `SocialShare` component's source code through a transform function implemented in `./codegen-social-icons.js`. - -_Where did `perfReport` and `socialIcons` come from?? See [Declaring targets][] below._ - -## Targets - -A **Target** is an object representing an "extension point", an area in code that can be accessed and intercepted. -All Targets are variants of a simple, common JavaScript pattern called the [Tapable Hook](https://github.com/webpack/tapable). -These objects may resemble event emitters. -They share some functionality with those: a Target lets you choose a point _by name_ in the time and space of a process and run other code in that time and place. -Unlike Event Emitters, Targets have defined behavior for how, and in what order, they will run their interceptors and how those interceptors may change things. - -The concepts of code reusability that already exist in ReactJS apps are still there. -You can import large or small components from VeniaUI and other modules, and put them together in your own React component tree. -You can write components in your own project which utilize third-party code. - -Targets provide an additional layer of customization, which can work smoothly with those plain code composition techniques. -All direct dependencies (listed in `dependencies` or `devDependencies`) of a PWA project can declare and intercept Targets. -An intercept file can access the full library of Targets declared by all direct dependencies. - -### Targets as Public API -Targets present another public API of a package alongside the modules it exports to runtime code. -For example, `@magento/venia-ui` provides components for importing, and talons for making deep changes to those components. -Let's say you want to make all CMS blocks that are only plain text (with no HTML) into big, beautiful blue text. -Your app can import VeniaUI's RichContent component to make its own enhanced one: - -```js -import React from 'react'; -import BaseRichContent from '@magento/venia-ui/lib/components/RichContent'; -import WordArt from 'react-wordart'; - -// If the content is just words, make 'em BLUE words. -export const RichContent = ({ html }) => - /^[^<>]+$/gm.test(html) ? ( // no tags! - - ) : ( - - ); -``` - -Your new component _uses_ RichContent, but it doesn't change RichContent. -It's not going to replace RichContent everywhere that other code uses it. - -RichContent is an important component, and custom content renderers are a popular Magento feature. -So, in addition to exporting the component, VeniaUI declares a Target called `richContentRenderers`. -This allows you to change the behavior of RichContent everywhere it's used, by adding a rendering strategy. - -As documented by VeniaUI, `richContentRenderers` expects a "rendering strategy" module which exports a `canRender` function and a `Component`. -Update your component to implement a rendering strategy, instead of wrapping RichContent itself. - -```js -import React from 'react'; -import WordArt from 'react-wordart'; - -const noTags = /^[^<>]+$/gm; - -const BlueWords = ({ html }) => ( - -); - -export const canRender = html => noTags.test(html); -export { BlueWords as Component }; -``` - -Now, add an interceptor in your intercept file. -```js - targets - .of('@magento/venia-ui') - .richContentRenderers.tap(richContentRenderers => { - richContentRenderers.add({ - componentName: 'BlueWords', - importPath: require.resolve('../BlueWords') - }); - }); -``` - -Since you now explicitly register BlueWords as a `richContentRenderer` via the declared target, the `RichContent` component will attempt to use that renderer everywhere `RichContent` is used. - -Targets are written in JavaScript. -This doesn't mean that they can only work with the JavaScript in the PWA storefront, however. -The built and published PWA contains HTML, CSS, and JavaScript, the main languages of the Web, but all these assets are generated by build process in Webpack, which runs in Node.js. -JavaScript files that declare and intercept Targets work with the build process and can modify the HTML and CSS that the build generates. -If you use module transforms, you'll be using JavaScript that parses and modifies other JavaScript! - -As a Targets-driven codebase grows, it might sometimes be confusing to work with JavaScript files that run as _build scripts_ in NodeJS, alongside similar-looking JavaScript files that are _source code_ to be bundled into the PWA and run on the shopper's device. - -A quick way to get your bearings in a JavaScript file is to look at what kind of module system the code is using. -Storefront JS that will run on the device must use ES6 Modules with `import` and `export`: -```js -import throttle from `lodash.throttle`; -export const everySecond = fn => - throttle(fn, 1000); -``` - -Backend JS that will run in Node,at build time or on the server side, must use CommonJS modules with `require()`: -```js -const throttle = require('lodash.throttle'); -module.exports.everySecond = fn => - throttle(fn, 1000); -``` - -### Declaring targets - -Targets must be defined and created before they are intercepted. -Modules define their own targets by registering a **declare file**. -The declare file also exports a function which receives a TargetProvider object. -The TargetProvider object provides a `declare` function which takes a dictionary of named Targets. -Furthermore, the TargetProvider has a utility collection called `types`, which holds all of the legal constructors for Targets. - -`./targets/declare.js`: -```js -module.exports = targets => { - targets.declare({ - perfReport: new targets.types.AsyncParallel(['report']) - socialIcons: new targets.types.SyncWaterfall(['iconlist']) - }); -} -``` - -The above declare file creates two targets that other modules, as well as the root project, can intercept. -The `perfReport` target runs its interceptors asynchronously and in parallel. -This is appropriate for logging and monitoring interceptors that don't affect functionality. -The `socialIcons` target runs its interceptors synchronously and in subscription order, passing return values as arguments to the next interceptor. -This is appropriate for customizations that must happen in a predictable order. - -Targets are variants of Tapables; see [Tapable](https://github.com/webpack/tapable) for a list of available types and behaviors. -(Note that the Tapable classnames all end with 'Hook', and the Target classnames do not.) - -The BuildBus runs all declare files before running any intercept files, so simply registering a declare file will guarantee that the targets are available to any dependent interceptor. -Like intercept files, declare files are CommonJS modules that run in Node. Organize them together with intercept files. - -To register `./targets/declare.js` as a declare file, add its path to `package.json` under the `pwa-studio.targets.declare` section: - ```diff - "module": "src/index.js", - "es2015": "src/index.js", - "esnext": "src/index.js", - "pwa-studio": { - "targets": { - + "declare": "./targets/declare.js", - "intercept": "./targets/intercept.js" - } - } - } - ``` - -# API - -## `Target` - -A Target is a wrapper around a [Tapable Hook](https://github.com/webpack/tapable). -It reproduces the Hook's API, and tracks activity and the connections between dependencies that use each others' Targets. -Targets can wrap any of the Tapable Hooks described in the above link, except for the `Loop` classes (which Tapable doesn't fully support yet) and the helper classes like `MultiHook` and `HookMap`. -The TargetProvider accessed by declare files and intercept files provides a set of the supported target types. - -```js -module.exports = targets => { - const SyncBail = targets.types.SyncBail; - assert(SyncBailHook === require('tapable').SyncBailHook); -} -``` - -(To avoid confusion with React Hooks, the `target.types` dictionary omits the "Hook" suffix from the supported tapable names.) - -All of the `target.types` constructors require an array of strings as their only argument. -These strings represent represent the arguments sent to interceptors. -If you plan to call the target with 2 arguments, you must supply two strings as argument names to the tapable constructor. - -In this documentation, the words "hook" and "tapable" are used interchangeably. -(**TODO**: Make this documentation _not_ do that.) -Both refer to the classes from the `tapable` library, which PWA Studio wraps with `Targets`. - -A `Target` implements the interface of the tapable used to declare it. If you declared: - -```js -targets.declare({ - cancelLogin: new targets.types.AsyncSeriesBail(['id']) -}) -``` - -Then in your intercept file, you will have access to: - -```js -targets.own.cancelLogin.tapPromise(promiseReturningHandler); - -const canceller = await targets.own.cancelLogin.promise(someId); -``` - -### Target names - -**TODO**: decide what is described here versus in doc comments or Concepts above - -Tap methods in the underlying Tapables always require two arguments: a name for the interceptor, and the callback. -When using Targets' tap methods, the name is optional. -For tracking purposes, all Target interceptors must have names, so the Target class will automatically use the name of the dependency package, such as `@my/pwa-extension`. -If you _do_ supply a string name as the first argument, the Target will concatenate your custom name with the package name. - -Tapables can also accept a single argument that is a `tapInfo` object, with `name` and `fn` properties, as well as other properties that can affect the order of execution. -Those features are available and encouraged! -The same principle applies: unlike raw Tapable instances, Targets don't require a `name` property in the `tapInfo` object. - -### Target Reference API - -**TODO**: Adapt or generate API doc from Target.js doc comments - -### Advanced Target API - -**TODO** Document Tapable concepts like: - - `before` and `stage` parameters - - `intercept` meta-interception possibilities - -## TargetProvider - -**TODO**: decide what is described here versus in doc comments or Concepts above - -### TargetProvider Reference API - -**TODO**: Adapt or generate API doc from Target.js doc comments - -## BuildBus - -The BuildBus, which scans dependencies and executes targets, is an internal-only object. -Only use the BuildBus directly if you are working directly on Buildpack code, which must invoke the BuildBus and call targets manually in order to "kick off" the execution of all targets in the dependency tree. - -### BuildBus Reference API - -**TODO**: Adapt or generate API doc from BuildBus.js doc comments - -## Builtin Targets and their APIs - -**TODO**: Adapt or generate API doc from the JSDoc comments all over all the declare files - -### Buildpack - -- envVarDefinitions -- transformModules -- webpackCompiler -- specialFeatures - -**TODO**: Adapt and move some stuff from the Contributing section below, relating to making higher-level targets from these - -### Peregrine - -- talons - -### VeniaUI - -- richContentRenderers -- routes - -# Development - -## Extension development - -When writing a PWA-compatible library, to publish on NPM or on the Magento Marketplace, think of Targets as the main tool in your toolbox. -To add new functionality, try adding interceptors to your storefront project and injecting the functionality that way. -When your prototype is working, try separating that work into a separate module and continuing to work on it as an encapsulated, portable extension! - -### Initial phase: in-project interceptors - -As in the [Quick Start][], new functionality may begin by intercepting from the storefront project itself. -The tutorial creates a Greeting Page by implementing the page in the storefront project's source folder. - -The next step is to turn that functionality into a new module. - -### Move the code - -Create a new project folder alongside your storefront. -Create `./GreetingPage.js` and paste in the content from the tutorial above. - -Run `yarn init` and then add the `pwa-studio` section to your `package.json`. - -Also, set the `"main"` field to `"./GreetingPage.js"`, to make it the default export of the package. - -```json -{ - "name": "@me/pwa-greeting-page", - "version": "1.0.0", - "description": "Hello, anything!", - "author": "PWA Developer", - "main": "./GreetingPage.js", - "license": "MIT", - "pwa-studio": { - "targets": { - "intercept": "./targets/intercept.js" - } - } -} -``` - -Create `./targets/intercept.js`. Now that you're working in a third-party module, you can use default NodeJs module resolution in the route path. -Since you're adding components from your third-party package to the storefront, make sure to flag them for processing as ES Modules with JSX, using the `specialFeatures` builtin target. - -```js -module.exports = targets => { - // targets.name is '@me/pwa-greeting-page' - targets.of('@magento/pwa-buildpack').specialFeatures.tap(flags => { - flags[targets.name] = { esModules: true }; - }); - targets.of('@magento/venia-ui').routes.tap(routes => { - routes.push({ - name: 'Greeting', - pattern: '/greeting/:who?', - path: targets.name - }); - return routes; - }); -}; -``` - -### Manage dependencies - -The GreetingPage uses `react` and `react-router`. -The intercept file depends on targets of `@magento/venia-ui`. -This means that the project using `@me/pwa-greeting-page` must also use `react`, `react-router`, and `@magento/venia-ui` as peers. -Declare these dependencies in `package.json`: - -```json -{ - "name": "@me/pwa-greeting-page", - "version": "1.0.0", - "description": "Hello, anything!", - "author": "PWA Developer", - "main": "./GreetingPage.js", - "license": "MIT", - "pwa-studio": { - "targets": { - "intercept": "./targets/intercept.js" - } - }, - "peerDependencies": { - "@magento/venia-ui": "~6.0.0", - "react": "~16.9.0", - "react-router-dom": "~5.1.0" - } -} -``` - -### Simulate install - -To install and test your `@me/pwa-greeting-page` extension, you would have to add it to the `package.json` dependencies in your storefront. -But since `@me/pwa-greeting-page` has never been published, it would cause errors to manually insert it into those dependencies. -Fortunately, for this exact use-case of developing a new module, Buildpack allows a dev-mode override here. - -First, `yarn link` to symlink your new extension to Yarn's global set. -Then, `cd` back to your store directory and run `yarn link @me/pwa-greeting-page`. This two-step process links the packages together so that Node and Webpack can now resolve `@me/pwa-greeting-page` from the storefront project directory, without it being present in the dependency array. - -The last thing is to make Buildpack use it, even though it's not a listed dependency. -The override for that is simply an environment variable! Set `BUILDBUS_DEPS_ADDITIONAL` to a comma-separated list of the packages Buildpack should check for interceptors, in addition to the listed packages in `package.json`. - -```sh -BUILDBUS_DEPS_ADDITIONAL='@me/pwa-greeting-page' yarn run watch:venia -``` - -It should work! The functionality of the new Greeting Page has been entirely ported into its own dependency. -Simply running `yarn add @me/pwa-greeting-page` to your project will now automatically add the `/greeting` route to your PWA storefront! - -### Testing - -Targets create functionality through the build process. -React components and other frontend code will only show the results of Target functionality after a build. -This makes Target testing more complex than unit testing typical React components. -Buildpack now provides a suite of helpers for testing your Target implementations, in Jest or in any other test framework. - -#### Unit Testing Targets - -To unit test individual Target implementations, use `mockTargetProvider` and `mockBuildBus`. - -`mockTargetProvider` example from Peregrine: -```js -const { mockTargetProvider } = require('@magento/pwa-buildpack'); -const targets = mockTargetProvider( - '@magento/peregrine', - (_, dep) => - ({ - '@magento/pwa-buildpack': { - specialFeatures: { - tap: jest.fn() - }, - transformModules: { - tap: jest.fn() - } - } - }[dep]) -); -declare(targets); -expect(targets.own.talons.tap).toBeDefined(); -const hook = jest.fn(); -// no implementation testing in declare phase -targets.own.talons.tap('test', hook); -targets.own.talons.call('woah'); -expect(hook).toHaveBeenCalledWith('woah'); - -intercept(targets); -const buildpackTargets = targets.of('@magento/pwa-buildpack'); -expect(buildpackTargets.transformModules.tap).toHaveBeenCalled(); -``` - -`mockBuildBus` example from VeniaUI: -```js -const { mockBuildBus } = require('@magento/pwa-buildpack'); -const bus = mockBuildBus({ - context: __dirname, - dependencies: [thisDep] -}); -bus.runPhase('declare'); -const { richContentRenderers, routes } = bus.getTargetsOf( - '@magento/venia-ui' -); -expect(richContentRenderers.tap).toBeDefined(); -expect(routes.tap).toBeDefined(); -const interceptor = jest.fn(); -// no implementation testing in declare phase -richContentRenderers.tap('test', interceptor); -richContentRenderers.call('woah'); -expect(interceptor).toHaveBeenCalledWith('woah'); - -const divByThree = jest.fn(x => x / 3); -routes.tap('addTwo', x => x + 2); -routes.tap({ name: 'divideByThree', fn: divByThree }); -expect(routes.call(10)).toBe(4); -``` - -**TODO**: Adapt or generate API doc from JSDoc comments - -#### Testing Webpack Loaders - -A custom Target implementation that uses `transformModules` may include a custom Webpack loader. -To test Webpack loaders in a simulated Webpack loader context, use `runLoader`. - -Example from Buildpack's `wrap-esm-loader`: -```js -const { runLoader } = require('@magento/pwa-buildpack'); -const { output, context } = await runLoader(wrapEsmLoader, source, { - query: [ - { - defaultExport: true, - wrapperModule: squareToCube - } - ], - resourcePath: 'foo' -}); -const cube = requireModule(output); -expect(cube(4)).toBe(64); -expect(context.getCalls('emitWarning')).toHaveLength(0); -expect(context.getCalls('addDependency')).toMatchObject([[squareToCube]]); -``` - -**TODO**: Adapt or generate API doc from JSDoc comments - -#### Integration Testing: Full Builds - -Most Targets will affect the behavior of React components, which can only be tested by building the React component through Buildpack, which executes those targets. -To simulate this, use `testFullBuild`. - -`buildModuleWith` example from Peregrine: - -```js -const { buildModuleWith } = require('@magento/pwa-buildpack'); -const talonIntegratingDep = { - name: 'goose-app', - declare() {}, - intercept(targets) { - targets.of('@magento/peregrine').talons.tap(talons => { - talons.ProductFullDetail.useProductFullDetail.wrapWith( - 'src/usePFDIntercept' - ); - talons.App.useApp.wrapWith('src/useAppIntercept'); - talons.App.useApp.wrapWith('src/swedish'); - }); - } -}; -const built = await buildModuleWith('src/index.js', { - context: __dirname, - dependencies: [ - { - name: '@magento/peregrine', - declare, - intercept - }, - talonIntegratingDep - ], - mockFiles: { - 'src/index.js': ` -import { useApp } from '@magento/peregrine/lib/talons/App/useApp'; -import { useProductFullDetail } from '@magento/peregrine/lib/talons/ProductFullDetail/useProductFullDetail'; -export default useApp() + useProductFullDetail()`, - 'src/usePFDIntercept': `export default function usePFDIntercept(original) { return function usePFD() { return 'BEEP >o'; } };`, - 'src/useAppIntercept': `export default function useAppIntercept(original) { - return function useApp() { - return 'o< HONK'; - }; -} -`, - 'src/swedish': `export default function swedish(impl) { -return function() { - return impl().replace("O", "Ö") -} -}` - } -}); - -expect(built.run()).toBe('o< HÖNKBEEP >o'); -``` - -**TODO**: Adapt or generate API doc from JSDoc comments - -## Contributing - -The Targets system does not automatically expose all of the inner workings of PWA dependencies. -It is an "explicit registration" system; to make something public, a developer must specifically create and employ a Target. -Adding or enhancing Targets to our core libraries is one of the best contributions you can make! -It gives a developer the chance to create their "dream API" that solves their business needs, and then to pull request it for possible inclusion into core. - -- **The transformModules target is powerful.** -This very low-level target is a way for dependencies to codemod their own files. -It shares some functionality with the Webpack [module configuration](https://webpack.js.org/configuration/module/), but it is designed to be more distributed and composable than that configuration. -Webpack's API is designed for project owners who have full control over their own source code. -They can design rules that use matching predicates, running all `**/*.js` files through a particular loader chain. -This is an important API and PWA Studio preserves it, but a plugin-driven architecture like Targets requires a different API that is more distributed and encapsulated. -The `transformModules` target builds rules by gathering requirements from multiple dependencies in parallel. -Instead of targeting whole groups of files with regular expressions and predicate functions, `transformModules` requests must target individual files that belong to the requestor's codebase. -Therefore, each file may have its own set of options and overrides. -With this API, `transformModules` enables code changes based on business rules and application logic, rather than the lower-level Webpack paradigm of transpiling and processing different filetypes. - -Where appropriate, consider implementing a new Target using the transformModules target instead of implementing another codemod pathway. -The transformModules target could also be augmented with new abilities! -Currently its features include: - -- The `source` transform type, for changing module source code using custom Webpack loader -- The `babel` transform type, for analyzing or updating a module syntax tree through a custom Babel plugin - -These two options for transforming JavaScript already offer a lot of additional opportunities for new tools. - -Source transforms use Webpack loaders, which can be very general-purpose. -Babel transforms use Babel plugins, which can also be very general-purpose and configurable. -Using these common interfaces, a Target developer can create additional low-level utility Targets that use `transformModules` with a general-purpose Webpack loader or Babel plugin as a `transformModule` -Buildpack offers one custom loader out of the box, for use with the `transformModules` target: the `wrap-esm-loader`. -This loader can be configured to edit the source code of any ES Module to decorate the exports of any module by running them through some other function. -Peregrine uses the Buildpack `transformModules` target plus its `wrap-esm-loader` to expose its individual talon modules for decoration. - -These transform modules can also be highly specific. -VeniaUI implements its own `BabelRouteInjectionPlugin`, a Babel plugin intended only to be used on Venia UI's `Routes` component. -It uses this plugin for its `routes` Target, making one single `transformModules` request to transform the `Routes` component with the `BabelRouteInjectionPlugin`. -A Target developer can create medium or high-level utility Targets by implementing more usage-specific Webpack loaders and Babel plugins, and using `transformModules` to hook them in to the build. - -Another way to contribute to the Targets system would be to propose and/or create additional transform types. -Possibilities: - -- A `postcss` transform type, for manipulating CSS files -- A `dom` transform type, for manipulating HTML, XML, or SVG documents -- A `binary` transform type, for streaming an image file or another asset through some plugin or service -- A `replace` transform type, for replacing a module with another under certain conditions, like a controlled and composable version of Webpack `resolve.alias` -- An `expose` transform type, for making the exports of a module available in a global context - - -### Help Wanted -- Target full Webpack config before creating compiler -- Target UPWARD file -- Target app shell HTML -- Target header, footer, page wrapper elements -- Target style diff --git a/pwa-devdocs/_drafts/pwa-studio-fundamentals/manage-state-with-redux/images/foo-in-the-redux-store.gif b/pwa-devdocs/_drafts/pwa-studio-fundamentals/manage-state-with-redux/images/foo-in-the-redux-store.gif deleted file mode 100644 index d3eaa47dda..0000000000 Binary files a/pwa-devdocs/_drafts/pwa-studio-fundamentals/manage-state-with-redux/images/foo-in-the-redux-store.gif and /dev/null differ diff --git a/pwa-devdocs/_drafts/pwa-studio-fundamentals/manage-state-with-redux/images/foo-redux-actions.gif b/pwa-devdocs/_drafts/pwa-studio-fundamentals/manage-state-with-redux/images/foo-redux-actions.gif deleted file mode 100644 index 18f3a6ff06..0000000000 Binary files a/pwa-devdocs/_drafts/pwa-studio-fundamentals/manage-state-with-redux/images/foo-redux-actions.gif and /dev/null differ diff --git a/pwa-devdocs/_drafts/pwa-studio-fundamentals/manage-state-with-redux/images/redux-store-screenshot.png b/pwa-devdocs/_drafts/pwa-studio-fundamentals/manage-state-with-redux/images/redux-store-screenshot.png deleted file mode 100644 index 1d246452e3..0000000000 Binary files a/pwa-devdocs/_drafts/pwa-studio-fundamentals/manage-state-with-redux/images/redux-store-screenshot.png and /dev/null differ diff --git a/pwa-devdocs/_drafts/pwa-studio-fundamentals/manage-state-with-redux/index.md b/pwa-devdocs/_drafts/pwa-studio-fundamentals/manage-state-with-redux/index.md deleted file mode 100644 index 89dfbd1cf4..0000000000 --- a/pwa-devdocs/_drafts/pwa-studio-fundamentals/manage-state-with-redux/index.md +++ /dev/null @@ -1,259 +0,0 @@ ---- -title: Manage State with Redux ---- - -## Overview - -PWA Studio uses Redux to manage the application state. -If you're not familiar with Redux you should see the [Learn More][] section and -do some of your own research online so you have basic understanding of it. - -In this tutorial we will demonstrate how you can work with Redux and PWA Studio together, -and combine Redux Reducers from the @magento/perigrine library with your own. - -_Note: Recent versions of PWA Studio now also use React Hooks to manage state._ - -### Introduction - -First lets look at how PWA Studio uses Redux by installing the [Redux DevTools][] extension for Chrome. -Once you have it installed, browse to the [Venia storefront][] and explore what it has in it's Redux Store. -![redux store in devtools][] - -Next explore the following files & directories in your project. - -1. _src/store.js_ - This file is responsible for creating a Redux store. It also combines Redux reducers and middlewares. -1. _node_modules/@magento/peregrine/lib/store/reducers_ - Each file in this directory contains a reducer that manages a specific part of the application state. - A reducer updates the application state given the current state and an action object. -1. _node_modules/@magento/peregrine/lib/store/actions_ - This directory contains all Redux action creator definitions. - The files in this directory group the action creators together based on the application feature they affect. -1. _node_modules/@magento/peregrine/lib/store/middleware_ - This directory contains a Redux middleware for development that logs dispatched actions and updated state to the browser console. - This functionality adheres to the [Redux middleware pattern][]. - -### Add to The Redux Store - -Create the file below to add a value to the redux store. - -_src/reducers/foo.js_ - -```javascript -import { handleActions } from 'redux-actions'; - -import actions from '@magento/peregrine/lib/store/actions/app'; // we'll use these actions for now, and create our own one later - -export const name = 'foo'; - -const initialState = { - test: 'lorem ipsum' -}; - -const reducerMap = { - [actions.toggleDrawer]: (state, { payload }) => { - return { - ...state, - test: payload - }; - } -}; - -export default handleActions(reducerMap, initialState); -``` - -Pay note of [handleActions][] which replaces the traditional [switch statement][] often used in Reducers. -Also, we are not using a custom `action` yet, for now we are using the `APP` from the _@magento/peregrine_ library. - -Next Create the following file... - -_src/reducers/index.js_ - -```javascript -import foo from './foo'; - -const reducers = { - foo -}; - -export default reducers; -``` - -Next in your applications _src/store.js_ file update the `import` statements to include your local _reducers_ and combine them with the _reducers_ from @magento/peregrine: - -```javascript -import { combineReducers, createStore } from 'redux'; -import { enhancer, reducers } from '@magento/peregrine'; -import myReducers from './reducers'; - -const rootReducer = combineReducers({ ...reducers, ...myReducers }); - -export default createStore(rootReducer, enhancer); -``` - -Now check to the storefront and you should be able to see foo.test added to the Redux State, open & close the navigation menu and it should update. -![foo in the redux store][] - -### Get from the Redux Store - -We'll display the foo.test value we set in the Redux store in the Foo component we created in a previous tutorial. - -Open the _src/components/Foo/Foo.js_ file and add the following import. - -```javascript -import { connect } from 'react-redux'; -``` - -Now to map the state from redux to your component's `props` replace the export statement with the following: - -```javascript -const mapStateToProps = ({ foo }) => ({ foo }); -export default connect(mapStateToProps)(Foo); -``` - -And lets assign `props.foo` to a `foo` constant in the _Foo.js_ component. - -```javascript -// other code -const Foo = props => { - const { foo } = props; - const classes = mergeClasses(defaultClasses, props.classes); - const [nameText, setNameText] = useState(''); - // other code -``` - -And add the following to your JSX: - -```jsx -

{foo.test}

-``` - -Browse to _/foo.html_ to see _"lorem ipsum"_ you have added to the redux store. - -### Update The Redux Store - -#### Created an Action - -To update the Redux store we first need to add a [redux action][]. - -Add the following files... - -_src/actions/foo/actions.js_ - -```javascript -import { createActions } from 'redux-actions'; - -const prefix = 'FOO'; -const actionTypes = [ - 'UPDATE_TEST' -]; - -export default createActions(...actionTypes, { prefix }); -``` - -_src/actions/foo/asyncActions.js_ - -```javascript -import actions from './actions'; - -export const updateTest = value => async dispatch => - dispatch(actions.updateTest(value)); -``` - -_src/actions/foo/index.js_ - -```javascript -export { default } from './actions'; -export * from './asyncActions'; -``` - -**NOTE:** PWA Studio uses: - -- [createActions][] to create multiple actions at once. -- [async actions][] which are useful when API responses update the redux store. - -#### Update the Reducer with the New Action - -Now that we have our redux action created add it to our reducer, -go to _src/reducers/foo.js_ and change the `import actions` statement to: - -```javascript -import actions from 'src/actions/foo'; -``` - -And in the `reducerMap` change `actions.toggleDrawer` to `actions.updateTest`. - -#### Create a component to update the Redux Store - -Next we'll create a new child component which will use the action above to update the redux store. - -_src/components/Foo/updateRedux.js_ - -```javascript -import React from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { PropTypes } from 'prop-types'; -import { updateTest } from 'src/actions/foo'; - -const updateRedux = props => { - const { test, updateTest } = props; - - return ( - - ); -} - -updateRedux.propTypes = { - test: PropTypes.string, - updateTest: PropTypes.func.isRequired -}; - -const mapDispatchToProps = dispatch => ({ - updateTest: (e) => dispatch(updateTest(e.target.value)) -}); - -export default compose( - connect( - null, - mapDispatchToProps - ) -)(updateRedux); -``` - -Import the above component to the _Foo.js_ Component. - -```javascript -import UpdateRedux from './updateRedux'; -``` - -And add it to the JSX: - -```jsx -
-

The input below is interacting with Redux:

- -

{foo.test}

-``` - -Now test it by typing into the new input box while checking Redux dev tools to see the value in the Redux store update. - -![foo redux actions](./images/foo-redux-actions.gif) - -## Learn More - -- [Getting Started with Redux][] - -[Getting Started with Redux]: https://redux.js.org/introduction/getting-started -[Learn More]: #learn-more -[Redux DevTools]: https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd -[Venia storefront]: https://venia.magento.com/ -[handleActions]: https://redux-actions.js.org/api/handleaction -[switch statement]: https://redux.js.org/basics/reducers#handling-more-actions -[redux action]: https://redux.js.org/basics/actions -[createActions]: https://redux-actions.js.org/api/createaction -[async actions]: https://redux.js.org/advanced/async-actions#async-actions -[Redux middleware pattern]: https://redux.js.org/advanced/middleware/ -[redux store in devtools]: ./images/redux-store-screenshot.png -[foo in the redux store]: ./images/foo-in-the-redux-store.gif -[foo redux actions]: ./images/foo-redux-actions.gif diff --git a/pwa-devdocs/_drafts/pwa-studio-fundamentals/reuse-a-venia-component/index.md b/pwa-devdocs/_drafts/pwa-studio-fundamentals/reuse-a-venia-component/index.md deleted file mode 100644 index 4c1bdae946..0000000000 --- a/pwa-devdocs/_drafts/pwa-studio-fundamentals/reuse-a-venia-component/index.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Reuse a Venia Component ---- - -Here we'll quickly demonstrated how PWA Studio components can be easily reused. - -Import the CategoryList to the Foo component: - -```javascript -import CategoryList from '@magento/venia-ui/lib/components/CategoryList'; -``` - -Next add the following JSX. - -```jsx -
-

Reuse of a the PWA Studio component to render a category list:

- -``` - -Check the storefront of the app to see the _CategoryList_ component rendered. - -## Learn more - -- [Modular components][] - -[Modular components]: {%link venia-pwa-concept/features/modular-components/index.md %} diff --git a/pwa-devdocs/_drafts/pwa-studio-fundamentals/use-magentos-graphql-api/images/graphql-and-apollo-client.png b/pwa-devdocs/_drafts/pwa-studio-fundamentals/use-magentos-graphql-api/images/graphql-and-apollo-client.png deleted file mode 100644 index ee1db15a8b..0000000000 Binary files a/pwa-devdocs/_drafts/pwa-studio-fundamentals/use-magentos-graphql-api/images/graphql-and-apollo-client.png and /dev/null differ diff --git a/pwa-devdocs/_drafts/pwa-studio-fundamentals/use-magentos-graphql-api/index.md b/pwa-devdocs/_drafts/pwa-studio-fundamentals/use-magentos-graphql-api/index.md deleted file mode 100644 index e302957109..0000000000 --- a/pwa-devdocs/_drafts/pwa-studio-fundamentals/use-magentos-graphql-api/index.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Use Magento's GraphQL API with Apollo ---- - -## Overview - -In this tutorial we will demonstrate how PWA Studio uses Apollo Queries to fetch data from the backend. - -## What is Apollo Client - -> Apollo Client is a complete state management library for JavaScript apps. Simply write a GraphQL query, and Apollo Client will take care of requesting and caching your data, as well as updating your UI. -> Fetching data with Apollo Client guides you to structure your code in a predictable, declarative way consistent with modern React best practices. With Apollo, you can build high-quality features faster without the hassle of writing data plumbing boilerplate. -> [https://www.apollographql.com/docs/react/][] - -## GraphQL API with Apollo Demo - -### Create a GraphQL query - -Create the below file: - -_src/queries/getProductData.graphql_ - -```graphql -query GetProductData($sku: String!) { - products (filter: {sku: {eq: $sku}}){ - items { - name, - url_key, - image { - url - } - } - } -} -``` - -### Use Apollo Client Query in a component - -Create a new child component: - -_src/components/Foo/productLink.js_ - -```javascript -import React, { Component } from 'react'; -import { Link } from '@magento/venia-ui/lib/drivers'; - -import { useQuery } from '@apollo/react-hooks'; -import GET_PRODUCT_DATA from '../../queries/getProductData.graphql'; // import the query you created above -import LoadingIndicator from '@magento/venia-ui/lib/components/LoadingIndicator'; - -const productLink = props => { - const { loading, error, data } = useQuery(GET_PRODUCT_DATA, { - variables: { sku: props.sku } - }); - - let result = ''; - - if (error) { - result = 'An error occurred while fetching results.'; - } else if (loading) { - result = ( - - ); - } else if (!data.products.items) { - result = 'No results were found.'; - } else { - result = ( - -
- {data.products.items[0].name} - - ); - } - - return result; -} - -export default productLink; -``` - -Add the `` component to the JSX section of the Foo component. _Don't forget to import it!_ - -Browse to the /foo.html URL in the application. -![graphql and apollo client][] - -## Learn More - -- [React Apollo](https://github.com/apollographql/react-apollo) - -[graphql and apollo client]: ./images/graphql-and-apollo-client.png -[https://www.apollographql.com/docs/react/]: https://www.apollographql.com/docs/react/ diff --git a/pwa-devdocs/_drafts/storybook/index.md b/pwa-devdocs/_drafts/storybook/index.md deleted file mode 100644 index 25d9bc8a02..0000000000 --- a/pwa-devdocs/_drafts/storybook/index.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -title: Storybook testing ---- - - - -[Storybook][] is an independent application that lets you view and test React components outside of a project. -It also serves as a library for all the visual components in a project and how they look in isolation under different conditions. - -Currently, the Peregrine package is the only project set up to use Storybook as a development and testing environment for its components. - -{: .bs-callout .bs-callout-info } -**Note:** -This topic only goes over the basics of using Storybook and how it is integrated with the PWA Studio project. -For more detailed information and topics on Storybook, see the [official Storybook documentation][] site. - -## Where to create Storybook stories - -In PWA Studio, Storybook is configured to look for files in a `__stories__` directory. -This directory should be created in the same directory as components, and -Storybook files should have the same name as the components they test. - -## Writing Storybook stories - -Storybook uses what it calls a **story** to represent a visual test case. -A story contains a single state for a component, and -multiple stories for a component make up a storybook file that the Storybook application uses to present the different states of a component. - -Storybook stories should cover the different visual states and behaviors of a component under different conditions. - -### Add stories - -Use the `storiesOf` module to create a list of stories for a specific component. - -The following code imports the `storiesOf` module and creates a list object for stories for a component called `MyComponent`. - -``` jsx -import { storiesOf } from '@storybook/react'; - -const stories = storiesOf('MyComponent', module); -``` - -Use the `add()` method on the list object to add stories for Storybook. -The method accepts the name of the story as the first parameter and a function that returns the component to render as the second parameter. - -``` jsx -stories.add( - 'MyStory', - () => -); -``` - -### Documentation - -Since Storybook can also be used to generate a reference guide for components, it also includes reference documentation that describe the component and its props. -This documentation lives in a markdown file inside a separate `__docs__` directory. - -Use the `withReadme` module from the `storybook-readme` add-on to include reference documentation with your stories: - -``` jsx -... -import { withReadme } from 'storybook-readme'; -import docs from '../__docs__/MyComponent.md'; -... -... -stories.add( - 'MyStory', - withReadme(docs, () => ) -); -``` - -### Storybook file example - -The following is an example of a Storybook file for the **Price** component: - -``` jsx -import React from 'react'; -import { storiesOf } from '@storybook/react'; -import { withReadme } from 'storybook-readme'; -import Price from '../Price'; -import docs from '../__docs__/Price.md'; - -const stories = storiesOf('Price', module); - -stories.add( - 'USD', - withReadme(docs, () => ) -); - -stories.add( - 'EUR', - withReadme(docs, () => ) -); - -stories.add( - 'JPY', - withReadme(docs, () => ) -); - -stories.add( - 'Custom Styles', - withReadme(docs, () => { - const classes = { - currency: 'curr', - integer: 'int', - decimal: 'dec', - fraction: 'fract' - }; - return ( -
- - -
- ); - }) -); -``` - -## Run the Storybook application - -While the Storybook application is running, you can navigate to it in your browser to view the stories and manually test the components. - -Use the following command in the root directory of the Peregrine package to run Storybook: - -``` sh -yarn run storybook -``` - -This command starts the Storybook application that is accessed through the browser at the following address: - -``` sh -http://localhost:9001/ -``` - -[storybook]: https://storybook.js.org/ -[official storybook documentation]: https://storybook.js.org/basics/introduction/ diff --git a/pwa-devdocs/_drafts/venia-pwa-concept/component/account-details/index.md b/pwa-devdocs/_drafts/venia-pwa-concept/component/account-details/index.md deleted file mode 100644 index 820131c1d4..0000000000 --- a/pwa-devdocs/_drafts/venia-pwa-concept/component/account-details/index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Account details component ---- - -| Description | Reference image | -| -------------------------- | :-------------------------------------------: | -| Account details | ![Account details]{:width="300px"} | -{:style="table-layout:auto"} - -[Account details]: {% link venia-pwa-concept/images/account-details.png %} - - -## Interactions diff --git a/pwa-devdocs/gulpfile.js b/pwa-devdocs/gulpfile.js deleted file mode 100644 index 50fe7da379..0000000000 --- a/pwa-devdocs/gulpfile.js +++ /dev/null @@ -1,3 +0,0 @@ -// Requires -var gulp = require('gulp'); -var jekyll = require('jekyll-tasks')(gulp); \ No newline at end of file diff --git a/pwa-devdocs/package.json b/pwa-devdocs/package.json deleted file mode 100644 index d3522d2edb..0000000000 --- a/pwa-devdocs/package.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "name": "pwa-devdocs", - "private": true, - "version": "7.0.0", - "description": "A documentation site for Magento PWA", - "main": "gulpfile.js", - "dependencies": { - "jquery": "^3.5.0" - }, - "scripts": { - "build": "npm-run-all -s build:js build:css build:reference-doc-snippets build:compatibility-table build:env-var-definition-doc build:html", - "build:compatibility-table": "node scripts/create-compatibility-table.js", - "build:css": "sass --style=compressed src/_scss/main.scss:src/builds/css/main.css", - "build:env-var-definition-doc": "node scripts/create-env-variables-docs", - "build:html": "bundle exec jekyll build --source src -I", - "build:js": "webpack --config webpack.config.js", - "build:production": "npm-run-all -s clean build:js build:css build:reference-doc-snippets build:compatibility-table build:env-var-definition-doc && jekyll build --source src/ --config src/_config.yml,_config-production.yml", - "build:reference-doc-snippets": "node scripts/create-reference-docs", - "clean": "rm -fr _site && rm -fr src/.jekyll-cache && rm -fr src/_includes/auto-generated", - "deploy": "yarn build:production && ./scripts/deploy.sh", - "develop": "yarn build && node scripts/develop.js", - "fix-markdown": "node scripts/fix-markdown.js", - "lint": "node scripts/lint", - "start": "npm-run-all -s clean develop" - }, - "repository": "github:magento/pwa-studio", - "author": "James Calcaben", - "license": "OSL-3.0", - "bugs": { - "url": "https://github.com/magento/pwa-studio/issues" - }, - "homepage": "https://github.com/magento/pwa-studio/tree/master/packages/pwa-devdocs#readme", - "devDependencies": { - "browser-sync": "^2.26.7", - "css-loader": "^2.1.1", - "jsdoc-to-markdown": "^5.0.3", - "mdast-builder": "^1.1.1", - "npm-run-all": "^4.1.5", - "react-docgen": "^3.0.0", - "remark": "^10.0.1", - "remark-frontmatter": "^1.3.2", - "remark-lint": "^6.0.5", - "remark-lint-blockquote-indentation": "^1.0.3", - "remark-lint-code-block-style": "^1.0.3", - "remark-lint-definition-case": "^1.0.4", - "remark-lint-definition-spacing": "^1.0.4", - "remark-lint-emphasis-marker": "^1.0.3", - "remark-lint-fenced-code-flag": "^1.0.3", - "remark-lint-fenced-code-marker": "^1.0.3", - "remark-lint-file-extension": "^1.0.3", - "remark-lint-final-definition": "^1.0.3", - "remark-lint-final-newline": "^1.0.3", - "remark-lint-first-heading-level": "^1.1.4", - "remark-lint-heading-increment": "^1.0.3", - "remark-lint-heading-style": "^1.0.3", - "remark-lint-link-title-style": "^1.0.4", - "remark-lint-list-item-bullet-indent": "^1.0.3", - "remark-lint-list-item-content-indent": "^1.0.3", - "remark-lint-list-item-indent": "^1.0.4", - "remark-lint-maximum-heading-length": "^1.0.3", - "remark-lint-no-blockquote-without-marker": "^2.0.3", - "remark-lint-no-consecutive-blank-lines": "^1.0.3", - "remark-lint-no-duplicate-definitions": "^1.0.5", - "remark-lint-no-duplicate-headings-in-section": "^1.0.4", - "remark-lint-no-emphasis-as-heading": "^1.0.3", - "remark-lint-no-empty-url": "^1.0.5", - "remark-lint-no-file-name-articles": "^1.0.3", - "remark-lint-no-file-name-consecutive-dashes": "^1.0.3", - "remark-lint-no-file-name-irregular-characters": "^1.0.3", - "remark-lint-no-file-name-mixed-case": "^1.0.3", - "remark-lint-no-file-name-outer-dashes": "^1.0.4", - "remark-lint-no-heading-content-indent": "^1.0.3", - "remark-lint-no-heading-like-paragraph": "^1.0.3", - "remark-lint-no-heading-punctuation": "^1.0.3", - "remark-lint-no-inline-padding": "^1.0.4", - "remark-lint-no-literal-urls": "^1.0.3", - "remark-lint-no-missing-blank-lines": "^1.0.3", - "remark-lint-no-paragraph-content-indent": "^1.0.6", - "remark-lint-no-reference-like-url": "^1.0.4", - "remark-lint-no-shortcut-reference-image": "^1.0.3", - "remark-lint-no-shortcut-reference-link": "^1.0.4", - "remark-lint-no-tabs": "^1.0.3", - "remark-lint-no-undefined-references": "^1.1.1", - "remark-lint-no-unused-definitions": "^1.0.5", - "remark-lint-ordered-list-marker-style": "^1.0.3", - "remark-lint-rule-style": "^1.0.3", - "remark-lint-strong-marker": "^1.0.3", - "remark-lint-unordered-list-marker-style": "^1.0.3", - "remark-preset-lint-markdown-style-guide": "^2.1.3", - "sass": "^1.26.3", - "sass-loader": "^7.3.1", - "style-loader": "^0.23.1", - "to-vfile": "^5.0.3", - "vfile-reporter": "^5.1.2", - "webpack": "^4.42.0", - "webpack-cli": "^3.3.11" - }, - "resolutions": { - "minimist": "^1.2.2" - } -} diff --git a/pwa-devdocs/scripts/create-compatibility-table.js b/pwa-devdocs/scripts/create-compatibility-table.js deleted file mode 100644 index 29e3da8288..0000000000 --- a/pwa-devdocs/scripts/create-compatibility-table.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * This script agenerates a PWA Studio to Magento Backend - * compatibility table in markdown. - */ - -const fs = require('fs'); -const path = require('path'); - -const compatibilityDefinitions = require('../../magento-compatibility.js'); - -const outputDirectory = path.resolve('src/_includes/auto-generated'); -const outputFilename = 'magento-compatibility.md'; -const outputFile = path.resolve(outputDirectory, outputFilename); - -/* - * Create a table row for every entry in the definition JSON. - */ -const tableRows = Object.keys(compatibilityDefinitions).reduce((rows, pwaVersion) => { - const magentoVersion = compatibilityDefinitions[pwaVersion]; - - const thisRow = `| ${pwaVersion} | ${magentoVersion} |\n`; - rows += thisRow; - - return rows; -}, ''); - -/* - * Create the contents of the markdown file. - */ -const markdownContents = ` -| PWA Studio version | Magento core version| -| :---: | :---: | -${ tableRows } -`; - -fs.writeFileSync(outputFile, markdownContents); diff --git a/pwa-devdocs/scripts/create-env-variables-docs/generateEnvVarDefinitionDocs.js b/pwa-devdocs/scripts/create-env-variables-docs/generateEnvVarDefinitionDocs.js deleted file mode 100644 index 9fedc36a5b..0000000000 --- a/pwa-devdocs/scripts/create-env-variables-docs/generateEnvVarDefinitionDocs.js +++ /dev/null @@ -1,30 +0,0 @@ -const fs = require('fs'); -const {root} = require('mdast-builder'); -const unified = require('unified'); -const stringify = require('remark-stringify'); -const handleSection = require('./handleSection'); - -/** - * A function for generating markdown content from an envVarDefinitions file - * - * @param {string} filepath The filepath to the envVarDefinitions file - * - * @returns {string} A markdown formatted string containing documentation from data in the envVarDefinitions file - */ -module.exports = filepath => { - const fileContent = JSON.parse(fs.readFileSync(filepath)); - - const {sections} = fileContent; - - let tree = root([]); - - sections.forEach(section => { - tree.children = tree.children.concat(handleSection(section)); - }); - - const processor = unified().use(stringify, {}); - - const result = processor.stringify(tree); - - return result; -}; diff --git a/pwa-devdocs/scripts/create-env-variables-docs/handleSection.js b/pwa-devdocs/scripts/create-env-variables-docs/handleSection.js deleted file mode 100644 index 9f8273d908..0000000000 --- a/pwa-devdocs/scripts/create-env-variables-docs/handleSection.js +++ /dev/null @@ -1,22 +0,0 @@ -const {heading, text} = require('mdast-builder'); -const handleVariable = require('./handleVariable'); - -/** - * Function for handling a section of the envVarDefinition file - * - * @param {object} section An object containing section data such as its name and its variable definitions - * - * @returns {Array} An array of markdown abstract syntax nodes containing the section and variable data - */ -const handleSection = section => { - const {name, variables} = section; - let result = [heading(2, text(name))]; - - variables.forEach(variable => { - result = result.concat(handleVariable(variable)); - }); - - return result; -}; - -module.exports = handleSection; diff --git a/pwa-devdocs/scripts/create-env-variables-docs/handleVariable.js b/pwa-devdocs/scripts/create-env-variables-docs/handleVariable.js deleted file mode 100644 index 8a62842656..0000000000 --- a/pwa-devdocs/scripts/create-env-variables-docs/handleVariable.js +++ /dev/null @@ -1,48 +0,0 @@ -const { - heading, - text, - paragraph, - strong, - inlineCode, -} = require('mdast-builder'); - -/** - * A function for generating a markdown abstract syntax tree (mdast) structure - * for a single environment variable definition - * - * @param {object} variable The environment variable data - * - * @returns {array} An array of mdast nodes containing the environment variable data - */ -const handleVariable = variable => { - const {type, desc, example, default: defaultValue} = variable; - let result = []; - - result.push(heading(3, inlineCode(variable.name))); - - result.push(paragraph([strong(text('Type:')), text(' '), inlineCode(type)])); - - // Include the default value if defined - if (defaultValue) { - result.push( - paragraph([ - strong(text('Default:')), - text(' '), - inlineCode(defaultValue.toString()), - ]), - ); - } - - // Include the example if defined - if (example) { - result.push( - paragraph([strong(text('Example:')), text(' '), inlineCode(example)]), - ); - } - - result.push(paragraph([text(desc)])); - - return result; -}; - -module.exports = handleVariable; diff --git a/pwa-devdocs/scripts/create-env-variables-docs/index.js b/pwa-devdocs/scripts/create-env-variables-docs/index.js deleted file mode 100644 index 6e74689dca..0000000000 --- a/pwa-devdocs/scripts/create-env-variables-docs/index.js +++ /dev/null @@ -1,19 +0,0 @@ -const path = require('path'); -const fs = require('fs'); -const generateEnvVarDefinitionDocs = require('./generateEnvVarDefinitionDocs'); - -const config = { - inputFilepath: path.join( - __dirname, - '../../../packages/pwa-buildpack/envVarDefinitions.json' - ), - outputFilepath: path.join( - __dirname, - '../../src/_includes/auto-generated/buildpack/reference/envVarDefinitions.md' - ) -}; - -const content = generateEnvVarDefinitionDocs(config.inputFilepath); - -fs.mkdirSync(path.dirname(config.outputFilepath), { recursive: true }); -fs.writeFileSync(config.outputFilepath, content); diff --git a/pwa-devdocs/scripts/create-reference-docs/config/buildpack.js b/pwa-devdocs/scripts/create-reference-docs/config/buildpack.js deleted file mode 100644 index 94ddd10d6e..0000000000 --- a/pwa-devdocs/scripts/create-reference-docs/config/buildpack.js +++ /dev/null @@ -1,26 +0,0 @@ -module.exports = [ - { - target: 'pwa-buildpack/lib/BuildBus/declare-base.js', - type: 'function' - }, - { - target: 'pwa-buildpack/lib/WebpackTools/ModuleTransformConfig.js', - type: 'function' - }, - { - target: 'pwa-buildpack/lib/BuildBus/TargetProvider.js', - type: 'function' - }, - { - target: 'pwa-buildpack/lib/BuildBus/BuildBus.js', - type: 'function' - }, - { - target: 'pwa-buildpack/lib/BuildBus/Target.js', - type: 'function' - }, - { - target: 'pwa-buildpack/lib/Utilities/getEnvVarDefinitions.js', - type: 'function' - } -] diff --git a/pwa-devdocs/scripts/create-reference-docs/config/index.js b/pwa-devdocs/scripts/create-reference-docs/config/index.js deleted file mode 100644 index cbfe45687e..0000000000 --- a/pwa-devdocs/scripts/create-reference-docs/config/index.js +++ /dev/null @@ -1,14 +0,0 @@ -const peregrineFiles = require('./peregrine'); -const veniaFiles = require('./venia'); -const pagebuilderFiles = require('./pagebuilder'); -const buildpackFiles = require('./buildpack'); - -let files = [].concat(peregrineFiles, veniaFiles, pagebuilderFiles, buildpackFiles); - -module.exports = { - baseGitHubPath: - 'github.com/magento/pwa-studio/blob/develop/', - packagesPath: 'packages', - includesPath: 'src/_includes/auto-generated', - files: files -}; diff --git a/pwa-devdocs/scripts/create-reference-docs/config/pagebuilder.js b/pwa-devdocs/scripts/create-reference-docs/config/pagebuilder.js deleted file mode 100644 index 0084a4261b..0000000000 --- a/pwa-devdocs/scripts/create-reference-docs/config/pagebuilder.js +++ /dev/null @@ -1,85 +0,0 @@ -module.exports = [ - { - target: - 'pagebuilder/lib/ContentTypes/Products/products.js', - type: 'function' - }, - { - target: - 'pagebuilder/lib/ContentTypes/Tabs/tabs.js', - type: 'function' - }, - { - target: - 'pagebuilder/lib/ContentTypes/TabItem/tabItem.js', - type: 'function' - }, - { - target: - 'pagebuilder/lib/ContentTypes/ButtonItem/buttonItem.js', - type: 'function' - }, - { - target: - 'pagebuilder/lib/ContentTypes/Buttons/buttons.js', - type: 'function' - }, - { - target: - 'pagebuilder/lib/ContentTypes/Slider/slider.js', - type: 'function' - }, - { - target: - 'pagebuilder/lib/ContentTypes/Text/text.js', - type: 'function' - }, - { - target: 'pagebuilder/lib/ContentTypes/Heading/heading.js', - type: 'function' - }, - { - target: 'pagebuilder/lib/ContentTypes/Row/row.js', - type: 'function' - }, - { - target: 'pagebuilder/lib/ContentTypes/Video/video.js', - type: 'function' - }, - { - target: 'pagebuilder/lib/ContentTypes/ColumnGroup/columnGroup.js', - type: 'function' - }, - { - target: 'pagebuilder/lib/ContentTypes/Column/column.js', - type: 'function' - }, - { - target: 'pagebuilder/lib/ContentTypes/Block/block.js', - type: 'function' - }, - { - target: 'pagebuilder/lib/ContentTypes/Html/html.js', - type: 'function' - }, - { - target: 'pagebuilder/lib/ContentTypes/Divider/divider.js', - type: 'function' - }, - { - target: 'pagebuilder/lib/ContentTypes/Image/image.js', - type: 'function' - }, - { - target: 'pagebuilder/lib/ContentTypes/Map/map.js', - type: 'function' - }, - { - target: 'pagebuilder/lib/ContentTypes/Banner/banner.js', - type: 'function' - }, - { - target: 'pagebuilder/lib/utils.js', - type: 'function' - } -]; diff --git a/pwa-devdocs/scripts/create-reference-docs/config/peregrine.js b/pwa-devdocs/scripts/create-reference-docs/config/peregrine.js deleted file mode 100644 index 9f14908805..0000000000 --- a/pwa-devdocs/scripts/create-reference-docs/config/peregrine.js +++ /dev/null @@ -1,46 +0,0 @@ -module.exports = [ - { - target: 'peregrine/lib/Price/price.js', - type: 'class' - }, - { - target: 'peregrine/lib/List/list.js', - type: 'class', - overrides: { - items: { - required: true - }, - render: { - required: true - } - } - }, - { - target: 'peregrine/lib/hooks/useEventListener.js', - type: 'function' - }, - { - target: 'peregrine/lib/hooks/useDropdown.js', - type: 'function' - }, - { - target: 'peregrine/lib/hooks/useWindowSize.js', - type: 'function' - }, - { - target: 'peregrine/lib/hooks/useSearchParam.js', - type: 'function' - }, - { - target: 'peregrine/lib/hooks/usePagination.js', - type: 'function' - }, - { - target: 'peregrine/lib/Toasts/useToastContext.js', - type: 'function' - }, - { - target: 'peregrine/lib/Toasts/useToasts.js', - type: 'function' - } -]; diff --git a/pwa-devdocs/scripts/create-reference-docs/config/venia.js b/pwa-devdocs/scripts/create-reference-docs/config/venia.js deleted file mode 100644 index 6169b1c164..0000000000 --- a/pwa-devdocs/scripts/create-reference-docs/config/venia.js +++ /dev/null @@ -1,38 +0,0 @@ -module.exports = [ - { - target: 'venia-ui/lib/components/RichContent/richContent.js', - type: 'function' - }, - { - target: 'venia-ui/lib/components/ToastContainer/toastContainer.js', - type: 'function' - }, - { - target: 'venia-ui/lib/components/Button/button.js', - type: 'function' - }, - { - target: 'venia-ui/lib/components/ButtonGroup/buttonGroup.js', - type: 'function' - }, - { - target: 'venia-ui/lib/components/Logo/logo.js', - type: 'function' - }, - { - target: 'venia-ui/lib/components/Mask/mask.js', - type: 'function' - }, - { - target: 'venia-ui/lib/components/Portal/portal.js', - type: 'function' - }, - { - target: 'venia-ui/lib/components/ProductImageCarousel/carousel.js', - type: 'function' - }, - { - target: 'venia-ui/lib/components/Trigger/trigger.js', - type: 'function' - } -]; diff --git a/pwa-devdocs/scripts/create-reference-docs/createClassDocs.js b/pwa-devdocs/scripts/create-reference-docs/createClassDocs.js deleted file mode 100644 index d3bc94ec92..0000000000 --- a/pwa-devdocs/scripts/create-reference-docs/createClassDocs.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Uses the react-docgen library to generate React class docs - */ -const reactDocs = require('react-docgen'); -const fs = require('fs'); - -const templates = require('./templates'); - -let createClassDocs = ({ sourcePath, overrides, githubSource }) => { - return new Promise((resolve, reject) => { - let content = fs.readFileSync(sourcePath); - let componentInfo = reactDocs.parse(content); - let { description, props } = componentInfo; - - let fileContent = templates.classDocs({ - description, - githubSource, - props, - propsOverrides: overrides - }); - - if (fileContent) { - resolve(fileContent); - } else { - reject(Error('Could not generate docs content', sourcePath)); - } - }); -}; - -module.exports = createClassDocs; diff --git a/pwa-devdocs/scripts/create-reference-docs/createFunctionDocs.js b/pwa-devdocs/scripts/create-reference-docs/createFunctionDocs.js deleted file mode 100644 index 527b4926ef..0000000000 --- a/pwa-devdocs/scripts/create-reference-docs/createFunctionDocs.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Uses the jsdoc-to-markdown library to generate function docs - */ -const jsDocs = require('jsdoc-to-markdown'); - -let createFunctionDocs = ({ sourcePath, githubSource }) => { - return jsDocs.render({ files: [sourcePath] }).then(content => { - return new Promise((resolve, reject) => { - if (!content) { - reject(Error('Could not generate content', sourcePath)); - } else { - resolve( - `${content}\n\nFor implementation details [**View Source**](${githubSource}).` - ); - } - }); - }); -}; - -module.exports = createFunctionDocs; diff --git a/pwa-devdocs/scripts/create-reference-docs/index.js b/pwa-devdocs/scripts/create-reference-docs/index.js deleted file mode 100644 index f89662ce1d..0000000000 --- a/pwa-devdocs/scripts/create-reference-docs/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Create reference content from source code. - * Content is placed inside the _includes folder to be used in actual topic files. - **/ - -const process = require('process'); -const fs = require('fs'); -const path = require('path'); - -const config = require('./config'); -const createClassDocs = require('./createClassDocs'); -const createFunctionDocs = require('./createFunctionDocs'); - -const docsProjectRoot = process.cwd(); - -config.files.forEach(file => { - let { target, overrides } = file; - - let sourcePath = path.join( - path.dirname(docsProjectRoot), - config.packagesPath, - target - ); - - let githubSource = "https://"+ path.join( - config.baseGitHubPath, - config.packagesPath, - target - ); - - let fileDestination = path.join( - docsProjectRoot, - config.includesPath, - path.join(path.dirname(target), path.basename(target, '.js')) + '.md' - ); - - switch (file.type) { - case 'class': - createClassDocs({ sourcePath, overrides, githubSource }).then( - fileContent => { - writeToFile(fileDestination, fileContent); - } - ); - break; - - case 'function': - createFunctionDocs({ sourcePath, githubSource }).then( - fileContent => { - writeToFile(fileDestination, fileContent); - } - ); - break; - - default: - break; - } -}); - -const writeToFile = (fileDestination, fileContent) => { - if (fileContent) { - console.log( - '> Generating reference docs: ' + - path.relative(docsProjectRoot, fileDestination) - ); - - fs.mkdirSync(path.dirname(fileDestination), { recursive: true }); - - fs.writeFileSync(fileDestination, fileContent); - } else { - console.error('> Skipping empty file content for', target); - } -}; diff --git a/pwa-devdocs/scripts/create-reference-docs/templates/index.js b/pwa-devdocs/scripts/create-reference-docs/templates/index.js deleted file mode 100644 index 09d06e518d..0000000000 --- a/pwa-devdocs/scripts/create-reference-docs/templates/index.js +++ /dev/null @@ -1,5 +0,0 @@ -const renderClassDocs = require('./renderClassDocs'); - -module.exports = { - classDocs: renderClassDocs, -}; diff --git a/pwa-devdocs/scripts/create-reference-docs/templates/renderClassDocs.js b/pwa-devdocs/scripts/create-reference-docs/templates/renderClassDocs.js deleted file mode 100644 index 61a542665f..0000000000 --- a/pwa-devdocs/scripts/create-reference-docs/templates/renderClassDocs.js +++ /dev/null @@ -1,69 +0,0 @@ -const requiredProp = 'check_box'; - -/** - * Function for overriding template props - */ -const overrideProps = (props, propsOverrides) => { - if (!propsOverrides) { - return props; - } - const result = Object.assign({}, props, propsOverrides); - - return result; -}; - -/** - * Function for rendering a prop entry - */ -const renderPropEntry = ({ key, required, defaultValue, propDescription }) => { - return `| \`${key}\` | ${required} | ${defaultValue} | ${propDescription}|\n`; -}; - -/** - * Function for generating the table for props - */ -const renderClassPropsTable = props => { - let result = `## Props\n\n `; - - const propsKeys = Object.keys(props); - - if (propsKeys.length > 0) { - result += - '|Name|Required|Default|Description|\n|---|:---:|:---:|---|\n'; - - propsKeys.forEach(key => { - let prop = props[key]; - - result += renderPropEntry({ - key: key, - required: prop.required ? requiredProp : '`-`', - defaultValue: prop.defaultValue - ? `\`${prop.defaultValue.value}\`` - : '`-`', - propDescription: prop.description ? prop.description : '`-`' - }); - }); - } - result += '{:style="table-layout:auto"}\n'; - - return result; -}; - -/** - * Main render function - */ -const renderClassDocs = ({ - description, - props, - propsOverrides, - githubSource -}) => { - return `${description} - -[View Source](${githubSource}) - -${renderClassPropsTable(overrideProps(props, propsOverrides))} -`; -}; - -module.exports = renderClassDocs; diff --git a/pwa-devdocs/scripts/deploy.sh b/pwa-devdocs/scripts/deploy.sh deleted file mode 100755 index ce223f054d..0000000000 --- a/pwa-devdocs/scripts/deploy.sh +++ /dev/null @@ -1,20 +0,0 @@ -#! /bin/bash - -# This script requires you to set TARGET_REPO and TARGET_BRANCH environment variables in a .env file - -source .env - -rm -fr /tmp/gh-pages -git init /tmp/gh-pages - -mv _site/* /tmp/gh-pages - -cd /tmp/gh-pages - -git checkout -b $TARGET_BRANCH - -git remote add origin $TARGET_REPO -git add . -git commit -m "HTML Generated" - -git push -f origin $TARGET_BRANCH diff --git a/pwa-devdocs/scripts/develop.js b/pwa-devdocs/scripts/develop.js deleted file mode 100644 index c43b702370..0000000000 --- a/pwa-devdocs/scripts/develop.js +++ /dev/null @@ -1,25 +0,0 @@ -const { exec } = require('child_process'); - -const workspace = require('browser-sync').create('workspace'); -const site = require('browser-sync').create('site'); - -function fileChangeHandler(_filesChanged) { - console.log('\nFile(s) change. Rebuilding...'); - exec('npm run build', buildCallback); -} - -function buildCallback(_error, stdout, _stderr) { - console.log(stdout); - site.reload(); -} - -workspace - .watch('./src/**/*.md', { ignored: /.*\/auto-generated\/.*/}) - .on('change', fileChangeHandler); -workspace.watch('./src/**/*.html').on('change', fileChangeHandler); -workspace.watch('./src/_scss/**/*.scss').on('change', fileChangeHandler); -workspace.watch('./src/_js/**/*.js').on('change', fileChangeHandler); - -site.init({ - server: './_site' -}); diff --git a/pwa-devdocs/scripts/fix-markdown.js b/pwa-devdocs/scripts/fix-markdown.js deleted file mode 100644 index d111c1cc7f..0000000000 --- a/pwa-devdocs/scripts/fix-markdown.js +++ /dev/null @@ -1,19 +0,0 @@ -const { fixer: fixMarkdown, linter: lint } = require('./markdown-linter'); -const process = require('process'); -const path = require('path'); - -const filepath = process.argv[2]; -const fullPath = path.join(path.dirname(__dirname), filepath); - -console.log('\x1b[34m', 'Formatting: ', filepath, '\x1b[0m'); - -fixMarkdown(fullPath).then(() => { - console.log( - '\x1b[32m', - 'Complete!', - '\x1b[33m', - 'Any remaining formatting issues will need manual fixing.\n', - '\x1b[0m' - ); - lint(fullPath); -}); diff --git a/pwa-devdocs/scripts/lint/index.js b/pwa-devdocs/scripts/lint/index.js deleted file mode 100644 index 3498c8615d..0000000000 --- a/pwa-devdocs/scripts/lint/index.js +++ /dev/null @@ -1,54 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const linter = require('../markdown-linter').linter; -const process = require('process'); - -const config = { - basePath: path.join(__dirname, '../../src') -}; - -// If a file or directory is specified, only run tests on that file or directory -const filepath = process.argv[2]; -if (filepath) { - const fullPath = path.join(__dirname, '..', '..', filepath); - - fs.stat(fullPath, (error, stats) => { - if (error) { - console.error(error); - } else if (stats.isFile()) { - lintFile(fullPath); - } else if (stats.isDirectory()) { - lintDirectory(fullPath); - } else { - console.error( - 'ERROR:', - filepath, - 'is neither a file nor directory' - ); - } - }); -} else { - lintDirectory(config.basePath); -} - -// Run tests on all markdown files found under the specified directory -function lintDirectory(directoryPath) { - fs.promises - .readdir(directoryPath, { withFileTypes: true }) - .then(filenames => { - filenames.forEach(file => { - const fullPath = path.join(directoryPath, file.name); - if (file.isDirectory()) { - lintDirectory(fullPath); - } else if (file.isFile() && path.extname(fullPath) === '.md') { - lintFile(fullPath); - } - }); - }); -} - -// Run all tests on a single file -function lintFile(filepath) { - // Run linter - linter(filepath); -} diff --git a/pwa-devdocs/scripts/markdown-linter/index.js b/pwa-devdocs/scripts/markdown-linter/index.js deleted file mode 100644 index 1a52e7944e..0000000000 --- a/pwa-devdocs/scripts/markdown-linter/index.js +++ /dev/null @@ -1,24 +0,0 @@ -const linter = require('./linter'); -const fs = require('fs'); -const report = require('vfile-reporter'); - -module.exports = { - linter: filepath => { - linter(filepath) - .then(file => { - console.log(report(file)); - }) - .catch(error => { - console.log(error); - }); - }, - fixer: filepath => { - return linter(filepath) - .then(file => { - return fs.promises.writeFile(filepath, String(file), 'utf8'); - }) - .catch(error => { - console.log(error); - }); - } -}; diff --git a/pwa-devdocs/scripts/markdown-linter/linter.js b/pwa-devdocs/scripts/markdown-linter/linter.js deleted file mode 100644 index fb6871f8b8..0000000000 --- a/pwa-devdocs/scripts/markdown-linter/linter.js +++ /dev/null @@ -1,15 +0,0 @@ -const remark = require('remark'); -const styleGuide = require('./style-guide'); -const vfile = require('to-vfile'); -const jekyllLinkTokenizer = require('./tokenizers').jekyllLink - -const linter = filepath => { - return vfile.read(filepath).then(vfile => { - return remark() - .use(styleGuide) - .use(jekyllLinkTokenizer) - .process(vfile); - }); -}; - -module.exports = linter; diff --git a/pwa-devdocs/scripts/markdown-linter/style-guide.js b/pwa-devdocs/scripts/markdown-linter/style-guide.js deleted file mode 100644 index 6c1fb06eef..0000000000 --- a/pwa-devdocs/scripts/markdown-linter/style-guide.js +++ /dev/null @@ -1,98 +0,0 @@ -module.exports.plugins = [ - require('remark-lint'), - require('remark-frontmatter'), - - // Blockquotes must be indented twice - [require('remark-lint-blockquote-indentation'), [1, 2]], - // Code blocks need to be fenced, not indented - [require('remark-lint-code-block-style'), [1, 'fenced']], - // Definitions must be in lowercase - require('remark-lint-definition-case'), - // No consecutive white spaces between definitions - require('remark-lint-definition-spacing'), - // Use underscore for emphasis - [require('remark-lint-emphasis-marker'), [1, '_']], - // Fenced code blocks must have a language associated with it - require('remark-lint-fenced-code-flag'), - // Use backticks (`) for code fences - [require('remark-lint-fenced-code-marker'), [1, '`']], - // Markdown files must use the 'md' file extension - require('remark-lint-file-extension'), - // Definitions must be placed at the end of the file - require('remark-lint-final-definition'), - // Files must have a newline at the end for consistency/predictability - // See: https://unix.stackexchange.com/questions/18743/whats-the-point-in-adding-a-new-line-to-the-end-of-a-file - require('remark-lint-final-newline'), - // Headings start at level 2 - [require('remark-lint-first-heading-level'), [1, 2]], - // Headings should increment sequentially - require('remark-lint-heading-increment'), - // Use 'atx' style headings - [require('remark-lint-heading-style'), [1, 'atx']], - // Use double quotes for link title styles - [require('remark-lint-link-title-style'), [1, '"']], - // Do not indent bullets - require('remark-lint-list-item-bullet-indent'), - // Do not use mixed indentations in lists - require('remark-lint-list-item-content-indent'), - // Use tab-size to separate list bullet and content - require('remark-lint-list-item-indent'), - // Headers should be limited to 60 characters - [require('remark-lint-maximum-heading-length'), [1, 60]], - // Block quotes require a marker on blank lines - require('remark-lint-no-blockquote-without-marker'), - // No consecutive blank lines - require('remark-lint-no-consecutive-blank-lines'), - // No duplicate definitions - require('remark-lint-no-duplicate-definitions'), - // No duplicate headings in the same heading section - require('remark-lint-no-duplicate-headings-in-section'), - // Do not use emphasis as a paragraph heading - require('remark-lint-no-emphasis-as-heading'), - // Do not use empty url links - require('remark-lint-no-empty-url'), - // Do not start filenames with an article - require('remark-lint-no-file-name-articles'), - // No consecutive dashes in file names - require('remark-lint-no-file-name-consecutive-dashes'), - // No irregular characters in file names - require('remark-lint-no-file-name-irregular-characters'), - // No mixed case file names - require('remark-lint-no-file-name-mixed-case'), - // No outer dashes in file names - require('remark-lint-no-file-name-outer-dashes'), - // Use a single space to indent headings - require('remark-lint-no-heading-content-indent'), - // No heading level greater than 6 - require('remark-lint-no-heading-like-paragraph'), - // Do not punctuate headings - require('remark-lint-no-heading-punctuation'), - // Do not add padding to inline markdown nodes - require('remark-lint-no-inline-padding'), - // Use angle brackets for literal URLs - require('remark-lint-no-literal-urls'), - // Use blank lines to separate content blocks - require('remark-lint-no-missing-blank-lines'), - // Do not indent paragraph content - require('remark-lint-no-paragraph-content-indent'), - // Do not use reference ids as URL - require('remark-lint-no-reference-like-url'), - // Use trailing [] on image references - require('remark-lint-no-shortcut-reference-image'), - // Use trailing [] on link references - require('remark-lint-no-shortcut-reference-link'), - // Use spaces instead of hard tabs - require('remark-lint-no-tabs'), - // All references must have a definition - require('remark-lint-no-undefined-references'), - // All definitions must be referenced - require('remark-lint-no-unused-definitions'), - // List item markers must use '.' - [require('remark-lint-ordered-list-marker-style'), [1, '.']], - // Use '---' for horizontal rules - [require('remark-lint-rule-style'), [1, '---']], - // Use '**' as a strong marker - [require('remark-lint-strong-marker'), [1, '*']], - // Use a minus ('-') for unordered lists - [require('remark-lint-unordered-list-marker-style'), [1, '-']] -]; diff --git a/pwa-devdocs/scripts/markdown-linter/tokenizers/index.js b/pwa-devdocs/scripts/markdown-linter/tokenizers/index.js deleted file mode 100644 index 31098e114f..0000000000 --- a/pwa-devdocs/scripts/markdown-linter/tokenizers/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - jekyllLink: require('./jekyll-link') -} diff --git a/pwa-devdocs/scripts/markdown-linter/tokenizers/jekyll-link.js b/pwa-devdocs/scripts/markdown-linter/tokenizers/jekyll-link.js deleted file mode 100644 index e344a92f4b..0000000000 --- a/pwa-devdocs/scripts/markdown-linter/tokenizers/jekyll-link.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * A remark-parse tokenizer to add support for jekyll style link definitions - * These definitions have spaces in the link and are not correctly parsed - * - * For more information see: - * - https://github.com/remarkjs/remark/tree/master/packages/remark-parse#extending-the-parser - */ - -const TOKENIZER_NAME = 'jekyllLinkDefinition'; - -function jekyllLinkDefinition() { - const Parser = this.Parser; - const tokenizers = Parser.prototype.inlineTokenizers; - const methods = Parser.prototype.inlineMethods; - - // Add a new inline tokenizer - tokenizers[TOKENIZER_NAME] = tokenizer; - - // Run it just before the `link` tokenizer. - methods.splice(methods.indexOf('link'), 0, TOKENIZER_NAME); -} - -/** - * The tokenizer function to use during parsing - * @param eat (function) A function used for consuming parts of a string and returning - * a function for adding a node to a syntax tree - * @param value (string) A value that may contain the value we are looking for - * @param silent (boolean) Whether the parser should just detect the existence of the pattern - * or also consume it - */ -function tokenizer(eat, value, silent) { - // This regex checks to see if a value looks like a markdown link definition - // Example: [link definition]: {% link /some/topic/index.md %} - const match = /^\[([^\]]+)\]:\s?(.*)/.exec(value); - - if (match) { - if (silent) { - return true; - } - - // Create new definition node based on captured values - // See: https://github.com/syntax-tree/mdast#definition - let newNode = { - type: 'definition', - identifier: match[1], - label: match[1], - url: match[2] - }; - - // Consume the matching text from value (returns a function for adding a new node) - // See: https://github.com/remarkjs/remark/tree/master/packages/remark-parse#eatsubvalue - const add = eat(match[0]); - - // Add the new node to the currently processed node - // See: https://github.com/remarkjs/remark/tree/master/packages/remark-parse#addnode-parent - return add(newNode); - } -} - -// Add a locator for the tokenizer. This is required for inline tokenizers. -// See: https://github.com/remarkjs/remark/tree/master/packages/remark-parse#tokenizerlocatorvalue-fromindex -tokenizer.locator = (value, fromIndex) => { - return value.indexOf('[', fromIndex); -}; - -module.exports = jekyllLinkDefinition; diff --git a/pwa-devdocs/src/.editorconfig b/pwa-devdocs/src/.editorconfig deleted file mode 100644 index c56c723990..0000000000 --- a/pwa-devdocs/src/.editorconfig +++ /dev/null @@ -1,15 +0,0 @@ -# editorconfig.org - -root = true - -[*] -indent_style = space -indent_size = 2 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.py] -indent_style = space -indent_size = 4 \ No newline at end of file diff --git a/pwa-devdocs/src/404.md b/pwa-devdocs/src/404.md deleted file mode 100644 index 1c5e9b2d09..0000000000 --- a/pwa-devdocs/src/404.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -layout: full-width -title: Page Not Found -menu_order: 1 -permalink: /404.html ---- - -The page you are looking for could not be found or the documentation does not exist. - -To report a missing page, please submit an issue in our public [GitHub]({{ site.github_repo }}) repo. - -[Return to main page]({{site.baseurl}}/) diff --git a/pwa-devdocs/src/_config.yml b/pwa-devdocs/src/_config.yml deleted file mode 100644 index 74155d1848..0000000000 --- a/pwa-devdocs/src/_config.yml +++ /dev/null @@ -1,93 +0,0 @@ -title: Magento PWA Documentation -description: Everything you need to build a Magento PWA. - -source: src - -theme: devdocs -logo: PWA Docs - -plugins: - - jekyll-redirect-from - - -defaults: - - - scope: - path: "" - values: - layout: "default" - github_link: true - feedback_link: true - github_repo: "https://github.com/magento/pwa-studio/" - github_files: "https://github.com/magento/pwa-studio/tree/develop/" - - - scope: - path: "technologies" - values: - toc-group: "getting-started" - - - scope: - path: "pwa-buildpack" - values: - toc-group: "getting-started" - - - scope: - path: "frequently-asked-questions" - values: - toc-group: "getting-started" - - - - scope: - path: "pwa-buildpack/reference" - values: - toc-group: "buildpack-api" - - - - scope: - path: "pagebuilder" - values: - toc-group: "pagebuilder" - - - - scope: - path: "peregrine" - values: - toc-group: "getting-started" - - - - scope: - path: "peregrine/reference" - values: - toc-group: "peregrine-api" - - - - scope: - path: "venia-pwa-concept" - values: - toc-group: "getting-started" - - - scope: - path: "venia-ui/reference" - values: - toc-group: "venia-api" - - - scope: - path: "tutorials" - values: - toc-group: "tutorials" - -algolia: - application_id: 'E642SEDTHL' - index_name: 'pwa-devdocs' - api_key: 'd2d0f33ab73e291ef8d88d8b565e754c' - lazy_update: true - excluded_files: - - vagrant - - common - - js - - i - - schemas - - static - -google: - gtm: GTM-KRCLXBB diff --git a/pwa-devdocs/src/_data/buildpack-api.yml b/pwa-devdocs/src/_data/buildpack-api.yml deleted file mode 100644 index 7e6115e655..0000000000 --- a/pwa-devdocs/src/_data/buildpack-api.yml +++ /dev/null @@ -1,94 +0,0 @@ -title: PWA Buildpack API -entries: - - label: Extension points - entries: - - label: Targets - url: /pwa-buildpack/reference/targets/ - - label: EnvVarDefinitions - url: /pwa-buildpack/reference/environment-variables/definitions-api/ - - label: Transform Requests - url: /pwa-buildpack/reference/transform-requests/ - # # TODO: when i document this - # - label: WrapEsmLoader - # url: /pwa-buildpack/reference/webpack-tools/loaders/wrap-esm-loader/ - - - label: Extension framework - entries: - - label: BuildBus - url: /pwa-buildpack/reference/extension-framework/ - entries: - - label: Target - url: /pwa-buildpack/reference/extension-framework/target/ - - label: TargetProvider - url: /pwa-buildpack/reference/extension-framework/targetprovider/ - # # TODO: when i document this - # - label: BuildBusPlugin - # url: /pwa-buildpack/reference/webpack-tools/plugins/buildbusplugin - - - - label: Command line interface - entries: - - label: Using the CLI - url: /pwa-buildpack/reference/buildpack-cli/ - - - label: Create custom origin - url: /pwa-buildpack/reference/buildpack-cli/create-custom-origin/ - - - label: Create environment file - url: /pwa-buildpack/reference/buildpack-cli/create-env-file/ - - - label: Create project - url: /pwa-buildpack/reference/buildpack-cli/create-project/ - - - label: Load environment file - url: /pwa-buildpack/reference/buildpack-cli/load-env/ - - - label: Developer utilities - entries: - - label: loadEnvironment - url: /pwa-buildpack/reference/buildpack-cli/load-env/#programmatic-api - - - label: createDotEnvFile - url: /pwa-buildpack/reference/buildpack-cli/load-env/#programmatic-api - - - label: getEnvVarDefinitions - url: /pwa-buildpack/reference/environment-variables/definitions-api/ - # # TODO: when I document this - # - # - label: configureHost - # url: /pwa-buildpack/reference/utilities/configurehost - # - # - label: addImgOptMiddleware - # url: /pwa-buildpack/reference/utilities/addimgoptmiddleware/ - - - label: Webpack tools - entries: - - label: configureWebpack - url: /pwa-buildpack/reference/configure-webpack - - - label: MagentoResolver - url: /pwa-buildpack/reference/magento-resolver/ - - - label: MagentoRootComponentsPlugin - url: /pwa-buildpack/reference/root-components-plugin/ - - - label: PWADevServer - url: /pwa-buildpack/reference/pwa-dev-server/ - - - label: ServiceWorkerPlugin - url: /pwa-buildpack/reference/serviceworker-plugin/ - # # TODO: when I document this - # - # - label: UpwardIncludePlugin - # url: /pwa-buildpack/reference/webpack-tools/upward-include-plugin - # - # - label: UpwardDevServerPlugin - # url: /pwa-buildpack/reference/webpack-tools/upward-dev-server-plugin - - - label: Environment configuration - entries: - - label: Variable definition API - url: /pwa-buildpack/reference/environment-variables/definitions-api/ - - - label: Core variable definitions - url: /pwa-buildpack/reference/environment-variables/core-definitions/ diff --git a/pwa-devdocs/src/_data/getting-started.yml b/pwa-devdocs/src/_data/getting-started.yml deleted file mode 100644 index 27cdc0e0f5..0000000000 --- a/pwa-devdocs/src/_data/getting-started.yml +++ /dev/null @@ -1,98 +0,0 @@ -title: Getting Started -entries: - - label: Overview - url: /technologies/overview/ - - - label: Frequently Asked Questions (FAQ) - url: /frequently-asked-questions/ - - - label: Tools and libraries - url: /technologies/tools-libraries/ - - - label: Magento integration - entries: - - label: Magento compatibility - url: /technologies/magento-compatibility/ - - - label: Magento theme vs PWA storefront - url: /technologies/theme-vs-storefront/ - - - label: PWA Storefront architecture - url: /technologies/storefront-architecture/ - entries: - - label: Runtime architecture - url: /technologies/storefront-architecture/runtime/ - - - label: Build-time architecture - url: /technologies/storefront-architecture/buildtime/ - - - label: Basic concepts - url: /technologies/basic-concepts/ - entries: - - label: Application shell - url: /technologies/basic-concepts/app-shell/ - - - label: Content rendering - url: /technologies/basic-concepts/content-rendering/ - - - label: CSS modules - url: /technologies/basic-concepts/css-modules/ - - - label: GraphQL - url: /technologies/basic-concepts/graphql/ - - - label: Client-side caching - url: /technologies/basic-concepts/client-side-caching/ - - - label: State management - url: /technologies/basic-concepts/state-management/ - - - label: PWA Buildpack - url: /pwa-buildpack/ - entries: - - label: Configuration management - url: /pwa-buildpack/configuration-management/ - - - label: Scaffolding - url: /pwa-buildpack/scaffolding/ - - - label: Custom project templates - url: /pwa-buildpack/scaffolding/custom-project-templates/ - - - label: Troubleshooting - url: /pwa-buildpack/troubleshooting/ - - - label: Peregrine - url: /peregrine/ - entries: - - label: Talons - url: /peregrine/talons/ - - label: Routing in PWA Studio - url: /peregrine/routing/ - - - label: Venia storefront concept - url: /venia-pwa-concept/ - entries: - - label: Storefront setup - url: /venia-pwa-concept/setup/ - - - label: Install Venia sample data - url: /venia-pwa-concept/install-sample-data/ - - - label: Project structure - url: /venia-pwa-concept/project-structure/ - - - label: Modular components - url: /venia-pwa-concept/features/modular-components/ - - - label: UPWARD - url: /technologies/upward/ - entries: - - label: Reference implementation - url: /technologies/upward/reference-implementation/ - - - label: Versioning strategy - url: /technologies/versioning/ - - - label: Contributing to PWA Studio - url: /technologies/contribute/ diff --git a/pwa-devdocs/src/_data/home-sections.yml b/pwa-devdocs/src/_data/home-sections.yml deleted file mode 100644 index ef21fea73c..0000000000 --- a/pwa-devdocs/src/_data/home-sections.yml +++ /dev/null @@ -1,23 +0,0 @@ -- title: Overview - content: The Magento PWA Studio project is a set of developer tools that allow you to develop, deploy, and maintain a PWA storefront on top of Magento 2. - url: /technologies/overview/ - -- title: Tutorials - content: Step-by-step instructions to help you become familiar with PWA Studio tools and concepts. - url: /tutorials/pwa-studio-fundamentals/ - -- title: Basic Concepts - content: Things you need to know to work with the Magento PWA Studio tools. - url: /technologies/basic-concepts/ - -- title: Theme vs Storefront - content: Learn the differences between a Magento theme and a PWA Studio storefront. - url: /technologies/theme-vs-storefront/ - -- title: Contribute to this project - content: Read our Contribution Guidelines to find out how you can help develop this project. - url: /technologies/contribute/ - -- title: Release notes - content: Read about new features and changes in the latest PWA Studio release. - url: /releases/ diff --git a/pwa-devdocs/src/_data/pagebuilder.yml b/pwa-devdocs/src/_data/pagebuilder.yml deleted file mode 100644 index 983cb08aa8..0000000000 --- a/pwa-devdocs/src/_data/pagebuilder.yml +++ /dev/null @@ -1,77 +0,0 @@ -title: Page Builder -entries: - - label: Integration - url: /pagebuilder/ - - - label: Known limitations - url: /pagebuilder/known-limitations/ - - - label: Creating custom components - entries: - - label: Overview - url: /pagebuilder/custom-components/overview/ - - - label: Set up component - url: /pagebuilder/custom-components/setup-component/ - - - label: Add aggregator - url: /pagebuilder/custom-components/add-aggregator/ - - - label: Add stylesheet - url: /pagebuilder/custom-components/add-stylesheet/ - - - label: Add component - url: /pagebuilder/custom-components/add-component/ - - - label: Debugging tips - url: /pagebuilder/custom-components/debugging/ - - - label: Utility functions - url: /pagebuilder/utility-functions/ - - - label: Components - entries: - - label: Banner - url: /pagebuilder/components/banner/ - - - label: Block - url: /pagebuilder/components/block/ - - - label: Buttons - url: /pagebuilder/components/buttons/ - - - label: Column - url: /pagebuilder/components/column/ - - - label: Divider - url: /pagebuilder/components/divider/ - - - label: Heading - url: /pagebuilder/components/heading/ - - - label: HTML Code - url: /pagebuilder/components/html/ - - - label: Image - url: /pagebuilder/components/image/ - - - label: Map - url: /pagebuilder/components/map/ - - - label: Products - url: /pagebuilder/components/products/ - - - label: Row - url: /pagebuilder/components/row/ - - - label: Slider - url: /pagebuilder/components/slider/ - - - label: Tabs - url: /pagebuilder/components/tabs/ - - - label: Text - url: /pagebuilder/components/text/ - - - label: Video - url: /pagebuilder/components/video/ diff --git a/pwa-devdocs/src/_data/peregrine-api.yml b/pwa-devdocs/src/_data/peregrine-api.yml deleted file mode 100644 index 465c0fbd76..0000000000 --- a/pwa-devdocs/src/_data/peregrine-api.yml +++ /dev/null @@ -1,41 +0,0 @@ -title: Peregrine API -entries: - - label: Components and utilities - entries: - - label: Item - url: /peregrine/reference/item/ - - - label: Items - url: /peregrine/reference/items/ - - - label: List - url: /peregrine/reference/list/ - - - label: Price - url: /peregrine/reference/price/ - - - label: Router - url: /peregrine/reference/router/ - - - label: Custom React hooks - entries: - - label: useDropdown - url: /peregrine/reference/hooks/useDropdown/ - - - label: useEventListener - url: /peregrine/reference/hooks/useEventListener/ - - - label: usePagination - url: /peregrine/reference/hooks/usePagination/ - - - label: useSearchParam - url: /peregrine/reference/hooks/useSearchParam/ - - - label: useToasts - url: /peregrine/reference/toasts/useToasts/ - - - label: useToastContext - url: /peregrine/reference/toasts/useToastContext/ - - - label: useWindowSize - url: /peregrine/reference/hooks/useWindowSize/ diff --git a/pwa-devdocs/src/_data/peregrine.yml b/pwa-devdocs/src/_data/peregrine.yml deleted file mode 100644 index b076a3a5f8..0000000000 --- a/pwa-devdocs/src/_data/peregrine.yml +++ /dev/null @@ -1,55 +0,0 @@ -title: Peregrine -entries: - - label: Overview - url: /peregrine/ - - - label: Routing in PWA Studio - url: /peregrine/routing/ - - - label: Utility modules - entries: - - label: REST API client - url: /peregrine/reference/rest-api-client/ - - - label: Custom React hooks - entries: - - label: useDropdown - url: /peregrine/reference/hooks/useDropdown/ - - - label: useEventListener - url: /peregrine/reference/hooks/useEventListener/ - - - label: usePagination - url: /peregrine/reference/hooks/usePagination/ - - - label: useSearchParam - url: /peregrine/reference/hooks/useSearchParam/ - - - label: useToasts - url: /peregrine/reference/toasts/useToasts - - - label: useToastContext - url: /peregrine/reference/toasts/useToastContext/ - - - label: useWindowSize - url: /peregrine/reference/hooks/useWindowSize/ - - - label: React components - entries: - - label: ContainerChild - url: /peregrine/reference/container-child/ - - - label: Item - url: /peregrine/reference/item/ - - - label: Items - url: /peregrine/reference/items/ - - - label: List - url: /peregrine/reference/list/ - - - label: Price - url: /peregrine/reference/price/ - - - label: Router - url: /peregrine/reference/router/ diff --git a/pwa-devdocs/src/_data/pwa-buildpack.yml b/pwa-devdocs/src/_data/pwa-buildpack.yml deleted file mode 100644 index c6c2ba01d7..0000000000 --- a/pwa-devdocs/src/_data/pwa-buildpack.yml +++ /dev/null @@ -1,45 +0,0 @@ -title: PWA Buildpack -entries: - - label: Overview - url: /pwa-buildpack/ - - - label: Configuration management - url: /pwa-buildpack/configuration-management/ - - - label: Buildpack CLI - url: /pwa-buildpack/reference/buildpack-cli/ - entries: - - - label: Create custom origin - url: /pwa-buildpack/reference/buildpack-cli/create-custom-origin/ - - - label: Create environment file - url: /pwa-buildpack/reference/buildpack-cli/create-env-file/ - - - label: Load environment file - url: /pwa-buildpack/reference/buildpack-cli/load-env/ - - - label: Reference - entries: - - - label: Configure webpack - url: /pwa-buildpack/reference/configure-webpack - - - label: Environment variable definitions - url: /pwa-buildpack/reference/environment-variables/core-definitions - - - label: MagentoResolver - url: /pwa-buildpack/reference/magento-resolver/ - - - label: MagentoRootComponentsPlugin - url: /pwa-buildpack/reference/root-components-plugin/ - - - label: PWADevServer - url: /pwa-buildpack/reference/pwa-dev-server/ - - - label: ServiceWorkerPlugin - url: /pwa-buildpack/reference/serviceworker-plugin/ - - - label: Troubleshooting - url: /pwa-buildpack/troubleshooting/ - diff --git a/pwa-devdocs/src/_data/technologies.yml b/pwa-devdocs/src/_data/technologies.yml deleted file mode 100644 index 92be53ada3..0000000000 --- a/pwa-devdocs/src/_data/technologies.yml +++ /dev/null @@ -1,55 +0,0 @@ -title: Technologies -entries: - - label: Overview - url: /technologies/overview/ - - - label: Magento compatibility - url: /technologies/magento-compatibility/ - - - label: Magento theme vs PWA storefront - url: /technologies/theme-vs-storefront/ - - - label: PWA Storefront architecture - url: /technologies/storefront-architecture/ - entries: - - label: Runtime architecture - url: /technologies/storefront-architecture/runtime/ - - - label: Build-time architecture - url: /technologies/storefront-architecture/buildtime/ - - - label: Tools and libraries - url: /technologies/tools-libraries/ - - - label: Basic concepts - url: /technologies/basic-concepts/ - entries: - - label: Application shell - url: /technologies/basic-concepts/app-shell/ - - - label: Container extensibility - url: /technologies/basic-concepts/container-extensibility/ - - - label: CSS modules - url: /technologies/basic-concepts/css-modules/ - - - label: GraphQL - url: /technologies/basic-concepts/graphql/ - - - label: Client-side caching - url: /technologies/basic-concepts/client-side-caching/ - - - label: State management - url: /technologies/basic-concepts/state-management/ - - - label: UPWARD - url: /technologies/upward/ - entries: - - label: Reference implementation - url: /technologies/upward/reference-implementation/ - - - label: Contributing to PWA Studio - url: /technologies/contribute/ - - - label: Versioning strategy - url: /technologies/versioning/ diff --git a/pwa-devdocs/src/_data/top-nav.yml b/pwa-devdocs/src/_data/top-nav.yml deleted file mode 100644 index 76c0442fe4..0000000000 --- a/pwa-devdocs/src/_data/top-nav.yml +++ /dev/null @@ -1,45 +0,0 @@ -- label: Getting Started - children: - - label: Overview - url: /technologies/overview/ - - - label: Frequently Asked Questions - url: /frequently-asked-questions/ - - - label: Storefront architecture - url: /technologies/storefront-architecture/ - - - label: Basic concepts - url: /technologies/basic-concepts/ - - - label: PWA Buildpack - url: /pwa-buildpack/ - - - label: Peregrine - url: /peregrine/ - - - label: Venia storefront concept - url: /venia-pwa-concept/ - - - label: UPWARD - url: /technologies/upward/ - -- label: Tutorials - url: /tutorials/ - -- label: Reference API - children: - - label: PWA Buildpack - url: /pwa-buildpack/reference/buildpack-cli/ - - - label: Peregrine API - url: /peregrine/reference/item/ - - - label: Venia UI API - url: /venia-ui/reference/components/Button/ - -- label: Integrations - children: - - label: Page Builder - url: /pagebuilder/ - \ No newline at end of file diff --git a/pwa-devdocs/src/_data/tutorials.yml b/pwa-devdocs/src/_data/tutorials.yml deleted file mode 100644 index ed14665d7e..0000000000 --- a/pwa-devdocs/src/_data/tutorials.yml +++ /dev/null @@ -1,54 +0,0 @@ -title: Tutorials -entries: - - label: Overview - url: /tutorials/ - - - label: Magento Cloud deployment - url: /tutorials/cloud-deploy/ - - - label: Hello UPWARD - entries: - - label: Creating a simple server - url: /tutorials/hello-upward/simple-server/ - - - label: Using the TemplateResolver - url: /tutorials/hello-upward/using-template-resolver/ - - - label: Adding React - url: /tutorials/hello-upward/adding-react/ - - - label: Create a TagList component - url: /tutorials/create-taglist-component/ - - - label: Enable SASS or LESS support - url: /tutorials/enable-sass-less-support/ - - - label: PWA Studio fundamentals - url: /tutorials/pwa-studio-fundamentals/ - entries: - - label: Project setup - url: /tutorials/pwa-studio-fundamentals/project-setup/ - - - label: Project structure - url: /tutorials/pwa-studio-fundamentals/project-structure/ - - - label: Add a static route - url: /tutorials/pwa-studio-fundamentals/add-a-static-route/ - - - label: Modify the site footer - url: /tutorials/pwa-studio-fundamentals/modify-site-footer/ - - - label: Using component props - url: /tutorials/pwa-studio-fundamentals/using-component-props/ - - - label: CSS modules - url: /tutorials/pwa-studio-fundamentals/css-modules/ - - - label: Manage state - url: /tutorials/pwa-studio-fundamentals/manage-state/ - - - label: Work with GraphQL - url: /tutorials/pwa-studio-fundamentals/work-with-graphql/ - - - label: Production launch checklist - url: /tutorials/pwa-studio-fundamentals/production-launch-checklist/ diff --git a/pwa-devdocs/src/_data/vars.yml b/pwa-devdocs/src/_data/vars.yml deleted file mode 100644 index d6e0b2cbbc..0000000000 --- a/pwa-devdocs/src/_data/vars.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Site specific variables - -title: Magento PWA Studio Documentation -description: Everything you need to build a Magento PWA. -repo: https://github.com/magento/pwa-studio diff --git a/pwa-devdocs/src/_data/venia-api.yml b/pwa-devdocs/src/_data/venia-api.yml deleted file mode 100644 index 4f3ea4bdf2..0000000000 --- a/pwa-devdocs/src/_data/venia-api.yml +++ /dev/null @@ -1,26 +0,0 @@ -title: Venia UI API -entries: - - - label: Button - url: /venia-ui/reference/components/Button/ - - - label: ButtonGroup - url: /venia-ui/reference/components/ButtonGroup/ - - - label: Logo - url: /venia-ui/reference/components/Logo/ - - - label: Mask - url: /venia-ui/reference/components/Mask/ - - - label: Portal - url: /venia-ui/reference/components/Portal/ - - - label: ProductImageCarousel - url: /venia-ui/reference/components/ProductImageCarousel/ - - - label: ToastContainer - url: /venia-ui/reference/components/ToastContainer/ - - - label: Trigger - url: /venia-ui/reference/components/Trigger/ \ No newline at end of file diff --git a/pwa-devdocs/src/_data/venia-pwa-concept.yml b/pwa-devdocs/src/_data/venia-pwa-concept.yml deleted file mode 100644 index f81d63feb4..0000000000 --- a/pwa-devdocs/src/_data/venia-pwa-concept.yml +++ /dev/null @@ -1,163 +0,0 @@ -title: Venia Storefront -entries: - - label: Overview - url: /venia-pwa-concept/ - - - label: Project structure - url: /venia-pwa-concept/project-structure/ - - - label: Venia storefront setup - url: /venia-pwa-concept/setup/ - - - label: Install Venia sample data - url: /venia-pwa-concept/install-sample-data/ - - - label: UI component reference - entries: - - - label: Button - url: /venia-ui/reference/components/Button/ - - - label: ButtonGroup - url: /venia-ui/reference/components/ButtonGroup/ - - - label: Logo - url: /venia-ui/reference/components/Logo/ - - - label: Mask - url: /venia-ui/reference/components/Mask/ - - - label: Modal - url: /venia-ui/reference/components/Modal/ - - - label: ProductImageCarousel - url: /venia-ui/reference/components/ProductImageCarousel/ - - - label: ToastContainer - url: /venia-ui/reference/components/ToastContainer/ - - - label: Trigger - url: /venia-ui/reference/components/Trigger/ - - - label: Features - entries: - - - label: Modular components - url: /venia-pwa-concept/features/modular-components/ - - - label: Checkout - url: /venia-pwa-concept/features/checkout/ - - - label: Braintree integration - url: /venia-pwa-concept/features/braintree/ - - - label: Design - entries: - - - label: Global style guide - url: /venia-pwa-concept/design/global-style/ - - - label: Colors - url: /venia-pwa-concept/design/colors/ - - - label: Typography - url: /venia-pwa-concept/design/typography/ - - - label: Buttons - url: /venia-pwa-concept/design/buttons/ - - - label: Form fields - url: /venia-pwa-concept/design/form-fields/ - - - label: Homepage - url: /venia-pwa-concept/design/homepage/ - - - label: Product page - url: /venia-pwa-concept/design/product-page/ - - - label: Category page - url: /venia-pwa-concept/design/category-page/ - - - label: Component specifications - entries: - - - label: Add to cart - url: /venia-pwa-concept/component/add-to-cart/ - - - label: Add to wishlist - url: /venia-pwa-concept/component/add-to-wishlist/ - - - label: Buy now / Buy with - url: /venia-pwa-concept/component/buy-now-with/ - - - label: Category menu - url: /venia-pwa-concept/component/category-menu/ - - - label: Color selector - url: /venia-pwa-concept/component/color-selector/ - - - label: Filter - url: /venia-pwa-concept/component/filter/ - - - label: Footer - url: /venia-pwa-concept/component/footer/ - - - label: Forgot password - url: /venia-pwa-concept/component/forgot-password/ - - - label: Header - url: /venia-pwa-concept/component/header/ - - - label: Image carousel - url: /venia-pwa-concept/component/image-carousel/ - - - label: Label selector - url: /venia-pwa-concept/component/label-selector/ - - - label: Main image - url: /venia-pwa-concept/component/main-image/ - - - label: Number of items - url: /venia-pwa-concept/component/number-of-items/ - - - label: Order confirmation - url: /venia-pwa-concept/component/order-confirmation/ - - - label: Page - url: /venia-pwa-concept/component/page/ - - - label: Product description - url: /venia-pwa-concept/component/product-description/ - - - label: Product listing - url: /venia-pwa-concept/component/product-listing/ - - - label: Purchase history - url: /venia-pwa-concept/component/purchase-history/ - - - label: Quantity selector - url: /venia-pwa-concept/component/quantity-selector/ - - - label: Quantity sync bar - url: /venia-pwa-concept/component/quantity-sync-bar/ - - - label: Recommended carousel - url: /venia-pwa-concept/component/recommended-carousel/ - - - label: Sale banner - url: /venia-pwa-concept/component/sale-banner/ - - - label: Share - url: /venia-pwa-concept/component/share/ - - - label: Show more - url: /venia-pwa-concept/component/show-more/ - - - label: Size selector - url: /venia-pwa-concept/component/size-selector/ - - - label: Sort - url: /venia-pwa-concept/component/sort/ - - - label: Title bar - url: /venia-pwa-concept/component/title-bar/ diff --git a/pwa-devdocs/src/_drafts/venia-pwa-concept/component/my-account-menu/index.md b/pwa-devdocs/src/_drafts/venia-pwa-concept/component/my-account-menu/index.md deleted file mode 100644 index 7bb16e5c3e..0000000000 --- a/pwa-devdocs/src/_drafts/venia-pwa-concept/component/my-account-menu/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: MyAccountMenu component ---- - -| Description | Reference image | -| -------------------------- | :-------------------------------------------: | -| My account menu | ![Order confirmation]{:width="300px"} | -{:style="table-layout:auto"} - -[My account menu]: {% link venia-pwa-concept/images/my-account-menu.png %} - -## Interactions - -* **Purchase History** link - On tap navigates the user to purchase history page. -* **Sign out** button - On click dispatches an action to sign out the user and refreshes the page. -* **x** button - On tap closes the menu. diff --git a/pwa-devdocs/src/_drafts/venia-pwa-concept/component/purchase-details-page/index.md b/pwa-devdocs/src/_drafts/venia-pwa-concept/component/purchase-details-page/index.md deleted file mode 100644 index d1518c04c8..0000000000 --- a/pwa-devdocs/src/_drafts/venia-pwa-concept/component/purchase-details-page/index.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: PurchaseDetailsPage component ---- - -| Description | Reference image | -| -------------------------- | :-------------------------------------------: | -| Purchase details page | ![Purchase details page]{:width="300px"} | -| Order details block | ![Order details]{:width="300px"} | -| Shipment details block | ![Shipment details]{:width="300px"} | -| Payment details block | ![Payment details]{:width="300px"} | -| Order summary block | ![Order summary]{:width="300px"} | -| Order items list | ![Order items list]{:width="300px"} | -| Order item | ![Order item]{:width="300px"} | -| Button group | ![Button group]{:width="300px"} | -{:style="table-layout:auto"} - -[Purchase details page]: {% link venia-pwa-concept/images/purchase-details-page.png %} -[Order details]: {% link venia-pwa-concept/images/purchase-details-order-details.png %} -[Shipment details]: {% link venia-pwa-concept/images/purchase-details-shipment-details.png %} -[Payment details]: {% link venia-pwa-concept/images/purchase-details-payment-details.png %} -[Order summary]: {% link venia-pwa-concept/images/purchase-details-order-summary.png %} -[Order items list]: {% link venia-pwa-concept/images/purchase-details-order-items-list.png %} -[Order item]: {% link venia-pwa-concept/images/purchase-details-order-item.png %} -[Button group]: {% link venia-pwa-concept/images/purchase-details-button-group.png %} - -## Interactions - -* **Tap BuyAgain** - Adds item to the cart. -* **Tap ShareItem** - Opens product details page. diff --git a/pwa-devdocs/src/_includes/content-not-available.md b/pwa-devdocs/src/_includes/content-not-available.md deleted file mode 100644 index c3635c8d1c..0000000000 --- a/pwa-devdocs/src/_includes/content-not-available.md +++ /dev/null @@ -1,13 +0,0 @@ -## Sorry! - -The content for this page does not exist yet! - -{% if include.issue %} -To contribute to this page, see the following [GitHub Issue]({{ site.data.vars.repo }}/issues/{{include.issue}}) for details. -{% else %} -If you would like to contribute content for this page, please visit our [Contribution Guide]. -{% endif %} - -[Return to main page]({{site.baseurl}}/) - -[Contribution Guide]: {{ site.data.vars.repo }}/blob/master/.github/CONTRIBUTING.md \ No newline at end of file diff --git a/pwa-devdocs/src/_includes/layout/after-site-header.html b/pwa-devdocs/src/_includes/layout/after-site-header.html deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pwa-devdocs/src/_includes/layout/footer-links.html b/pwa-devdocs/src/_includes/layout/footer-links.html deleted file mode 100644 index 219d9cb5f3..0000000000 --- a/pwa-devdocs/src/_includes/layout/footer-links.html +++ /dev/null @@ -1,6 +0,0 @@ - \ No newline at end of file diff --git a/pwa-devdocs/src/_includes/layout/footer-scripts.html b/pwa-devdocs/src/_includes/layout/footer-scripts.html deleted file mode 100644 index 99c7e85cfa..0000000000 --- a/pwa-devdocs/src/_includes/layout/footer-scripts.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pwa-devdocs/src/_includes/layout/header-scripts.html b/pwa-devdocs/src/_includes/layout/header-scripts.html deleted file mode 100644 index 582c1c639b..0000000000 --- a/pwa-devdocs/src/_includes/layout/header-scripts.html +++ /dev/null @@ -1,55 +0,0 @@ - - -{% if site.environment == "public" %} - - - - - -{% endif %} diff --git a/pwa-devdocs/src/_includes/layout/header-styles.html b/pwa-devdocs/src/_includes/layout/header-styles.html deleted file mode 100644 index 35fe629f3a..0000000000 --- a/pwa-devdocs/src/_includes/layout/header-styles.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/pwa-devdocs/src/_includes/layout/navigation.html b/pwa-devdocs/src/_includes/layout/navigation.html deleted file mode 100644 index 89f0610c1d..0000000000 --- a/pwa-devdocs/src/_includes/layout/navigation.html +++ /dev/null @@ -1,24 +0,0 @@ - - diff --git a/pwa-devdocs/src/_includes/layout/page-header.html b/pwa-devdocs/src/_includes/layout/page-header.html deleted file mode 100644 index 55e7a43bd0..0000000000 --- a/pwa-devdocs/src/_includes/layout/page-header.html +++ /dev/null @@ -1,16 +0,0 @@ - -
- -

{{ page.title }}

- - {% if page.subtitle %} -

{{ page.subtitle }}

- {% endif %} - - {% include layout/github-links.html %} - - {% include layout/edition-callout.html %} - - {% include layout/pre-release-banner.html %} - -
diff --git a/pwa-devdocs/src/_includes/layout/pre-release-banner.html b/pwa-devdocs/src/_includes/layout/pre-release-banner.html deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pwa-devdocs/src/_includes/layout/sidebar-nav-root-item.html b/pwa-devdocs/src/_includes/layout/sidebar-nav-root-item.html deleted file mode 100644 index d0affc11b9..0000000000 --- a/pwa-devdocs/src/_includes/layout/sidebar-nav-root-item.html +++ /dev/null @@ -1,34 +0,0 @@ - -{% if page.toc-group == "getting-started" %} - {% assign toc = site.data.getting-started %} - -{% elsif page.toc-group == "buildpack-api" %} - {% assign toc = site.data.buildpack-api %} - -{% elsif page.toc-group == "peregrine-api" %} - {% assign toc = site.data.peregrine-api %} - -{% elsif page.toc-group == "venia-api" %} - {% assign toc = site.data.venia-api %} - -{% elsif page.toc-group == "technologies" %} - {% assign toc = site.data.technologies %} - -{% elsif page.toc-group == "pwa-buildpack" %} - {% assign toc = site.data.pwa-buildpack %} - -{% elsif page.toc-group == "pagebuilder" %} - {% assign toc = site.data.pagebuilder %} - -{% elsif page.toc-group == "peregrine" %} - {% assign toc = site.data.peregrine %} - -{% elsif page.toc-group == "venia-pwa-concept" %} - {% assign toc = site.data.venia-pwa-concept %} - -{% elsif page.toc-group == "tutorials" %} - {% assign toc = site.data.tutorials %} - -{% endif %} - -{% include layout/toc.html %} diff --git a/pwa-devdocs/src/_includes/layout/toc.html b/pwa-devdocs/src/_includes/layout/toc.html deleted file mode 100644 index 903133510e..0000000000 --- a/pwa-devdocs/src/_includes/layout/toc.html +++ /dev/null @@ -1,32 +0,0 @@ - - \ No newline at end of file diff --git a/pwa-devdocs/src/_includes/peregrine/reference/list-selection-models.md b/pwa-devdocs/src/_includes/peregrine/reference/list-selection-models.md deleted file mode 100644 index bfe05316ad..0000000000 --- a/pwa-devdocs/src/_includes/peregrine/reference/list-selection-models.md +++ /dev/null @@ -1,4 +0,0 @@ -The `selectionModel` currently accepts the following values: - -* **radio** (default) -* **checkbox** diff --git a/pwa-devdocs/src/_js/collapsible.js b/pwa-devdocs/src/_js/collapsible.js deleted file mode 100644 index c3c6f072ea..0000000000 --- a/pwa-devdocs/src/_js/collapsible.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - * A collapsible widget used in the left TOC - */ - -define("collapsible", - ["jquery/dist/jquery"], - function(jquery) { - - let hide = (control, target, speed) => { - jquery(control).html("arrow_drop_down"); - jquery(target).slideUp(speed); - } - - let show = (control, target, speed) => { - jquery(control).html("arrow_drop_up"); - jquery(target).slideDown(speed); - - } - - let toggle = (control, target, speed) => { - if(jquery(control).html() === "arrow_drop_down") { - show(control,target, speed); - } - else { - hide(control,target, speed); - } - } - - let Collapsible = { - - /** - * Applies the collapsible functionality - * @control {DOM} The DOM element that controls the hide/show. - * This element needs to have a material.io icon tag (). - * @target {DOM} The DOM element to hide/show - * @speed {int} The speed of the show/hide functionality - */ - apply: function(control, target, speed=200) { - jquery(control).click(function(){ - toggle(jquery(control).children('i'), target,speed); - }) - }, - - /** - * Toggles the collapsible functionality - */ - toggle: toggle - - } - - return Collapsible; - - } -); \ No newline at end of file diff --git a/pwa-devdocs/src/_js/index.js b/pwa-devdocs/src/_js/index.js deleted file mode 100644 index 6817095214..0000000000 --- a/pwa-devdocs/src/_js/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// Javascript goes here - -// Use addEventListener to allow other scripts firing on window load -window.addEventListener('load', (event) => { - let toc = document.getElementsByClassName('table-of-contents'); - - if(toc){ - let active = document.getElementsByClassName('active')[0]; - - if( active ) { - active.scrollIntoView({inline: "center", block: "center", behavior: "smooth"}); - } - } -}); \ No newline at end of file diff --git a/pwa-devdocs/src/_plugins/github_path.rb b/pwa-devdocs/src/_plugins/github_path.rb deleted file mode 100644 index 5a7f33b7c9..0000000000 --- a/pwa-devdocs/src/_plugins/github_path.rb +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright © Magento, Inc. All rights reserved. -# See COPYING.txt for license details. - -# frozen_string_literal: true - -# -# This custom plugin dynamically sets the 'github_path' parameter -# for each page except 'redirect.html' pages. -# A value of the parameter is available as {{ page.github_path }}. -# The parameter contains a file path relative to its repository. -# -Jekyll::Hooks.register :pages, :post_init do |page| - - # Skip virtual pages like MRG topics - next if page.kind_of? Jekyll::PageWithoutAFile - # Process only files with 'md' and 'html' extensions - next unless File.extname(page.path).match?(/md|html/) - # Skip redirects - next if page.name == 'redirect.html' - - dir = File.join( - page.site.source, - File.dirname(page.path) - ) - - filename = File.basename page.path - - # Change to the parent directory of the page and read full file path - # from git index. - Dir.chdir(dir) do - page.data['github_path'] = `git ls-files --full-name #{filename}`.strip - end -end diff --git a/pwa-devdocs/src/_plugins/sitemap_generator.rb b/pwa-devdocs/src/_plugins/sitemap_generator.rb deleted file mode 100644 index ee096f3da1..0000000000 --- a/pwa-devdocs/src/_plugins/sitemap_generator.rb +++ /dev/null @@ -1,274 +0,0 @@ -# Sitemap.xml Generator is a Jekyll plugin that generates a sitemap.xml file by -# traversing all of the available posts and pages. -# -# See readme file for documentation -# -# Updated to use config file for settings by Daniel Groves -# Site: http://danielgroves.net -# -# Author: Michael Levin -# Site: http://www.kinnetica.com -# Distributed Under A Creative Commons License -# - http://creativecommons.org/licenses/by/3.0/ -require 'jekyll/document' -require 'rexml/document' - -module Jekyll - - class Jekyll::Document - attr_accessor :name - - def path_to_source - File.join(*[@name].compact) - end - - def location_on_server(my_url) - "#{my_url}#{url}" - end - end - - class Page - attr_accessor :name - - def path_to_source - File.join(*[@dir, @name].compact) - end - - def location_on_server(my_url) - location = "#{my_url}#{url}" - location.gsub(/index.html$/, "") - end - end - - # Recover from strange exception when starting server without --auto - class SitemapFile < StaticFile - def write(dest) - true - end - end - - class SitemapGenerator < Generator - priority :lowest - - # Config defaults - SITEMAP_FILE_NAME = "/sitemap.xml" - EXCLUDE = ["/atom.xml", "/feed.xml", "/feed/index.xml"] - INCLUDE_POSTS = ["/index.html"] - CHANGE_FREQUENCY_NAME = "change_frequency" - PRIORITY_NAME = "priority" - - # Valid values allowed by sitemap.xml spec for change frequencies - VALID_CHANGE_FREQUENCY_VALUES = ["always", "hourly", "daily", "weekly", - "monthly", "yearly", "never"] - - # Goes through pages and posts and generates sitemap.xml file - # - # Returns nothing - def generate(site) - # Configuration - sitemap_config = site.config['sitemap'] || {} - @config = {} - @config['filename'] = sitemap_config['filename'] || SITEMAP_FILE_NAME - @config['change_frequency_name'] = sitemap_config['change_frequency_name'] || CHANGE_FREQUENCY_NAME - @config['priority_name'] = sitemap_config['priority_name'] || PRIORITY_NAME - @config['exclude'] = sitemap_config['exclude'] || EXCLUDE - @config['include_posts'] = sitemap_config['include_posts'] || INCLUDE_POSTS - - sitemap = REXML::Document.new << REXML::XMLDecl.new("1.0", "UTF-8") - - urlset = REXML::Element.new "urlset" - urlset.add_attribute("xmlns", - "http://www.sitemaps.org/schemas/sitemap/0.9") - - @last_modified_post_date = fill_posts(site, urlset) - fill_pages(site, urlset) - - sitemap.add_element(urlset) - - # Create destination directory if it doesn't exist yet. Otherwise, we cannot write our file there. - Dir::mkdir(site.dest) if !File.directory? site.dest - - # File I/O: create sitemap.xml file and write out pretty-printed XML - filename = @config['filename'] - file = File.new(File.join(site.dest, filename), "w") - formatter = REXML::Formatters::Pretty.new(4) - formatter.compact = true - formatter.write(sitemap, file) - file.close - - # Keep the sitemap.xml file from being cleaned by Jekyll - site.static_files << Jekyll::SitemapFile.new(site, site.dest, "/", filename) - end - - # Create url elements for all the posts and find the date of the latest one - # - # Returns last_modified_date of latest post - def fill_posts(site, urlset) - - last_modified_date = nil - site.collections["posts"].docs.each do |post| - if !excluded?(site, post.name) - url = fill_url(site, post) - urlset.add_element(url) - end - - date = File.mtime(post.path) - last_modified_date = date if last_modified_date == nil or date > last_modified_date - end - - last_modified_date - end - - # Create url elements for all the normal pages and find the date of the - # index to use with the pagination pages - # - # Returns last_modified_date of index page - def fill_pages(site, urlset) - site.pages.each do |page| - if !excluded?(site, page.path_to_source) - if File.exists?(page.path) - url = fill_url(site, page) - urlset.add_element(url) - end - end - end - end - - # Fill data of each URL element: location, last modified, - # change frequency (optional), and priority. - # - # Returns url REXML::Element - def fill_url(site, page_or_post) - url = REXML::Element.new "url" - - loc = fill_location(site, page_or_post) - url.add_element(loc) - - lastmod = fill_last_modified(site, page_or_post) - url.add_element(lastmod) if lastmod - - - - if (page_or_post.data[@config['change_frequency_name']]) - change_frequency = - page_or_post.data[@config['change_frequency_name']].downcase - - if (valid_change_frequency?(change_frequency)) - changefreq = REXML::Element.new "changefreq" - changefreq.text = change_frequency - url.add_element(changefreq) - else - puts "ERROR: Invalid Change Frequency In #{page_or_post.name}" - end - end - - if (page_or_post.data[@config['priority_name']]) - priority_value = page_or_post.data[@config['priority_name']] - if valid_priority?(priority_value) - priority = REXML::Element.new "priority" - priority.text = page_or_post.data[@config['priority_name']] - url.add_element(priority) - else - puts "ERROR: Invalid Priority In #{page_or_post.name}" - end - end - - url - end - - # Get URL location of page or post - # - # Returns the location of the page or post - def fill_location(site, page_or_post) - loc = REXML::Element.new "loc" - url = site.config['url'] + site.config['baseurl'] - loc.text = page_or_post.location_on_server(url) - - loc - end - - # Fill lastmod XML element with the last modified date for the page or post. - # - # Returns lastmod REXML::Element or nil - def fill_last_modified(site, page_or_post) - lastmod = REXML::Element.new "lastmod" - date = File.mtime(page_or_post.path) - latest_date = find_latest_date(date, site, page_or_post) - - if @last_modified_post_date == nil - # This is a post - lastmod.text = latest_date.iso8601 - else - # This is a page - if posts_included?(site, page_or_post.path_to_source) - # We want to take into account the last post date - final_date = greater_date(latest_date, @last_modified_post_date) - lastmod.text = final_date.iso8601 - else - lastmod.text = latest_date.iso8601 - end - end - lastmod - end - - # Go through the page/post and any implemented layouts and get the latest - # modified date - # - # Returns formatted output of latest date of page/post and any used layouts - def find_latest_date(latest_date, site, page_or_post) - layouts = site.layouts - layout = layouts[page_or_post.data["layout"]] - while layout - date = File.mtime(layout.path) - - latest_date = date if (date > latest_date) - - layout = layouts[layout.data["layout"]] - end - - latest_date - end - - # Which of the two dates is later - # - # Returns latest of two dates - def greater_date(date1, date2) - if (date1 >= date2) - date1 - else - date2 - end - end - - # Is the page or post listed as something we want to exclude? - # - # Returns boolean - def excluded?(site, name) - @config['exclude'].include? name - end - - def posts_included?(site, name) - @config['include_posts'].include? name - end - - # Is the change frequency value provided valid according to the spec - # - # Returns boolean - def valid_change_frequency?(change_frequency) - VALID_CHANGE_FREQUENCY_VALUES.include? change_frequency - end - - # Is the priority value provided valid according to the spec - # - # Returns boolean - def valid_priority?(priority) - begin - priority_val = Float(priority) - return true if priority_val >= 0.0 and priority_val <= 1.0 - rescue ArgumentError - end - - false - end - end -end diff --git a/pwa-devdocs/src/_posts/.gitkeep b/pwa-devdocs/src/_posts/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pwa-devdocs/src/_scss/_variables.scss b/pwa-devdocs/src/_scss/_variables.scss deleted file mode 100644 index 6577496855..0000000000 --- a/pwa-devdocs/src/_scss/_variables.scss +++ /dev/null @@ -1,101 +0,0 @@ -$body-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; -//$body-font-family: 'Open Sans', 'Helvetica', 'Arial', sans-serif; - -$font-size-base: 1rem; -$font-size-lg: 1.25rem; -$font-size-sm: .875rem; -$font-size-xsm: .7rem; - -$font-weight-light: 300; -$font-weight-normal: normal; -$font-weight-medium: 500; -$font-weight-bold: bold; - -$line-height-base: 1.5; - -$spacing: 5px; - -$sidebar-width: 270px; -$page-info-width: 200px; - -$header-height: $spacing*11; - - -// Breakpoints -$small-screen: 'max-width: 768px'; -$medium-screen: 'max-width: 1023px'; -$medium-to-large-screen: 'max-width: 1200px'; -$large-screen: 'min-width: 1500px'; - - - - - -// Colors -$brand-color: #F26322; -$body-font-color: #2b2b2c; -$accent-color: #26A2AA; - -$light-gray-color: #F1F1F1; -$dark-gray-color: #888; -$beige-color: #CAC3B4; - -$footer-color: #A6ABB0; -$footer-link-color: #D8D9DA; -$footer-background-color: #31302B; - - -$link-color: #1572D0; -$link-hover-color: #cc0000; -$link-active-color: #EC632E; -$link-visited-color: #609; - -$border-color: #d2d2d2; - - -// buttons -$btn-color: $body-font-color; -$btn-bg-color: #ccc; - -$btn-primary-color: #fff; -$btn-primary-bg-color: $brand-color; - - - - - - -// Dropdown - -$dropdown-bg: #fff; -$dropdown-border-color: #ccc; -$dropdown-border-width: 1px; -$dropdown-divider-bg: #e5e5e5; - -$dropdown-link-color: $body-font-color; -$dropdown-link-hover-color: $body-font-color; -$dropdown-link-hover-bg: #f2f3f3; - -$dropdown-link-active-color: $link-color; -$dropdown-link-active-bg: $link-color; - -$dropdown-link-disabled-color: #ccc; -$dropdown-header-color: #ccc; - -$caret-width: .3em; -$caret-width-lg: $caret-width; - -$border-radius: 0; -$line-height: 1.3; - - - - -$transition-duration: .2s; - - -// Z Index - -$zindex-appbar: 1000; -$zindex-nav-fader: 900; -$zindex-dropdown: 9999; diff --git a/pwa-devdocs/src/_scss/main.scss b/pwa-devdocs/src/_scss/main.scss deleted file mode 100644 index 0743393624..0000000000 --- a/pwa-devdocs/src/_scss/main.scss +++ /dev/null @@ -1,9 +0,0 @@ -// Import theme variables -@import "variables"; - -@import "var/syntax"; - -@import "src/home"; -@import "src/material-icons"; - -@import "src/code-block-style-overrides.scss"; diff --git a/pwa-devdocs/src/_scss/src/.gitkeep b/pwa-devdocs/src/_scss/src/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pwa-devdocs/src/_scss/src/_code-block-style-overrides.scss b/pwa-devdocs/src/_scss/src/_code-block-style-overrides.scss deleted file mode 100644 index af523ee1b9..0000000000 --- a/pwa-devdocs/src/_scss/src/_code-block-style-overrides.scss +++ /dev/null @@ -1,13 +0,0 @@ -.highlight .gd, -.highlight .gi { - border: none; - background: none; -} - -.highlight .gi { - color: #00B218; -} - -.highlight .gd { - color: #FF3B6F; -} diff --git a/pwa-devdocs/src/_scss/src/_home.scss b/pwa-devdocs/src/_scss/src/_home.scss deleted file mode 100644 index e554101719..0000000000 --- a/pwa-devdocs/src/_scss/src/_home.scss +++ /dev/null @@ -1,83 +0,0 @@ -// General tiles (TODO: move this to a theme) -$column-gap: 0.75rem !default; - -.columns { - display: flex; - flex-wrap: wrap; - margin-left: (-$column-gap); - margin-right: (-$column-gap); - margin-top: (-$column-gap); - margin-bottom: (-$column-gap); -} - -.column { - display: flex; - - flex-basis: 0; - flex-grow: 1; - flex-shrink: 1; - - padding: $column-gap; -} - - -// Home page sections - - -.home-getting-started { - - .column { - width: 50%; - flex-basis: 50%; - - @media ($small-screen) { - width: auto; - flex-basis: auto; - padding-left: 0; - padding-right: 0; - } - } -} - - - - - -.home-contribute { - - .intro { - text-align: center; - } - - h2 { - font-size: 40px; - font-weight: $font-weight-light; - - @media ($small-screen) { - font-size: 34px; - } - } - - .column { - flex-basis: 33%; - flex-grow: 0; - - p:last-child { - margin-bottom: 0; - } - - @media ($medium-screen) { - flex-basis: 50%; - } - - @media ($small-screen) { - width: auto; - flex-basis: auto; - padding: 0; - } - } -} - -dl dd { - margin-left: 20px; -} diff --git a/pwa-devdocs/src/_scss/src/_material-icons.scss b/pwa-devdocs/src/_scss/src/_material-icons.scss deleted file mode 100644 index 404374bc56..0000000000 --- a/pwa-devdocs/src/_scss/src/_material-icons.scss +++ /dev/null @@ -1,14 +0,0 @@ -.material-icons { - &.edit{ - vertical-align: sub; - } - - &.warning{ - vertical-align: sub; - color: #ffa500; - } - - &.green{ - color: #008000; - } -} diff --git a/pwa-devdocs/src/_scss/src/menu-section.scss b/pwa-devdocs/src/_scss/src/menu-section.scss deleted file mode 100644 index 299cbb30f9..0000000000 --- a/pwa-devdocs/src/_scss/src/menu-section.scss +++ /dev/null @@ -1,28 +0,0 @@ -.menu-section { - padding-bottom: 5px; - - .toc-entry { - display: flex; - cursor: pointer; - - border-bottom: 1px solid #d2d2d2; - - h4 { - flex-grow: 1; - } - - .material-icons { - font-size: 36px; - color: #26A2AA; - } - } - - .table-of-contents { - - .stub { - color: #626366; - font-style: italic - } - - } -} diff --git a/pwa-devdocs/src/_scss/var/_syntax.scss b/pwa-devdocs/src/_scss/var/_syntax.scss deleted file mode 100644 index 15ad797710..0000000000 --- a/pwa-devdocs/src/_scss/var/_syntax.scss +++ /dev/null @@ -1,65 +0,0 @@ -.highlight .hll { background-color: #ffc; } -.highlight .c { color: #999; } /* Comment */ -.highlight .err { color: #a00; background-color: #faa } /* Error */ -.highlight .k { color: #069; } /* Keyword */ -.highlight .o { color: #555 } /* Operator */ -.highlight .cm { color: #09f; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #099 } /* Comment.Preproc */ -.highlight .c1 { color: #999; } /* Comment.Single */ -.highlight .cs { color: #999; } /* Comment.Special */ -.highlight .gd { background-color: #fcc; border: 1px solid #c00 } /* Generic.Deleted */ -.highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .gr { color: #f00 } /* Generic.Error */ -.highlight .gh { color: #030; } /* Generic.Heading */ -.highlight .gi { background-color: #cfc; border: 1px solid #0c0 } /* Generic.Inserted */ -.highlight .go { color: #aaa } /* Generic.Output */ -.highlight .gp { color: #009; } /* Generic.Prompt */ -.highlight .gs { } /* Generic.Strong */ -.highlight .gu { color: #030; } /* Generic.Subheading */ -.highlight .gt { color: #9c6 } /* Generic.Traceback */ -.highlight .kc { color: #069; } /* Keyword.Constant */ -.highlight .kd { color: #069; } /* Keyword.Declaration */ -.highlight .kn { color: #069; } /* Keyword.Namespace */ -.highlight .kp { color: #069 } /* Keyword.Pseudo */ -.highlight .kr { color: #069; } /* Keyword.Reserved */ -.highlight .kt { color: #078; } /* Keyword.Type */ -.highlight .m { color: #f60 } /* Literal.Number */ -.highlight .s { color: #d44950 } /* Literal.String */ -.highlight .na { color: #4f9fcf } /* Name.Attribute */ -.highlight .nb { color: #366 } /* Name.Builtin */ -.highlight .nc { color: #0a8; } /* Name.Class */ -.highlight .no { color: #360 } /* Name.Constant */ -.highlight .nd { color: #99f } /* Name.Decorator */ -.highlight .ni { color: #999; } /* Name.Entity */ -.highlight .ne { color: #c00; } /* Name.Exception */ -.highlight .nf { color: #c0f } /* Name.Function */ -.highlight .nl { color: #99f } /* Name.Label */ -.highlight .nn { color: #0cf; } /* Name.Namespace */ -.highlight .nt { color: #2f6f9f; } /* Name.Tag */ -.highlight .nv { color: #033 } /* Name.Variable */ -.highlight .ow { color: #000; } /* Operator.Word */ -.highlight .w { color: #bbb } /* Text.Whitespace */ -.highlight .mf { color: #f60 } /* Literal.Number.Float */ -.highlight .mh { color: #f60 } /* Literal.Number.Hex */ -.highlight .mi { color: #f60 } /* Literal.Number.Integer */ -.highlight .mo { color: #f60 } /* Literal.Number.Oct */ -.highlight .sb { color: #c30 } /* Literal.String.Backtick */ -.highlight .sc { color: #c30 } /* Literal.String.Char */ -.highlight .sd { color: #c30; font-style: italic } /* Literal.String.Doc */ -.highlight .s2 { color: #c30 } /* Literal.String.Double */ -.highlight .se { color: #c30; } /* Literal.String.Escape */ -.highlight .sh { color: #c30 } /* Literal.String.Heredoc */ -.highlight .si { color: #a00 } /* Literal.String.Interpol */ -.highlight .sx { color: #c30 } /* Literal.String.Other */ -.highlight .sr { color: #3aa } /* Literal.String.Regex */ -.highlight .s1 { color: #c30 } /* Literal.String.Single */ -.highlight .ss { color: #fc3 } /* Literal.String.Symbol */ -.highlight .bp { color: #366 } /* Name.Builtin.Pseudo */ -.highlight .vc { color: #033 } /* Name.Variable.Class */ -.highlight .vg { color: #033 } /* Name.Variable.Global */ -.highlight .vi { color: #033 } /* Name.Variable.Instance */ -.highlight .il { color: #f60 } /* Literal.Number.Integer.Long */ - -.css .o, -.css .o + .nt, -.css .nt + .nt { color: #999; } diff --git a/pwa-devdocs/src/assets/i/home-bg.jpg b/pwa-devdocs/src/assets/i/home-bg.jpg deleted file mode 100644 index 6bac29a6fa..0000000000 Binary files a/pwa-devdocs/src/assets/i/home-bg.jpg and /dev/null differ diff --git a/pwa-devdocs/src/frequently-asked-questions/index.md b/pwa-devdocs/src/frequently-asked-questions/index.md deleted file mode 100644 index 74ed8125d5..0000000000 --- a/pwa-devdocs/src/frequently-asked-questions/index.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: Frequently Asked Questions(FAQ) ---- - -## How do I get started with PWA Studio - -If you are developing a new storefront, the [PWA Studio fundamentals][] tutorial series provides an introduction to the different tools and features of PWA Studio. - -If you want to learn about the technologies and concepts behind PWA Studio, the [Getting Started][] section of this site provides background information about this project. - -If you are interested in looking at the project source or contributing to the project, check out the [project repository][]. - -## Does PWA Studio support server-side rendering (SSR) - -Yes, PWA Studio provides tools that support both server-side and client-side rendering strategies. -For more information on content rendering support, see the [Content Rendering][] topic. - -Community members have also suggested the following tools and services to address SEO and SSR needs: - -- [SeoSnap][] -- [Prerender.io][] - -## How do I customize a new storefront project - -The Tutorials section of this site contains a number of tutorials which cover customizations such as: - -- [How to add a static route][] -- [How to modify the site footer][] -- [How to use component props][] -- [How to use CSS modules][] - -## Are there any live stores built using PWA Studio - -Yes, there are a few! -The community-created [PWA Studio Stats][] site lists some of these storefronts that are built using PWA Studio technologies. - -## Which payment methods does PWA Studio support - -PWA Studio supports Braintree payments out of the box in its Venia storefront implementation. -The project also supports adding other payment methods to a storefront project, but -it requires additional implementation for the storefront developer. - -## How do I deploy to production - -A PWA Studio storefront uses an UPWARD server as the backend for the frontend code. -Magento provides two different UPWARD server implementations, UPWARD-JS and UPWARD-PHP. - -UPWARD-JS is a node implementation of an UPWARD server. -It is used during storefront development when you use the `yarn watch` command, but -you can use it for production by calling `yarn build` to generate production assets and `yarn start` to start a server. - -UPWARD-PHP is a PHP implementation of an UPWARD server. -It is a dependency of the [Magento 2 UPWARD connector module][], which lets you run an UPWARD server on the same machine as your Magento 2 instance. -See the [Magento Cloud deployment][] tutorial to learn how to deploy your storefront on the Magento Cloud. - -## Can I use Windows with PWA Studio for development - -Developing with PWA Studio in Windows is not supported because of its incompatibility with some of the project's dependencies. - -Currently, the PWA Studio core team does not have the bandwidth to develop and maintain a Windows development solution, but -community members have suggested the following workarounds: - -- Using Docker to spin up a Linux environment -- Using the [Windows Subsystem for Linux][] - -## How can I query other stores via GraphQL - -To let the storefront query a specific store view in Magento you need to add the store code to these two files: - -- [packages/peregrine/lib/Router/resolveUnknownRoute.js][] - - - Add `Store: YOUR_STORE_CODE` - -- [packages/venia-ui/lib/drivers/adapter.js][] - - - Add `headers:{ Store: YOUR_STORE_CODE }` - -## Image component loads wrongly sized images from the srcSet - -When you use the `` component from `venia-ui`, change the following values: - -- [packages/venia-ui/lib/util/images.js][] - - - Change `DEFAULT_WIDTH_TO_HEIGHT_RATIO` to match your image ratio. - - Change the values in the `imageWidths` mapping to better fit your dimensions. - -- [packages/venia-ui/lib/components/gallery/item.js][] - - - Supply the `` component with a `widths` prop as shown in the GalleryItem component defined in the linked file. - -{: .bs-callout .bs-callout-info} -_**Note:** For testing, resize the viewport manually instead of using the native device emulator in Chrome, which gives incorrect values._ - -[getting started]: <{%link technologies/overview/index.md %}> - -[pwa studio fundamentals]: <{%link tutorials/pwa-studio-fundamentals/index.md %}> - -[content rendering]: <{% link technologies/basic-concepts/content-rendering/index.md %}> - -[how to add a static route]: <{%link tutorials/pwa-studio-fundamentals/add-a-static-route/index.md %}> - -[how to modify the site footer]: <{%link tutorials/pwa-studio-fundamentals/modify-site-footer/index.md %}> - -[how to use component props]: <{%link tutorials/pwa-studio-fundamentals/using-component-props/index.md %}> - -[how to use css modules]: <{%link tutorials/pwa-studio-fundamentals/css-modules/index.md %}> - -[magento cloud deployment]: <{% link tutorials/cloud-deploy/index.md %}> - -[project repository]: https://github.com/magento/pwa-studio - -[seosnap]: https://seosnap.io/ - -[prerender.io]: https://prerender.io/ - -[pwa studio stats]: https://pwastudio-stats.com/ - -[magento 2 upward connector module]: https://github.com/magento-research/magento2-upward-connector - -[windows subsystem for linux]: https://docs.microsoft.com/en-us/windows/wsl/install-win10 - -[packages/peregrine/lib/router/resolveunknownroute.js]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/Router/resolveUnknownRoute.js#L97 - -[packages/venia-ui/lib/drivers/adapter.js]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/drivers/adapter.js#L120 - -[packages/venia-ui/lib/util/images.js]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/util/images.js#L6 - -[packages/venia-ui/lib/components/gallery/item.js]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/Gallery/item.js#L18 diff --git a/pwa-devdocs/src/guides/testing/index.md b/pwa-devdocs/src/guides/testing/index.md deleted file mode 100644 index 3863ff275f..0000000000 --- a/pwa-devdocs/src/guides/testing/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md %} \ No newline at end of file diff --git a/pwa-devdocs/src/index.html b/pwa-devdocs/src/index.html deleted file mode 100644 index c8691f6143..0000000000 --- a/pwa-devdocs/src/index.html +++ /dev/null @@ -1,34 +0,0 @@ ---- -layout: home ---- - - -
-
- {% include layout/pre-release-banner.html %} - - {% include grid.html sections=site.data.home-sections large="3" %} -
- -
- -
- -
- -
- -

PWA Studio in GitHub

- -

- The Magento PWA Studio project is an open source GitHub project that welcomes community contributions and collaboration. -

-

- If you have any questions, issues, or suggestions, please join the #pwa Slack channel at magentocommeng.slack.com. -

- -
- -
- -
diff --git a/pwa-devdocs/src/pagebuilder/components/banner/index.md b/pwa-devdocs/src/pagebuilder/components/banner/index.md deleted file mode 100644 index 61ffd4a554..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/banner/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Banner ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Banner/banner.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/block/index.md b/pwa-devdocs/src/pagebuilder/components/block/index.md deleted file mode 100644 index a0bd3ebba6..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/block/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Block ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Block/block.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/buttons/index.md b/pwa-devdocs/src/pagebuilder/components/buttons/index.md deleted file mode 100644 index e860599cfe..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/buttons/index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Buttons ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Buttons/buttons.md %} -{% include auto-generated/pagebuilder/lib/ContentTypes/ButtonItem/buttonItem.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/column/index.md b/pwa-devdocs/src/pagebuilder/components/column/index.md deleted file mode 100644 index c99daa856f..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/column/index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Column ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Column/column.md %} -{% include auto-generated/pagebuilder/lib/ContentTypes/ColumnGroup/columnGroup.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/divider/index.md b/pwa-devdocs/src/pagebuilder/components/divider/index.md deleted file mode 100644 index f265dde2be..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/divider/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Divider ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Divider/divider.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/heading/index.md b/pwa-devdocs/src/pagebuilder/components/heading/index.md deleted file mode 100644 index 0afa0b802a..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/heading/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Heading ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Heading/heading.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/html/index.md b/pwa-devdocs/src/pagebuilder/components/html/index.md deleted file mode 100644 index aa7d42d51e..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/html/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: HTML Code ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Html/html.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/image/index.md b/pwa-devdocs/src/pagebuilder/components/image/index.md deleted file mode 100644 index 6c564f4da8..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/image/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Image ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Image/image.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/map/index.md b/pwa-devdocs/src/pagebuilder/components/map/index.md deleted file mode 100644 index 037cf624f7..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/map/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Map ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Map/map.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/products/index.md b/pwa-devdocs/src/pagebuilder/components/products/index.md deleted file mode 100644 index b294f5947b..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/products/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Products ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Products/products.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/row/index.md b/pwa-devdocs/src/pagebuilder/components/row/index.md deleted file mode 100644 index 49637c8627..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/row/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Row ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Block/block.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/slider/index.md b/pwa-devdocs/src/pagebuilder/components/slider/index.md deleted file mode 100644 index 9fb6a587dc..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/slider/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Slider ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Slider/slider.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/tabs/index.md b/pwa-devdocs/src/pagebuilder/components/tabs/index.md deleted file mode 100644 index e5933b9b66..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/tabs/index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Tabs ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Tabs/tabs.md %} -{% include auto-generated/pagebuilder/lib/ContentTypes/TabItem/tabItem.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/text/index.md b/pwa-devdocs/src/pagebuilder/components/text/index.md deleted file mode 100644 index 4e3276bb68..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/text/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Text ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Text/text.md %} diff --git a/pwa-devdocs/src/pagebuilder/components/video/index.md b/pwa-devdocs/src/pagebuilder/components/video/index.md deleted file mode 100644 index f26599576b..0000000000 --- a/pwa-devdocs/src/pagebuilder/components/video/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Video ---- - - - -{% include auto-generated/pagebuilder/lib/ContentTypes/Video/video.md %} diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/AddAggregatorOverview.svg b/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/AddAggregatorOverview.svg deleted file mode 100644 index 05ee439954..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/AddAggregatorOverview.svg +++ /dev/null @@ -1 +0,0 @@ -master formataggregatorBuild out your aggregator to retrieve properties from your content type nodes within the master format.Return the properties in an object so that the framework can push it to you component to populate corresponding properties. componentuse utility & DOM functionsreturn property object \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/AggregatorHTMLConsoleOutput.png b/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/AggregatorHTMLConsoleOutput.png deleted file mode 100644 index 63f7440517..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/AggregatorHTMLConsoleOutput.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/AggregatorObjectConsoleOutput.png b/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/AggregatorObjectConsoleOutput.png deleted file mode 100644 index 65504ed314..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/AggregatorObjectConsoleOutput.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/MasterFormatHTML.svg b/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/MasterFormatHTML.svg deleted file mode 100644 index 887fbed553..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/MasterFormatHTML.svg +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - content type - - - - - - appearance - - - - - - element - - - - - - styles - - - - - - classes - - - - - - html content - - - - - - text - - - - - <div data-content-type="example_quote" data-appearance="default" data-element="main" style="border-style: none; border-width: 1px….more;”> - <blockquote class=“quote blue-quote" data-element="quote">I know where I came from—but where did all you zombies come from?</blockquote> - <div class="quote-author" data-element="author">Robert A. Heinlein</div> - <div class="quote-description" data-element="description"> - <div> - <span style="color: #808080;"> - <em>All You Zombies</em> (short story) - </span> - </div> - </div> - </div> - - - - - - structure - - - - HTML content from - tinyMCE editor used for - Quote’s description input - - - - \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/MasterFormatToComponent.svg b/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/MasterFormatToComponent.svg deleted file mode 100644 index ff7604fd74..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/images/MasterFormatToComponent.svg +++ /dev/null @@ -1 +0,0 @@ -React componentsmaster formatMagento instancePWA appPage Builder for PWAConverting the master format HTML into React components \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/index.md b/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/index.md deleted file mode 100644 index 287ab2a3c5..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-aggregator/index.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Add aggregator ---- - -The purpose of the configuration aggregator (`configAggregator`) is to retrieve properties from a content type's HTML and return those properties as a flat object of `key:values`. The framework (specifically the ``) then passes this object to your component, where you can assign the properties to your component's corresponding properties for rendering within a PWA Studio app. - -![Aggregator Overview](images/AddAggregatorOverview.svg) - -## Content type HTML - -The key to building out your aggregator is knowing the structure, content, and properties available in your content type's master format. You can do this the hard way by looking in the database of your Magento instance (specifically, the `content` field in the `cms_page` and `cms_block` tables). But there is a better way. - -**Protip**: Place a `console.log(node)` at the top of your `configAggregator` function so you can see exactly what your content type's HTML (the `HTMLElement` passed by the framework) looks like. In the `ExampleQuote` starter code, you would add it as shown here: - -```js -export default (node, props) => { - console.log(node); - return { - // Retrieve properties from node here - }; -}; -``` - -The console output should look something like this: - -![Content type HTML](images/AggregatorHTMLConsoleOutput.png) - -The `node` (HTMLElement) passed to the aggregator contains only your content type's HTML from the master format, not the entire master format as you would find in the database. - -## The Aggregator - -The interface for a `configAggregator` is: - -```ts -(node: HTMLElement, props: {contentType: string, appearance: string}) => {[key: string]: any} -``` - -To recap, the purpose of your component's aggregator is to collect (aggregate) properties from your content type's HTML and return a property object for use in your component. The object you return should contain all the text, html, inline styles, and classes you need to faithfully reproduce your content type as a component in PWA Studio. - -Let's look at our Quote content HTML in detail (color coded for easier analysis) to determine the properties we want to pass to our component: - -![Master format HTML](images/MasterFormatHTML.svg) - -Here's what we think we need for our component: - -- The inline **styles** from the main node -- The **text** content from the `
` and `author` nodes -- The **HTML** content from the `description` node -- The CSS **classes** from all three child nodes (`
`, `author`, and `description`) - -To retrieve these properties, you'll want to use a combination of [HTMLElement DOM properties][] along with our [utility functions][], as shown next in the example. - -### Example aggregator - -Here is the aggregator we use for the `ExampleQuote` component: - -```js -import { getAdvanced } from '../../utils'; - -export default (node, props) => { - - console.log(node); - - return { - quote: node.childNodes[0].textContent, - author: node.childNodes[1].textContent, - description: node.childNodes[2].innerHTML, - ...getAdvanced(node) - }; -}; -``` - -First we `import` the [utility functions][] we want to use. In our case, we know that our Quote content type provides end users with the Advanced form section. So we import the `getAdvanced()` function from `utils.js`. This function is a wrapper that just runs a number of other utility functions that can be used independently if these values are on different nodes: - -```js -export function getAdvanced(node) { - return { - ...getPadding(node), - ...getMargin(node), - ...getBorder(node), - ...getTextAlign(node), - ...getCssClasses(node), - ...getIsHidden(node) - }; -} -``` - -Then we use the `element` names from the content type HTML (color coded in green above) as our property key names: `quote`, `author`, and `description`. Naming your properties like this helps to identify where the data in the component comes from. - -Next, we use the `textContent` and `innerHTML` DOM properties to grab the text and html values from the appropriate `childNodes`. - -Finally, we use the `getAdvanced()` utility function to retrieve all the property values from the Advanced section of our content type's form and use the spread operator `(...)` to expand them into the current object. - -{: .bs-callout-info} -The Quote content type also has a form section called Background (from the `pagebuilder_base_form_with_background_attributes` form). This section of the form allows end users to enter all kinds of background attributes, such as images, colors, positions and so on. If your custom content uses the Background section, you should retrieve the those attributes using the `getBackgroundImages(node)` utility function. However, to keep things simple for our component, we decided not to pull these attributes from the HTML. - -### Retrieving data from different Appearances - -If your content type has different appearances, the HTML for each appearance will also differ. To handle these differences, we provide the `appearance` within the `props` argument so you can modify your queries in order to retrieve data from the correct node. - -For our Quote content type, we only have one appearance (the default); so we do not need to use it. However, the Row content type has three appearances, so it uses a conditional based on the `props.appearance` value to determine the correct node to use, as shown here: - -```js -// Targeting appearances in the Row aggregator - -export default (node, props) => { - // Determine which node holds the data for the appearance - const dataNode = - props.appearance === 'contained' ? node.childNodes[0] : node; - return { - minHeight: dataNode.style.minHeight ? dataNode.style.minHeight : null, - ... - }; -``` - -## Test the aggregator - -The best way to see the properties returned by your aggregator is using `console.log()`. For our Quote aggregator, we can do something like this: - -```js -import { getAdvanced, getCssClasses, getBackgroundImages } from '../../utils'; - -export default (node, props) => { - console.log(node); - - const propObject = { - quote: node.childNodes[0].textContent, - author: node.childNodes[1].textContent, - description: node.childNodes[2].innerHTML, - ...getAdvanced(node) - }; - - console.log(propObject); - return propObject; -}; -``` - -Adding `console.log(node)` at the beginning of your aggregator function, and at he end (`console.log(propObject)`), helps to show you the HTML you receive and the object you return. The property object returned from our aggregator looks like this: - -![Aggregator object console output](images/AggregatorObjectConsoleOutput.png) - -{: .bs-callout-info} -You will need to know the property `key-values` you are returning so that that you can assign them to corresponding properties in your component when you build it out. - -[utility functions]: <{% link pagebuilder/utility-functions/index.md %}> - -[HTMLElement DOM properties]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentOutput.png b/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentOutput.png deleted file mode 100644 index 813aba5fb5..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentOutput.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentOutput.svg b/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentOutput.svg deleted file mode 100644 index 4e8c130e71..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentOutput.svg +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - return ( - <div style={ - formStyles - }> - - - <div className={ - classes.quote - }>{ - quote - }</div> - <div className={ - classes.quoteAuthor - }>{ - author - }</div> - <div - className={ - classes.quoteDescription - } - dangerouslySetInnerHTML={toHTML( - description - )} - /> - </div> - ); - - - - - - - - - - - { textAlign, border, marginTop….more } - - - - - - - - styles - - - - - - classes - - - - - - html content - - - - - - text - - - - \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentSteps.svg b/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentSteps.svg deleted file mode 100644 index 5086e6db8f..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-component/images/AddComponentSteps.svg +++ /dev/null @@ -1,140 +0,0 @@ - - - - AddComponentSteps - Created with Sketch. - - - - - - - - - - - - - - - - - - - - 4 - - - - - Apply CSS classes - - - Import and assign - CSS classes from - your component - stylesheet. - - - - - - - You - - - - - - - - - - Add props & prop-types - - - - - - - - - - - - - 1 - - - - - Add and assign props to - local variables that match - the props names from - your aggregator. - - - - - - - - - - - - - - 2 - - - - - Use JSX to recreate the - HTML markup of your - content type and apply both - content and style props. - - - Add JSX markup - - - - - - - - - - - - - 3 - - - - - Apply form styles - - - Group the styles from the - content type’s form into a - separate “styles object” to - simplify markup styling. - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-component/index.md b/pwa-devdocs/src/pagebuilder/custom-components/add-component/index.md deleted file mode 100644 index c2a0358558..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-component/index.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -title: Add component ---- - -The purpose of a Page Builder component is to recreate a Page Builder content type (from your Magento instance) to display inside a PWA app. Developing this component is similar to developing other React components in PWA Studio. However, the properties defined within a Page Builder component are determined by the properties returned from your configuration aggregator. The following steps highlight how to put these properties to use in your component: - -![Add Component steps overview](images/AddComponentSteps.svg) - -## Step 1: Add local props and prop-types - -The first step is to declare local variables that match the names of the props being passed from your aggregator, for destructuring. For our `ExampleQuote`, we declare and assign these properties as follows: - -```js -const ExampleQuote = props => { - const { - quote, - author, - description, - textAlign, - border, - borderColor, - borderWidth, - borderRadius, - isHidden, - marginTop, - marginRight, - marginBottom, - marginLeft, - paddingTop, - paddingRight, - paddingBottom, - paddingLeft, - cssClasses - } = props; -``` - -With a destructuring assignment, our component takes a `props` object and copies its values to our local variables. All you need to do is make sure the names of your local variables exactly match the names of the `props` passed from your aggregator. As noted before, you can use `console.log(props)` at the top of your component to see the names of the `keys` being passed in on the props object. - -Along with defining your local variables, you need to add the comparable `prop-types` to define exactly what can be passed into your component. The `ExampleQuote` component defines the following `prop-types`: - -```js -import { arrayOf, string, bool } from 'prop-types'; - -ExampleQuote.propTypes = { - quote: string, - author: string, - description: string, - textAlign: string, - border: string, - borderColor: string, - borderWidth: string, - borderRadius: string, - isHidden: bool, - marginTop: string, - marginRight: string, - marginBottom: string, - marginLeft: string, - paddingTop: string, - paddingRight: string, - paddingBottom: string, - paddingLeft: string, - cssClasses: arrayOf(string) -}; -``` - -## Step 2: Add JSX markup - -Your JSX markup should recreate the HTML structure of your Page Builder content type and provide the slots for rendering its content and styles. For example, here is the markup needed to recreate the structure of our Quote content type and host the local content-related `props` values from our aggregator: - -```jsx -const toHTML = str => ({ __html: str }); - -return ( -
-
{quote}
-
{author}
-
-
-); -``` - -Because our `description` property value is HTML, we need to use React's [dangerouslySetInnerHTML][] and `__html` to render it out properly. - -## Step 3: Apply form styles - -To make it easy to apply all the inline styles from your content type to your Page Builder component, you can create a separate object that contains only the styles retrieved from the content type's form. These styles include those that are retrieved by [utility functions][] like `getAdvanced()` and `getBackgroundImages()`. - -For our component, we created an object called `formStyles` to group our form styles as shown here: - -```js -const formStyles = { - textAlign, - border, - borderColor, - borderWidth, - borderRadius, - isHidden, - marginTop, - marginRight, - marginBottom, - marginLeft, - paddingTop, - paddingRight, - paddingBottom, - paddingLeft -}; -``` - -These are the styles returned from the Advanced form section of our Quote content type (using `getAdvanced()`). When they are grouped together as shown, we can apply them all at once to our component, as follows: - -```jsx -return ( -
-
{quote}
-
{author}
-
-
-); -``` - -Now we need to apply the CSS classes we used to style the rest of our content type. - -## Step 4: Apply CSS classes - -Applying CSS classes to your component in PWA involves importing both your CSS stylesheet and a PWA Studio function called `mergeClasses`. This function does exactly what its name implies: it merges classes from different sources into a single variable you can use to add your classes to your JSX, using `className`. - -For our component, we import our component stylesheet and the `mergeClasses` function as follows: - -```js -import defaultClasses from './exampleQuote.css'; -import { mergeClasses } from '../../../../../classify'; - -``` - -We then merge the classes from our stylesheet with any classes passed in on the props and use a single variable (`classes`) to apply our consolidated classes to the correct nodes in the JSX: - -```jsx -const classes = mergeClasses(defaultClasses, props.classes); - -return ( -
-
{quote}
-
{author}
-
-
-); -``` - -Merging the `props.classes` ensures that our component can apply and override styles from other components. - -In the previous code block, we only used a single class, `classes.quote`, to style the quote in our component. However, our original class required two different classes (`.quote` and `.blue-quote`) for styling. As a best practice, you want to use the `composes` construct from [CSS Modules][] as much as possible. - -For example, in our `exampleQuote.css`, we composed each color quote class with the `.qoute` class as shown in the following snippet: - -```css -.quote { - display: block; - font-size: 1.4em; - margin: 1em 1em 0.3em 0.6em; - quotes: '\201C''\201D''\2018''\2019'; - text-decoration: none; - font-style: italic; - word-break: normal !important; - line-height: 1.25em; - padding: 0; - font-weight: 300; -} -.blackQuote { - composes: quote; - color: #333333; -} -.blueQuote { - composes: quote; - color: #007ab9; -} -... -``` - -This ensures that for each colored quote class, we also apply the `.quote` class. - -## Component output - -If you have followed along using the `ExampleQuote` component, you should see something like this displayed in the PWA Venia app: - -![Add Component output](images/AddComponentOutput.svg) - -[utility functions]: {% link pagebuilder/utility-functions/index.md %} -[css modules]: {%link technologies/basic-concepts/css-modules/index.md %} -[dangerouslysetinnerhtml]: https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/images/AddStylesheetCamelCase.png b/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/images/AddStylesheetCamelCase.png deleted file mode 100644 index 43aa61b8c0..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/images/AddStylesheetCamelCase.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/images/AddStylesheetSteps.svg b/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/images/AddStylesheetSteps.svg deleted file mode 100644 index 172f49dc95..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/images/AddStylesheetSteps.svg +++ /dev/null @@ -1 +0,0 @@ -YouCopy content type classes1Copy the classes from the frontend css of your content type.2Change the LESS syntax to standard CSS syntax.Change LESS to CSSCSS3Rename classes (optional)Change your class names to camelCase to to enjoy dot syntax and intellisense. \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/index.md b/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/index.md deleted file mode 100644 index 1e7449389e..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/add-stylesheet/index.md +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: Add stylesheet ---- - -Styling your Page Builder components is the same as styling any other component in PWA Studio. However, the CSS stylesheet for your component should define CSS classes that are comparable to the CSS classes you use on the frontend for original content type (`view/frontend/web/css/source/content-type//_import.less`). The following steps highlight the tasks for setting up the CSS classes for your component: - -![Add Stylesheet steps](images/AddStylesheetSteps.svg) - -## Step 1: Add content type classes - -Start by adding the CSS classes from the frontend css of your content type. For our Quote content type, we copied the frontend styles (`app/code/Example/PageBuilderQuote/view/frontend/web/css/source/content-type/example-quote/_import.less`) and added them to our `exampleQuote.css`. - -## Step 2: Convert LESS to CSS - -PWA studio uses [CSS Modules][]. It does not include tooling for LESS pre-processors, so you will need to convert your LESS into standard CSS style rules. For example, the LESS stylesheet for our Quote content type is shown here, followed by the equivalent CSS we included in our `exampleQuote.css`. - -**Quote content type LESS styles** (`_import.less`): - -```scss -& when (@media-common = true) { - blockquote.quote { - display: block; - font-size: 1.3em; - margin: 1em; - padding: 0.5em 10px; - quotes: "\201C" "\201D" "\2018" "\2019"; - text-decoration: none; - word-break: normal !important; - line-height: 1.5; - padding: 0; - font-weight: 300; - &:before { - content: open-quote; - font-size: 2.6em; - margin-right: 0.2em; - vertical-align: -0.35em; - line-height: 0; - margin-left: -0.5em; - font-weight: 300; - } - &:after { - content: close-quote; - font-size: 0; - line-height: 0; - margin-left: 0; - } - } - div { - &.quote-author { - text-align: left; - padding-right: 30px; - font-size: 14px; - color: #666; - margin-left: 1.1em; - } - &.quote-description { - text-align: left; - padding-right: 30px; - font-size: 14px; - color: #999; - margin-left: 1.1em; - font-weight: 300; - } - } - .black-quote { - color: #333333; - &:before { - color: #333333; - } - } - .blue-quote { - color: #007ab9; - &:before { - color: #71adcc; - } - } - .green-quote { - color: #009900; - &:before { - color: #009900; - } - } - .red-quote { - color: #990000; - &:before { - color: #990000; - } - } - .purple-quote { - color: #990099; - &:before { - color: #990099; - } - } -} -``` - -**Equivalent component styles** (`exampleQuote.css`): - -```css -.quote { - display: block; - font-size: 1.4em; - margin: 1em 1em 0.3em 0.6em; - quotes: '\201C''\201D''\2018''\2019'; - text-decoration: none; - font-style: italic; - word-break: normal !important; - padding: 0; - font-weight: 300; -} -.quote:before { - content: open-quote; - font-size: 2.4em; - margin-right: 0.1em; - vertical-align: -0.3em; - line-height: 0; - margin-left: -0.3em; - font-weight: 300; -} -.quote:after { - content: close-quote; - font-size: 0; - line-height: 0; - margin-left: 0; -} -.quoteAuthor { - padding-right: 30px; - font-size: 16px; - color: #333333; - line-height: 24px; - margin-left: 1.5em; - word-break: normal !important; - font-weight: 600; -} -.quoteDescription { - position: relative; - padding-right: 30px; - font-size: 16px; - line-height: 18px; - color: #666666; - margin-left: 1.5em; - font-weight: 300; - word-break: normal !important; -} -.blackQuote { - color: #333333; -} -.blackQuote::before { - color: #333333; -} -.blueQuote { - color: #007ab9; -} -.blueQuote::before { - color: #007ab9; -} -.greenQuote { - color: #009900; -} -.greenQuote::before { - color: #009900; -} -.redQuote { - color: #990000; -} -.redQuote::before { - color: #990000; -} -.purpleQuote { - color: #990099; -} -.purpleQuote::before { - color: #990099; -} -``` - -## Step 3: Rename classes (optional) - -Renaming your class names to use camelCase instead of hyphens allows you to work with CSS classes in your component as if they were JavaScript object properties. For example, if you name the class for the quote author's name as `.quote-author` (with a hyphen), you must access this class in your component like this: - -```html -
{author}
-``` - -This not only uses a string which is prone to errors, but you don't have the benefit of your editor's intellisense. - -Compare that to using camelCase for your hyphenated class names by renaming `.quote-author` to `.quoteAuthor` and thereby enabling access to CSS classes using dot syntax, as shown here: - -![Change class names to camelCase](images/AddStylesheetCamelCase.png) - -**Protip**: Use camelCase to rename your CSS classes so that you can use dot syntax and intellisense to browse through your style rules more easily when applying them to your component. - -[css modules]: {%link technologies/basic-concepts/css-modules/index.md %} diff --git a/pwa-devdocs/src/pagebuilder/custom-components/debugging/index.md b/pwa-devdocs/src/pagebuilder/custom-components/debugging/index.md deleted file mode 100644 index 4df74e871e..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/debugging/index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Debugging tips ---- - -If you haven't yet modified the config object and setup the references you'll see the following console warning, telling you the component is missing: - -```text -parseStorageHtml.js?4091:67 No config aggregator defined for content type X, this content type won't be rendered. -``` - -If you _have_ modified the configuration and your content type is still not displaying, debug through `packages/pagebuilder/lib/parseStorageHtml.js` to determine if your configuration item is correctly detected. diff --git a/pwa-devdocs/src/pagebuilder/custom-components/overview/images/OverviewSteps.svg b/pwa-devdocs/src/pagebuilder/custom-components/overview/images/OverviewSteps.svg deleted file mode 100644 index 6442f6f438..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/overview/images/OverviewSteps.svg +++ /dev/null @@ -1 +0,0 @@ -4Add componentBuild out your React component using the properties from the configAggregator.3Build out the CSS styles for your component (as needed).Add stylesheetCSS2Add aggregatorBuild out your configAggregator to get properties from your content type’s master format.YouSet up component1Create and configure your component files to the component framework. \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/overview/images/PageBuilderQuoteAdmin.png b/pwa-devdocs/src/pagebuilder/custom-components/overview/images/PageBuilderQuoteAdmin.png deleted file mode 100644 index 3116c95199..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/overview/images/PageBuilderQuoteAdmin.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/overview/images/PageBuilderQuoteStorefront.png b/pwa-devdocs/src/pagebuilder/custom-components/overview/images/PageBuilderQuoteStorefront.png deleted file mode 100644 index e246a6fc41..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/overview/images/PageBuilderQuoteStorefront.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/overview/index.md b/pwa-devdocs/src/pagebuilder/custom-components/overview/index.md deleted file mode 100644 index c9216fe78c..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/overview/index.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Overview ---- - -Let's assume you have at least one _custom_ Page Builder content type rendering content on your Magento storefront. But now you want that content to show up in your PWA app as well. What do you do? Short answer: You create a custom PWA Page Builder component (also know as a "content type component"). The long answer is described in this series of topics. The steps shown here describe the recommended process for developing content type components: - -![Overview of steps](images/OverviewSteps.svg) - -The topics for these steps show you how to create the code that retrieves properties (content and styling) from your content type HTML (in the configAggregator) and assign those properties to the equivalent properties in your in content type component. - -## Prerequisites - -Before you start creating your custom content type component in PWA Studio, make sure you have met the following prerequisites: - -- Your Magento instance should have a custom content type added and saved to the **home** page in the Admin. Currently, the `home` page is the only page you can render Page Builder content within PWA Studio. -- Your Magento instance should render this content type on the home page of your storefront. - -{: .bs-callout-info} -We assume you already have the PWA Studio set up and running in your development environment. If you do not, [use these instructions][] to do that now. - -## Using the Quote content type - -To help explain the process of creating a custom Page Builder component, we frequently refer to a component called `ExampleQuote`. We built this component as the PWA counterpart to the example Quote content type found on the [GitHub pagebuilder-examples repo][]. - -If you want to follow along with these topics more closely, [download and install the PageBuilderQuote module][] in your Magento instance and use it to fulfill the prerequisites previously mentioned. - -## Home page in Admin - -The first prerequisite is to add and save your custom content type to your Magento Home page in Admin. Here we see the Quote content type saved to the Home page in the Admin: - -![PageBuilderQuote in Admin](images/PageBuilderQuoteAdmin.png) - -## Home page on Storefront - -The second prerequisite is to ensure that your custom content type renders successfully in the storefront of your Magento instance. Here we see the Quote content type rendered on the Home page of a Luma storefront: - -![PageBuilderQuote on Storefront](images/PageBuilderQuoteStorefront.png) - -After you have met these prerequisites, you are ready to begin creating your custom Page Builder component in the PWA Studio. - -[use these instructions]: <{% link venia-pwa-concept/setup/index.md %}> - -[download and install the pagebuilderquote module]: https://github.com/magento-devdocs/pagebuilder-examples/tree/master/Example/PageBuilderQuote - -[github pagebuilder-examples repo]: https://github.com/magento-devdocs/pagebuilder-examples/tree/master/Example/PageBuilderQuote diff --git a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/ConfigureComponentOutput.png b/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/ConfigureComponentOutput.png deleted file mode 100644 index 30fc0ed55a..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/ConfigureComponentOutput.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/PageBuilderConfigFile.png b/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/PageBuilderConfigFile.png deleted file mode 100644 index 0a43b1b6a1..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/PageBuilderConfigFile.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/PageBuilderFilesSetup.png b/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/PageBuilderFilesSetup.png deleted file mode 100644 index 7d5b2990ef..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/PageBuilderFilesSetup.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/SetupComponentSteps.svg b/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/SetupComponentSteps.svg deleted file mode 100644 index 3bd49db0b2..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/SetupComponentSteps.svg +++ /dev/null @@ -1 +0,0 @@ -YouCreate starter files1Create starter code for the four files that make up your component.2Add your starter files to the framework configuration object.Configure componentCSS \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/SetupComponentTest.svg b/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/SetupComponentTest.svg deleted file mode 100644 index e71e7b10b0..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/images/SetupComponentTest.svg +++ /dev/null @@ -1 +0,0 @@ -ExampleQuote component rendered using starter code \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/index.md b/pwa-devdocs/src/pagebuilder/custom-components/setup-component/index.md deleted file mode 100644 index 7309edafee..0000000000 --- a/pwa-devdocs/src/pagebuilder/custom-components/setup-component/index.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Set up component ---- - -Setting up your component is about getting the essential component files in place so that your component is actively participating in the Page Builder component framework. After you create these files and wire them into the component framework, you can focus all your attention on developing each file to faithfully recreate your content type as a PWA component. The following steps highlight the tasks for setting up your component: - -![Component setup steps](images/SetupComponentSteps.svg) - -## Step 1: Create starter files - -The first thing you need to do within PWA Studio is create the directory and skeleton files needed for your component, as follows: - -- **configAggregator.js** (required) - Function to retrieve content and styling properties from your content type's master format HTML. -- **myComponent.js** (required) - React component for populating properties that correspond to the original Page Builder content type. For our ExampleQuote, we use `exampleQuote.js`. -- **myComponent.css** (optional but usually needed) - CSS classes that provide addition styles needed to present your component as desired. For our ExampleQuote, we use `exampleQuote.css`. -- **index.js** (required) - Entry file needed to identify your component in PWA Studio. - -Currently, you need to add your content type's component, like `ExampleQuote`, to the `ContentTypes` directory, where the native Page Builder components are kept. This will change when we implement different rules for extending Page Builder components. But for now, add your custom content type components as shown here: - -![Component file structure](images/PageBuilderFilesSetup.png) - -Starter code for the `ExampleQuote` component files is provided as follows. - -### configAggregator.js - -```js -export default (node, props) => { - return { - // Retrieve properties from node here - }; -}; -``` - -### exampleQuote.css - -```css -/* class for testing setup */ -.testClass { - line-height: 1.4em; - font-size: 1em; - color: #0066cc; -} -``` - -### exampleQuote.js - -```jsx -import React from 'react'; -import { mergeClasses } from '../../../../../classify'; -import defaultClasses from './exampleQuote.css'; -import { shape, string } from 'prop-types'; - -const classes = mergeClasses(defaultClasses, props.classes); - -// Component for testing setup -const ExampleQuote = props => { - return ( -
-
Content Type: {props.contentType}
-
Appearance: {props.appearance}
-
- ); -}; - -ExampleQuote.propTypes = { - classes: shape({ - testClass: string - }), - contentType: string, - appearance: string -} - -export default ExampleQuote; -``` - -### index.js - -```js -export { default } from './exampleQuote'; -``` - -## Step 2: Configure component - -Configuring your component is about connecting your component to the Page Builder component framework. The framework provides a static config object (in `config.js`) that acts as a kind of registry of content types supported within PWA Studio. To include support for your custom content type component, you'll need to add an entry to the `config.js`: - -![Component config file](images/PageBuilderConfigFile.png) - -Open the `config.js` file and `import` your `configAggregator`. The import statement for our ExampleQuote is shown here: - -```js -import exampleQuoteConfigAggregator from './ContentTypes/ExampleQuote/configAggregator'; -``` - -Add an entry that references your `configAggregator` and `component`, using the name of your content type as the `key`. For our `ExampleQuote`, the name of the Quote content type is `example_quote`, so the entry for our Quote component (`ExampleQuote`) in the config file looks like this: - -```js -example_quote: { - configAggregator: exampleQuoteConfigAggregator, - component: React.lazy(() => import('./ContentTypes/ExampleQuote')) -}, -``` - -### A note about lazy loading components - -When building PWAs, performance is key. That's why we recommend loading less critical components using `React.lazy`. This will result in a very slight delay in that content rendering but will ensure we don't bloat the bundle size for the store. For more information, see the [react lazy loading][] docs on the React site. - -By default, we apply `React.lazy` to the following content types: Banner, Slider, Slide Item, Tab, Tab Item, Button, Button Item, Block, Products, HTML, and Divider. - -To have your component loaded lazily you simply have to wrap your `component` reference in a call to `React.lazy` as previously shown for the ExampleQuote component: - -```js -component: React.lazy(() => import('./ContentTypes/ExampleQuote')) -``` - -## Test the component setup - -After adding these files and hooking them up to the framework through the configuration file (`config.js`), your skeleton component will appear on the Venia home page: - -![ExampleQuote component rendered with starter code](images/ConfigureComponentOutput.png) - -If you see this rendering without errors in the Venia app, you are ready to start developing your content type component. - -## Troubleshooting - -If you have errors, make sure you have: - -1. Copied the correct starter code for each of the four files. -2. Added the correct name of your content type to the `config.js` file (`example_quote` if you are using the Quote content type). - -[react lazy loading]: https://reactjs.org/docs/code-splitting.html#reactlazy diff --git a/pwa-devdocs/src/pagebuilder/images/PageBuilderBigPicture1.svg b/pwa-devdocs/src/pagebuilder/images/PageBuilderBigPicture1.svg deleted file mode 100644 index 0c719b64b5..0000000000 --- a/pwa-devdocs/src/pagebuilder/images/PageBuilderBigPicture1.svg +++ /dev/null @@ -1 +0,0 @@ -Equivalent Page Builder content type React componentsPage Builder content types (master format HTML)Magento DatabasePWA Studio appPage Builder Integration Framework (content type processing)The integration matches Page Builder content types to their equivalent Page Builder React componentsmobile devicePWA StudioMagento Commerce 2.3.4+12 \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/images/PageBuilderIntegration.svg b/pwa-devdocs/src/pagebuilder/images/PageBuilderIntegration.svg deleted file mode 100644 index b045c3f488..0000000000 --- a/pwa-devdocs/src/pagebuilder/images/PageBuilderIntegration.svg +++ /dev/null @@ -1 +0,0 @@ -Your custom content typesYour custom React componentsYour custom content types can also participate in this integration…You will need to create your own React components that are equivalent to your custom Page Builder content types…15 native Page Builder content types15 equivalent Page Builder React componentsdatabasemaster format HTMLPage Builder content type React componentsPage Builder integration frameworkMagento Commerce 2.3.4+PWA StudioPWA Studio requests a page built with Page Builder content types. This page is stored in the Magento database as a block of HTML called the master formatPWA Studio displays the page on the storefront using the integration’s equivalent Page Builder content type React components12…However……These docs explain how. \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/images/PageBuilderIntegrationDetails.svg b/pwa-devdocs/src/pagebuilder/images/PageBuilderIntegrationDetails.svg deleted file mode 100644 index 5a576ee74d..0000000000 --- a/pwa-devdocs/src/pagebuilder/images/PageBuilderIntegrationDetails.svg +++ /dev/null @@ -1 +0,0 @@ -NOYES47Uses configuration to return the content type’s equivalent React component.Magento Commerce 2.3.4+PWA app1Requests content (GraphQL) and returns CMS page or block HTML.CustomerPageBuilderContentTypeFactoryproperty aggregatorscontent type componentsmaster format parserIs it Page Builder content?( )config function9Returns Page Builder content to the PWA app (Venia).Returns object tree of properties.Passes master format.Passes object tree to factory.8Parse each content type from master format and use configuration to return properties from its configAggregator.for each content typeRenders and returns components with properties.356( )( )2RichContentDeveloper integration points for their custom content type components \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/index.md b/pwa-devdocs/src/pagebuilder/index.md deleted file mode 100644 index 94c16a106e..0000000000 --- a/pwa-devdocs/src/pagebuilder/index.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Page Builder to PWA integration ---- - -{: .bs-callout-info} -The Page Builder integration to PWA Studio is only compatible with Magento Commerce 2.3.4+. A GraphQL change within Magento Commerce 2.3.4 was necessary in order to integrate the Page Builder Products content type into PWA Studio. - -## Page Builder Integration: The Big Picture - -At the highest level, the Page Builder integration into PWA Studio simply ensures that CMS Pages built in Magento Commerce with _native_ Page Builder content types are rendered correctly within PWA Studio apps. - -The diagram below shows how the PWA Studio makes a request to the Magento Commerce backend to retrieve a CMS page for processing. The Page Builder integration framework processes the original Page Builder HTML and returns a group of React components that faithfully reproduces the Page Builder content for display in a PWA Studio app. - -![Page Builder Integration Big Picture](images/PageBuilderBigPicture1.svg) - -1. The Page Builder integration framework processes Page Builder content types within a CMS Page: Rows, Headings, Banners, Sliders, and so on. - -2. A set of equivalent content type React components -- Row, Heading, Banner, Slider, Text and so on -- are populated with the content and style properties from the original Page Builder content types so they can be displayed correctly within PWA Studio app storefronts. - -## Page Builder Integration: Custom Content Types - -If you only used Page Builder's 15 native content types (Dynamic Blocks are not supported), your Page Builder pages are automatically rendered within a PWA Studio app. No development work is necessary. However, if you use one or more of your own custom Page Builder content types within your CMS pages (for example, a [Quote-Testimonial content type][]), you will need to create your own equivalent Page Builder React component and integrate it within the framework. Otherwise, your custom content type will not appear on the storefront within a PWA Studio app. That area of your page will simply be blank. - -{: .bs-callout-info} -To develop and integrate your own custom content type components into your PWA Studio app, follow our [Creating custom components][] tutorial. - -![Page Builder Integration Overview](images/PageBuilderIntegration.svg) - -## Page Builder Integration Framework: The Details - -As part of the Page Builder integration to PWA Studio, we implemented a framework that converts Page Builder’s master format (HTML) into a structured format that works in React and PWA Studio. The components and functions within the Page Builder integration work together to: - -* Receives Page Builder content types in the original HTML format (**RichContent** and **PageBuilder** components) - -* Extracts the content and properties from each content type's HTML (**Master Format parser**, **config function**, and **property aggregators**) - -* Retrieves the equivalent content type React components for those content types (**ContentTypeFactory**, **config function**, and **content type components**) - -* Populates those React components with the content and style properties from the original content types (**ContentTypeFactory and content type components**) - -* Returns those components for for display in a PWA Studio app (**PageBuilder** and **RichContent** components) - -The components and functions that provide these services are described as follows: - -**RichContent**: The `` component provides the entry point into the Page Builder PWA framework. It determines whether the HTML passed by the PWA Studio app contains Page Builder content. If it does, the HTML is sent to the `` component for processing. If not, the HTML is sent directly to the PWA Studio app for display. - -**PageBuilder**: The `` component (not to be confused with the individual Page Builder React components) directs the parsing of the master format HTML as well as retrieving, populating, and returning the equivalent React components back to the Venia app. - -**Master Format parser**: The master format parser (`parseStorageHtml()`) decomposes the master format HTML into the content type HTML fragments (HTMLElements) that compose the master format. The parser sends the content type HTML to the correct property aggregator (`configAggregator`) using the configuration object. - -**Config function** (_integration point_): The configuration function (`getContentTypeConfig()`) provides an interface for retrieving a content type's _property aggregator_ and its corresponding _content type component_. The configuration object also provides the integration point for your own custom content type components. See [Set up component][] for details. - -**Property aggregator** (_integration point_): The property aggregator for a content type (example: `bannerConfigAggregator`) is a function that retrieves both content and style properties from the content type's HTML. Aggregators typically use both DOM properties and several provided framework utility functions to retrieve these properties and write them to flat property objects used to populate the content type React components. For each of your custom content types, you will need to create your own property aggregator. See [Add aggregator][] for details. - -**Content type component** (_integration point_): The content type component is a React component that is equivalent to a Page Builder content type. There are 15 content type components within PWA Studio: Row, Column, Tabs, Banners, Sliders, and so on. Each content type component is populated with the original content and style properties from the content type to faithfully represent your Page Builder content within a PWA Studio app like Venia. For each of your custom content types, you will need to create the equivalent content type React component . See [Add component][] for details. - -**ContentTypeFactory**: The `` component parses a property object tree to retrieve the equivalent React component for each content type property object it finds. It then populates these components and sends them back to the PWA Studio app as a composite React element displayed to the end user. - -## Page Builder Integration Framework: How it works - -The framework executes on the client side to ensure compatibility with the various hosting options available for Magento Commerce. The following flow diagram describes how the parts of the framework work together to render Page Builder components within the Venia app. - -![Page Builder Integration Details](images/PageBuilderIntegrationDetails.svg) - -1. The **Venia app** sends a GraphQL query to get the user's requested page. This requested page comes from the `content` field of `cms_pages` table in Magento's database. The content returned is an HTML string with Page Builder meta data. We call this HTML string the master format, which is passed to the `` component for initial processing. - -2. The **RichContent** component determines if the HTML string contains Page Builder content, using simple pattern recognition. If the HTML does not include Page Builder content, it is returned to Venia and rendered as plain HTML. If the HTML does include Page Builder content, the HTML string (which we can now define as a master format) is passed to the `` framework component, which starts the process of matching the content types within the master format to their equivalent PWA Studio React components. - -3. The **PageBuilder** framework component passes the master format to the framework's parser function called `parseStorageHTML()`. - -4. The **parser** function parses the master format HTML recursively to decompose all the Page Builder content types into their own `HTMLElement` strings for further processing. When the parser finds a content type, it uses the framework's config function to access that content type's property aggregator. The aggregator retrieves content and styles from the `HTMLElement` and writes them to a flat object (used later to hydrate the content type component). - - {: .bs-callout-info} - Each Page Builder content type has its own corresponding property aggregator. For example, the Heading content type (rendered in the master format as HTML) has a Heading aggregator (`headingConfigAggregator`), which converts the Heading's HTML properties to a flat object with those same properties. The parser does this for each content type it finds in the master format: uses the `getContentTypeConfig()` function to find and run the content type's property aggregator, which returns an object with both the content and the style properties for that content type. All CMS pages built with Page Builder have at least two content types: a Row content type and at least one other content type contained within that Row, such as a Banner. - -5. When the **parser** function finishes processing all the content types within the master format, it returns a property object tree for those content types back to the `` component. - -6. The **PageBuilder** framework component passes the property object tree to the framework's `` component for further processing. - -7. Much like in step 4 with the parser, the framework's **ContentTypeFactory** component retrieves the equivalent React component for each content type property object it finds within the object tree. - -8. The **ContentTypeFactory** populates those React components with the property values retrieved from each content type's property aggregator. - -9. And finally, the **PageBuilder** framework component returns a composite React element with all the Page Builder content type components needed to render the original Page Builder content within a PWA Studio app. - -[Quote-Testimonial content type]: https://devdocs.magento.com/page-builder/docs/create-custom-content-type/overview.html -[Creating custom components]: <{%link pagebuilder/custom-components/overview/index.md %}> -[add aggregator]: <{%link pagebuilder/custom-components/add-aggregator/index.md %}> -[set up component]: <{%link pagebuilder/custom-components/setup-component/index.md %}> -[add component]: <{%link pagebuilder/custom-components/add-component/index.md %}> diff --git a/pwa-devdocs/src/pagebuilder/known-limitations/images/LimitationsTextAlign.png b/pwa-devdocs/src/pagebuilder/known-limitations/images/LimitationsTextAlign.png deleted file mode 100644 index 9939cd3894..0000000000 Binary files a/pwa-devdocs/src/pagebuilder/known-limitations/images/LimitationsTextAlign.png and /dev/null differ diff --git a/pwa-devdocs/src/pagebuilder/known-limitations/index.md b/pwa-devdocs/src/pagebuilder/known-limitations/index.md deleted file mode 100644 index 910cb652d1..0000000000 --- a/pwa-devdocs/src/pagebuilder/known-limitations/index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Known limitations ---- - -The following items are known limitations to implementing PWA Studio components for Page Builder content types: - -- **CMS Pages only** - Page Builder integration within PWA Studio only supports Magento CMS Pages created with Page Builder. It does not support CMS Blocks, Product content, or Category content created with Page Builder. -- **Widgets in TinyMCE** - Widgets are not supported within content types that provide text input from the TinyMCE editor, such as Text, Banner, Slider, and HTML Code. -- **Dynamic Blocks** - Not supported in PWA Studio. PWA Studio currently has no concept of a Dynamic Block. Dynamic Blocks required session information to correctly display their content. Currently this session is not shared between PWA Studio and the backend and there are no GraphQL endpoints for Dynamic Block. -- **Products text alignment** - Text alignment for Products does not work within the PWA Studio gallery because the gallery is rendered with the CSS grid layout. The Alignment property (as set within the Products content type form) will always default to `Left`. -- **Extensibility** - PWA Studio currently lacks an extensibility model, which prevents Page Builder from using an existing framework / model. We can potentially use the comment based root component declaration that is baked into PWA Studio, but this will require additional work. -- **GraphQL query results** - Some content types (such as Products) create a large amount of output from the GraphQL endpoint, even though we don't intend to render it. -- **Staging and Preview** - PWA Studio does not support cache invalidation, which means Staging and Preview are not supported in Venia. \ No newline at end of file diff --git a/pwa-devdocs/src/pagebuilder/utility-functions/index.md b/pwa-devdocs/src/pagebuilder/utility-functions/index.md deleted file mode 100644 index 58924cdaab..0000000000 --- a/pwa-devdocs/src/pagebuilder/utility-functions/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Utility functions ---- - -The utility functions help with retrieving commonly stored data in a content type. For example, the `getAdvanced(node)` wrapper function retrieves all the content type's Advanced form section settings so you do not have to worry about retrieving each one separately. Retrieving background images and associated properties is also made easy with the `getBackgroundImages(node)` function. - -For implementation details [View Source][] - - - -{% include auto-generated/pagebuilder/lib/utils.md %} - -[view source]: https://github.com/magento/pwa-studio/blob/feature/page-builder/packages/pagebuilder/lib/utils.js diff --git a/pwa-devdocs/src/peregrine/index.md b/pwa-devdocs/src/peregrine/index.md deleted file mode 100644 index 5c99451410..0000000000 --- a/pwa-devdocs/src/peregrine/index.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Peregrine ---- - -The Peregrine package is a collection of functions that act as the brains of your visual components. -They provide pieces of logic for UI components, such as the ones provided by the [Venia][] library. -Use or remix these functions and components to create a unique Magento PWA storefront. - -## Custom React hooks - -Many of the functions provided by Peregrine are [custom React hooks][]. -This lets them maintain an internal state without relying on an external library, such as Redux. - -Peregrine hooks are designed to be flexible, and non-opinionated about UI. -They contain code for providing data or behavior logic and do not render content themselves. -Rendering content is left up to UI components. - -Separating logic and presentation code gives developers more flexibility on how to use PWA Studio components with their own custom code. -A developer may choose to use a Venia feature that uses certain Peregrine hooks with minor visual modifications, or -they can use those same Peregrine hooks to develop their own feature with a different UI. - -For more information about custom hooks, see the React documentation for [Building Your Own Hooks][]. - -### Return signatures - -The return signatures of Peregrine hooks vary and is dependent on their purpose. - -Some return an array with *state* and *api* objects, which follow the same pattern as [`useState()`][] and [`useReducer()`]. -This lets you specify the variable names of the provided objects when you [destructure][] the array. - -Other Peregrine hooks return a single object. - -Use the reference docs on this site or in the [JSDoc][] blocks in the source code learn the API for each hook. - -## JSDoc blocks - -Most of the reference docs in this section are generated from [JSDoc][] blocks. -The currently published docs reflect what is available from the most recent release, but -the JSDoc blocks in the source are kept up to date for developers who want to work with unreleased code. - -## Source - -Visit the [`peregrine`][] package to view the source or contribute to this project. - -[venia]: {%link venia-pwa-concept/index.md %} - -[`peregrine`]: https://github.com/magento/pwa-studio/tree/master/packages/peregrine -[custom react hooks]: https://reactjs.org/docs/hooks-custom.html -[destructure]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment -[jsdoc]: https://devdocs.io/jsdoc/ -[`usestate()`]: https://reactjs.org/docs/hooks-reference.html#usestate -[`usereducer()`]: https://reactjs.org/docs/hooks-reference.html#usereducer -[building your own hooks]: https://reactjs.org/docs/hooks-custom.html diff --git a/pwa-devdocs/src/peregrine/reference/container-child/index.md b/pwa-devdocs/src/peregrine/reference/container-child/index.md deleted file mode 100644 index 23f8bf97eb..0000000000 --- a/pwa-devdocs/src/peregrine/reference/container-child/index.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: ContainerChild ---- - -The `ContainerChild` component is the only child allowed within a [Container] in Magento PWA storefront. -This component is responsible for rendering content. - -## Props - -| Name | Required | Description | -| -------- | :-------------------------------------------: | --------------------------------------------------------- | -| `id` | check_box | A unique string identifier | -| `render` | check_box | A [render prop] that should return the children to render | -{:style="table-layout:auto"} - -## Example - -``` jsx -import { ContainerChild } from '@magento/peregrine'; - -
-
Used just like a normal render() method
} - /> - ( -
Can render anything a normal component can render
- )} - /> -
; -``` - -[render prop]: https://reactjs.org/docs/render-props.html -[Container]: {% link technologies/basic-concepts/container-extensibility/index.md %} \ No newline at end of file diff --git a/pwa-devdocs/src/peregrine/reference/hooks/useDropdown/index.md b/pwa-devdocs/src/peregrine/reference/hooks/useDropdown/index.md deleted file mode 100644 index 70bd59e6dd..0000000000 --- a/pwa-devdocs/src/peregrine/reference/hooks/useDropdown/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: useDropdown ---- - - - -{% include auto-generated/peregrine/lib/hooks/useDropdown.md %} diff --git a/pwa-devdocs/src/peregrine/reference/hooks/useEventListener/index.md b/pwa-devdocs/src/peregrine/reference/hooks/useEventListener/index.md deleted file mode 100644 index dd9c2a427b..0000000000 --- a/pwa-devdocs/src/peregrine/reference/hooks/useEventListener/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: useEventListener ---- - - - -{% include auto-generated/peregrine/lib/hooks/useEventListener.md %} diff --git a/pwa-devdocs/src/peregrine/reference/hooks/usePagination/index.md b/pwa-devdocs/src/peregrine/reference/hooks/usePagination/index.md deleted file mode 100644 index 7180f6e258..0000000000 --- a/pwa-devdocs/src/peregrine/reference/hooks/usePagination/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: usePagination ---- - - - -{% include auto-generated/peregrine/lib/hooks/usePagination.md %} diff --git a/pwa-devdocs/src/peregrine/reference/hooks/useSearchParam/index.md b/pwa-devdocs/src/peregrine/reference/hooks/useSearchParam/index.md deleted file mode 100644 index 694d18a804..0000000000 --- a/pwa-devdocs/src/peregrine/reference/hooks/useSearchParam/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: useSearchParam ---- - - - -{% include auto-generated/peregrine/lib/hooks/useSearchParam.md %} - -## Example - -The following example, uses the `useSearchParam()` hook to get the `query` parameter from the URL. - - diff --git a/pwa-devdocs/src/peregrine/reference/hooks/useWindowSize/index.md b/pwa-devdocs/src/peregrine/reference/hooks/useWindowSize/index.md deleted file mode 100644 index 32d563ef73..0000000000 --- a/pwa-devdocs/src/peregrine/reference/hooks/useWindowSize/index.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: useWindowSize ---- - - - -{% include auto-generated/peregrine/lib/hooks/useWindowSize.md %} - -## Examples - -It is recommended to only create/use the WindowSizeContextProvider a single time at the top level of your app: - -```jsx -return( - - - -) -``` - -Inside a component in your application, use the `useWindowSize()` function to get the window size value that updates when the window size changes. - -```jsx -import { useWindowSize } from '@magento/peregrine'; - -function MyComponent(props) { - - const windowSize = useWindowSize(); - - return ( - - Inner window size: {windowSize.innerWidth} x {windowSize.innerHeight} - - ); - -} -``` diff --git a/pwa-devdocs/src/peregrine/reference/item/index.md b/pwa-devdocs/src/peregrine/reference/item/index.md deleted file mode 100644 index 44e4270a84..0000000000 --- a/pwa-devdocs/src/peregrine/reference/item/index.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Item ---- - - -The `Item` component takes a data object and renders it using a [render prop] or wraps it in an HTML element. - -This component is used as a direct child of the [`Items`] fragment. - -## Props - -| Name | Required | Default | Description | -| ------------ | :-------------------------------------------: | ------- | ------------------------------------------------------------- | -| `classes` | | `{}` | A classname hash | -| `hasFocus` | | `false` | Set to `true` if the browser is currently focused on the item | -| `isSelected` | | `false` | Set to `true` if the item is currently selected | -| `item` | check_box | | A data object. If this is a string, it is rendered as a child | -| `render` | check_box | `'div'` | A render prop or HTML tagname string, such as `"div"`. | -{:style="table-layout:auto"} - -## Example - -``` jsx -{% raw %} -import Item from '@magento/peregrine'; - - -{% endraw %} -``` - -[render prop]: https://reactjs.org/docs/render-props.html -[`Items`]: {% link peregrine/reference/items/index.md %} -[`List`]: {% link peregrine/reference/list/index.md %} \ No newline at end of file diff --git a/pwa-devdocs/src/peregrine/reference/items/index.md b/pwa-devdocs/src/peregrine/reference/items/index.md deleted file mode 100644 index 25f4b4e8ca..0000000000 --- a/pwa-devdocs/src/peregrine/reference/items/index.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Items ---- - -The `Items` component uses content in a data object to render a list of [`Item`] components. - -It follows the [Fragments] pattern and returns its children without a wrapping element. -This allows you to decide how you want to wrap your list of items. - -The `Items` component is used as a direct child of the [`List`] component. - -## Props - -| Name | Required | Description | -| ---------------- | :-------------------------------------------: | ------------------------------------------------------------------- | -| `items` | check_box | An iterable that yields `[key, item]` pairs such as an ES2015 [Map] | -| `renderItem` | | A [render prop] or HTML tagname string. | -| `selectionModel` | | A string corresponding to a selection model. | -{:style="table-layout:auto"} - -### Selection models - -{% include peregrine/reference/list-selection-models.md %} - -## Example - -``` jsx -import Items from '@magento/peregrine'; - -const data = { - s: { id: 's', value: 'Small' }, - m: { id: 'm', value: 'Medium' }, - l: { id: 'l', value: 'Large' } -}; - - -``` - -[`List`]: {% link peregrine/reference/list/index.md %} -[render prop]: https://reactjs.org/docs/render-props.html -[Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map -[Fragments]: https://reactjs.org/docs/fragments.html -[`Item`]: {% link peregrine/reference/item/index.md %} \ No newline at end of file diff --git a/pwa-devdocs/src/peregrine/reference/list/index.md b/pwa-devdocs/src/peregrine/reference/list/index.md deleted file mode 100644 index 05ad2980f3..0000000000 --- a/pwa-devdocs/src/peregrine/reference/list/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: List ---- - - -{% include auto-generated/peregrine/lib/List/list.md %} - -### Selection models - -{% include peregrine/reference/list-selection-models.md %} - -## Example - -``` jsx -{% raw %} -import { List } from '@magento/peregrine'; - -const simpleData = new Map() - .set('s', 'Small') - .set('m', 'Medium') - .set('l', 'Large') - - - -const complexData = new Map() - .set('s', { id: 's', value: 'Small' }) - .set('m', { id: 'm', value: 'Medium' }) - .set('l', { id: 'l', value: 'Large' }) - - (
    {props.children}
)} - renderItem={props => (
  • {props.value}
  • )} -/> -{% endraw %} -``` - -[render prop]: https://reactjs.org/docs/render-props.html -[Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map diff --git a/pwa-devdocs/src/peregrine/reference/price/index.md b/pwa-devdocs/src/peregrine/reference/price/index.md deleted file mode 100644 index 104666cf30..0000000000 --- a/pwa-devdocs/src/peregrine/reference/price/index.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Price ---- - - -{% include auto-generated/peregrine/lib/Price/price.md %} - -## Example - -```jsx -import Price from '@peregrine/Price'; -import cssModule from './my-pricing-styles'; - -; -/* - $ - 88 - . - 81 -*/ -``` diff --git a/pwa-devdocs/src/peregrine/reference/rest-api-client/index.md b/pwa-devdocs/src/peregrine/reference/rest-api-client/index.md deleted file mode 100644 index 1eee2e23fd..0000000000 --- a/pwa-devdocs/src/peregrine/reference/rest-api-client/index.md +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: REST API client ---- - -The REST API client utility module provided by Peregrine allows you to work with non-GraphQL web APIs. -The default implementation is a client that works with the REST API for Magento 2.3 and above. - -## Magento 2 REST API client - -The Magento 2 REST API client provides a `request()` function which places a request to a Magento backend and returns a [`Promise`][] as a response. -This function is similar to the Web standard [`fetch()`][] function with a few differences in [response][] and [error][] handling. -It also contains features to support [multicasting][] and [rolling requests][]. - -For basic use cases, use the `request()` method. -For more advanced cases, use the [`M2ApiRequest`][] class, which the `request()` method wraps. - -### Syntax - -```js -request(resourceUrl, opts) -``` - -#### Parameters - -`resourceUrl` ([`UVString`][]) - -: A [Magento REST endpoint][]. - -`opts` (object) - -: An options object that can contain all possible [fetch options][]. - - Additional options: - - * `parseJSON` (boolean): Automatically parse the response into JSON format. - Defaults to `true`. - * `multicast` (boolean): Manually set whether a request should use the [multicasting][] feature. - -#### Returns - -A [`Promise`][] object that contains the result of the request. See [response handling][response]. - -### Usage - -The following example imports the `request()` function into another module: - -```js -import { RestApi } from '@magento/peregrine'; - -const { request } = RestApi.Magento2; -``` - -Use the `request()` function to place and receive API calls using `async/await` syntax: - -```js -async function displayGuestCartItems(cartId) { - const cartResponse = await request( - `guest-carts/${cartId}`, - { - method: 'GET' - } - ); - const cart = await cartResponse; - console.log(cart.items); -} -``` - -Or use the `Promise` object directly: - -```js -function displayGuestCartItems(cartId) { - return request( - `guest-carts/${cartId}`, - { - method: 'GET' - } - ) - .then(({ items }) => console.log(items);) -} -``` - -### Response handling - -The `request()` method returns a [`Promise`][] object with a fully parsed REST resource instead of an HTTP response as in the standard [`fetch()`][] API. - -To make `request()` behave like `fetch()`, set the value of `parseJSON` to `false` in the options object. -This changes the value passed to the `Promise.resolve()` function back to a [`Response`][] object. - -```js -request( - `guest-carts/${cartId}`, - { - method: 'GET', - parseJSON: false - } -).then(({ response }) => console.log(response);) -``` - -### Error handling - -Promises returned by `request()` are rejected if the server responds with an HTTP error code within the 4xx-5xx range. -This is different from the standard `fetch()` behavior, which ignores HTTP errors so it can resolve the promise and only fails on network connectivity errors. - -The Magento REST API uses HTTP error codes to denote failed operations, so -the `request()` method responds to these server-side errors by rejecting them. -When the server returns an error code, the `request()` method builds an error containing metadata for debugging and rejects the `Promise`. - - -### Multicasting - -The multicasting feature of the Magento 2 REST client collects all successive calls to the `request()` method and returns a single request and response that is shared to all method callers. - -In any distributed architecture, where applications are built from components with view, behavior, and data fetching strategy, multiple components may request the same resource at the same time. -GraphQL clients resolve this by merging GraphQL queries together, dispatching a request as a single call, and distributing the pieces of the GraphQL response to the original callers. -A direct call using `fetch()` or `XMLHttpRequest()` does not provide this functionality. - -The `request()` method makes up for this by using a pattern-matching rule on inflight requests. -All requests with the same method, path, and body text are considered multicastable by default. -A clone of the response object is returned if a request meets the following criteria: - -* The pattern of the new request matches one that is already in progress, i.e. the network has not loaded the resource yet. -* No unsafe operations, such as `POST`, have occurred to the target resource between the time of the original request and the new request. -* The request is not a `POST` request. - These requests create and/or modify server state, so it is unsafe to reuse their results. - -#### Override multicast - -The `multicast` configuration option forces multicasting to be `true` or `false` and bypasses the previously described rules. - -```js -// A normally multicast request forced not to multicast -request('carts/mine',{ method: 'GET', multicast: false }); - -// A normally non-multicast request forced to multicast -request( - 'carts/mine/items', - { - method: 'POST', - body: cartItem, - multicast: true - } -); -``` - -### Rolling requests - -A rolling request is a multicast which overrides and replaces matching, previous multicast requests. -It helps maintain a fresh resource, such as a shopping cart, and reduces network traffic by aborting outstanding matching requests. - -This feature has no effect on non-multicast requests. - -To use a rolling request, set the `cache` configuration option to `reload` or `no-store`. - -### The `M2ApiRequest` class - -The `request()` method is a convenience wrapper on top of the -`M2ApiRequest` class. - -Use the `M2ApiRequest` class if you want more control over your REST requests. - -```js -import { RestApi } from '@magento/peregrine'; -const { M2ApiRequest } = RestApi; - -function placeCancelable(emitter) { - const req = new M2ApiRequest( - 'some/slow/large/resource', - { - method: 'GET', - } - ); - req.run(); - emitter.on('someevent', () => { - req.abortRequest(); - }); - return req.getResponse(); // AbortError -} -``` - -#### API - -`new M2ApiRequest(resourceUrl, opts)` - -: Creates a new `M2ApiRequest` class to a specific `resourceUrl` using the configuration values in `opts`. - See `request()` method [parameters][]. - -`run()` - -: Execute the request. - This must be run before `getResponse()` or `abortRequest()` can be called. - -`getResponse()` - -: Get the promise for the network operation. - This method can only be called after `run()` executes. - This method exists so that requests can reuse the promises from other requests. - - **Returns:** [`Promise`][] - `Promise` object for the result of the request. - -`abortRequest()` - -: Abort the network operation. - Multicasted requests will catch the `AbortError` and attempt to reuse a cached request. - Other requests will pass the `AbortError` rejection to the consumer. - - **Kind:** Instance method of M2ApiRequest - -`isRolling()` - -: Used to determine if a request intends to use the [rolling requests][] feature and override prior requests to the same resource. - - **Returns**: boolean - True if the request is rolling. False otherwise. - -[`Promise`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise -[`fetch()`]: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch -[response]: #response-handling -[error]: #error-handling -[multicasting]: #multicasting -[rolling requests]: #rolling-requests -[`Response`]: https://developer.mozilla.org/en-US/docs/Web/API/Response -[Magento REST endpoint]: https://devdocs.magento.com/guides/v2.3/rest/list.html -[fetch options]: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters -[`UVString`]: https://developer.mozilla.org/en-US/docs/Web/API/USVString -[`M2ApiRequest`]: #the-m2apirequest-class -[parameters]: #parameters diff --git a/pwa-devdocs/src/peregrine/reference/router/index.md b/pwa-devdocs/src/peregrine/reference/router/index.md deleted file mode 100644 index 6efc4c697e..0000000000 --- a/pwa-devdocs/src/peregrine/reference/router/index.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Router ---- - -The Peregrine Router is a client-side router that is designed to understand the different storefront routes within Magento 2. -If using Peregrine to bootstrap your PWA, it is configured automatically. If not, the Router can be manually consumed. - -## Props - -| Name | Required | Description | -| ------------- | :-------------------------------------------: | ------------------------------------------------------------------------------------------------------- | -| `apiBase` | check_box | Root URL of the Magento store (including protocol and hostname) | -| `using` | | Router implementation from React-Router. Possible values: `BrowserRouter`, `HashRouter`, `MemoryRouter` | -| `routerProps` | | Any additional props to pass to React-Router | -{:style="table-layout:auto"} - -## Example - -The following example shows the manual usage of the Router component: - -``` jsx -import ReactDOM from 'react-dom'; -import { Router } from '@magento/peregrine'; - -ReactDOM.render( - , - document.querySelector('main') -); -``` \ No newline at end of file diff --git a/pwa-devdocs/src/peregrine/reference/toasts/useToastContext/index.md b/pwa-devdocs/src/peregrine/reference/toasts/useToastContext/index.md deleted file mode 100644 index 2550588bdb..0000000000 --- a/pwa-devdocs/src/peregrine/reference/toasts/useToastContext/index.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: useToastContext ---- - - - -{% include auto-generated/peregrine/lib/Toasts/useToastContext.md %} - -## Examples - -### Using the Toast context logic - -Import the ToastContextProvider and wrap it around components that use Toast data and functionality. - -```jsx -// MyComponent.js - -import {ToastContextProvider} from '@magento/peregrine' -import {ToastContainer, AddToastComponent} from './MyToastComponents' - -... - -const MyComponent = () =>{ - - return ( - - // A component which would display based on state. - // A component which adds a toast using actions. - - ) -} - -... -``` - -Call **useToastContext()** to get the current state of the toast store and a dispatch function. - -```jsx -// MyToastComponents.js - -import {useToastContext} from '@magnto/peregrine'; - -export const ToastContainer = () =>{ - const [toastState, toastDispatch] = useToastContext(); - - const toastData = toastState.map(toast=>{ - // Do something with the toast data - }) - - return
    {toastData}
    -} - -export const AddToastComponent = () =>{ - return - ( -
    - // Some component that allows you to add toast data using the - // toastDispatch() function or useToast() hook -
    - ) -} - -``` diff --git a/pwa-devdocs/src/peregrine/reference/toasts/useToasts/index.md b/pwa-devdocs/src/peregrine/reference/toasts/useToasts/index.md deleted file mode 100644 index 093da9fff5..0000000000 --- a/pwa-devdocs/src/peregrine/reference/toasts/useToasts/index.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: useToasts ---- - - - -{% include auto-generated/peregrine/lib/Toasts/useToasts.md %} - -## Examples - -### Adding a toast - -Use the `addToast()` function from the API to add a toast to the toast store. - -{: .bs-callout .bs-callout-info} -If an `onAction()` or `onDismiss()` callback is provided, the implementer _must_ call the passed in `remove()` function. -If the `onDismiss()` callback is not provided, the toast is removed immediately. - -```jsx -const { toasterState, api } = useToast(); -const { addToast } = api; - -addToast({ - type: 'error', - message: 'An error occurred!', - actionText: 'Retry', - onAction: remove => { - async attemptRetry(); - remove(); - }, - onDismiss: remove => { - async doSomethingOnDismiss(); - remove(); - }, - icon: -}); -``` - -See also: [ToastContainer][] - -[toastcontainer]: {%link venia-ui/reference/components/ToastContainer/index.md %} diff --git a/pwa-devdocs/src/peregrine/routing/index.md b/pwa-devdocs/src/peregrine/routing/index.md deleted file mode 100644 index ba9aab5332..0000000000 --- a/pwa-devdocs/src/peregrine/routing/index.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Routing in PWA Studio ---- - -For web applications, routing is the process of mapping a URL to specific page resources. - -In a multi-page application, routing is performed on the server side. -Every URL request fetches new HTML from the server and the browser loads the entire page. -This approach is inefficient because the same assets get loaded every time site navigation occurs. - -For a single-page application (SPA), such as a progressive web app, routing is performed on the client side. -Single-page applications do not reload the browser during navigation. -Instead, the application uses the URL to fetch smaller pieces of data from the server and updates specific items on the page. - -## Routing for PWA Studio storefronts - -PWA Studio provides tools that support both server-side and client-side routing. - -### Server-side routing - -Server-side routing is accomplished using the [UPWARD][] configuration file. -Since the configuration file defines how the server responds to requests, -you can specify a different template to render each page type, such as a CMS page or a product details page. - -Early versions of the Venia storefront used this approach, but -in the current version, every page request now returns the same HTML with the application shell. -The application decides how the page should render based on the request. - -If you want a better idea of how UPWARD works, follow the [Hello UPWARD tutorial][]. - -### Client-side routing - -Client-side routing happens inside the storefront application. -When a user navigates inside the application, it updates the relevant pieces instead of refreshing the entire page to update content. - -Since Venia is a single-page application, it uses client-side routing for internal navigation. - -## How routing works in Venia - -This section goes over the routing flow implemented in Venia. -It is the default workflow for all new projects created using the scaffolding tool, -but it is not the only possible workflow for routing. - -### Initial request - -Venia's UPWARD server handles the initial request to the storefront application. -Its `upward.yml` configuration tells the server to return an `index.html` page created at build time by Webpack, via the [HtmlWebpackPlugin][]. -The content of this file is the same for all page types. - -After the browser loads the application shell, routing is handled client-side by React Router. - -### Routes component - -Used inside the [App component][], the [Routes component][] provides the switch logic for deciding which component to use to render the main content for the current route. - -Routes in a PWA do not have to correspond to routes in the old Magento storefront. Venia has routes not defined in the Magento backend, such as _Create account_ or full page _Checkout_. -These routes are assigned components which render content for those pages in the Routes component. - -### MagentoRoute component - -The [MagentoRoute component][] handles the routes that are Magento-specific, such as a product or category page. -It uses its [Peregrine talon][] counterpart to determine which component to display. - -### useMagentoRoute() talon - -The [`useMagentoRoute()`][] talon returns the correct component for a page type. It uses the [`getRouteComponent()`][] helper function to get the **root component** associated with a page type. -It uses the `resolveUnknownRoute()` function to determine the page type for a route and retrieves the root component associated with that type using a global `fetchRootComponent` function. -The `fetchRootComponent` function is autogenerated at build time by the Buildpack RootComponentsPlugin, which searches for RootComponents in the project and builds a manifest. - -### resolveUnknownRoute() - -The [`resolveUnknownRoute()`][] function is a utility function for fetching page type information from the backend Magento server using a GraphQL query. -The `getRouteComponent()` function uses the information from this query to get the correct root component from an object that maps page types to root components. - -[upward]: {%link venia-pwa-concept/features/modular-components/index.md %} -[hello upward tutorial]: {%link tutorials/hello-upward/simple-server/index.md %} -[peregrine talon]: {%link peregrine/talons/index.md %} - -[app component]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/App/app.js -[routes component]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/Routes/routes.js -[magentoroute component]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/MagentoRoute/magentoRoute.js -[`usemagentoroute()`]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/talons/MagentoRoute/useMagentoRoute.js -[`getroutecomponent()`]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/talons/MagentoRoute/getRouteComponent.js -[`resolveunknownroute()`]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/Router/resolveUnknownRoute.js -[htmlwebpackplugin]: https://webpack.js.org/plugins/html-webpack-plugin/ diff --git a/pwa-devdocs/src/peregrine/talons/index.md b/pwa-devdocs/src/peregrine/talons/index.md deleted file mode 100644 index 9487201abb..0000000000 --- a/pwa-devdocs/src/peregrine/talons/index.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Talons ---- - -Most [React component][] contain two distinct sections: a section for logic and a presentational section. - -The logic section contains code for generating new values from props, maintaining local state, and lifecycle or side effect methods. -This section can be considered the "brains" of the component. - -The content section of a React component contains code that defines the component's DOM structure. -It often uses values from the logic part of the component to pass down into another component or display using HTML elements. - -PWA Studio separates these two sections into distinct components with specific concerns: a Venia UI component and a Peregrine Talon. - -## Peregrine talon overview - -Peregrine talons are the logic component counterparts for Venia UI components. -Each talon in Peregrine is designed to provide data or perform side effects for a specific Venia UI component. - -For example, the [`SearchBar`][] component uses the [`useSearchBar()`][] talon to get initial values and functions it needs to handle changes in focus or search term value. -The `useSearchBar()` talon also keeps track of the component's `expanded` state, which determines how the search bar looks. - -## Talons versus hooks - -Talons are a PWA Studio concept that represent a specialized type of React hook. - -Peregrine **hooks**, such as `useDropdown()` and `useWindowSize()`, are designed to be re-usable pieces of code, but -Peregrine **talons** are designed to fulfill the logic needs of individual Venia UI components. -This means that each talon corresponds to a single Venia component and is not useful outside the component. -If a talon needs to use functionality identical to another talon, it is provided by a Peregrine hook. - -For example, the functionality provided by the `useHeader()` talon is only relevant to the `Header` component. - -## Using talons - -Talons are not re-usable hooks, but they make it easier to work with UI components by providing standard functionality. -This lets developers focus on developing the presentation DOM and CSS pieces of a component. - -Venia UI components use talons by default, so developers can use Venia UI components as is without worrying about talons. -If developers want to change how a Venia UI component looks, they can import its associated talon into a new or modified UI component of the same type. - -### Talon props and returned object - -Talons use many of the same props as its Venia UI component counterpart. -These props are passed into the talon as a single object and are used to generate new values or perform side effects. - -The return value after calling a talon is an API object that UI components can destructure for values to display or assign to events, such as `onClick` or `onHover` functions. - -### Example - -The following code snippet comes from Venia's [`Pagination`][] UI component: - -``` jsx - -... - -import { usePagination } from '@magento/peregrine/lib/talons/Pagination/usePagination'; - -... - -const Pagination = props => { - const { currentPage, setPage, totalPages } = props.pageControl; - - const talonProps = usePagination({ - currentPage, - setPage, - totalPages - }); - - const { - handleLeftSkip, - handleRightSkip, - handleNavBack, - handleNavForward, - isActiveLeft, - isActiveRight, - tiles - } = talonProps; - - ... -} -``` - -[react component]: https://reactjs.org/docs/components-and-props.html -[`usesearchbar()`]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/talons/SearchBar/useSearchBar.js -[`searchbar`]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/SearchBar/searchBar.js -[`pagination`]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/Pagination/pagination.js diff --git a/pwa-devdocs/src/pwa-buildpack/configuration-management/index.md b/pwa-devdocs/src/pwa-buildpack/configuration-management/index.md deleted file mode 100644 index 1e6481838d..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/configuration-management/index.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: Configuration management ---- - -The PWA buildpack library provides small tools to configure your environment and larger, overall workflows that a developer has to configure and control. - -These configurations differ across projects and different environments within those projects. -For example, environments for development, testing, staging, and production are configured to support different behaviors. - -## The `.env` file - -Like the rest of PWA Studio, buildpack uses environment variables as its central source of configuration settings. -A PWA Studio project using buildpack requires a [`.env` file][] in its root directory. -Each line in the file contains a configuration using the following form: - -```text -NAME=value -``` - -In any script in any programming language, you can access these environment variables directly by sourcing the file as a legal POSIX shell script. - -## Command Line Interface (CLI) - -Buildpack provides a [`buildpack` CLI][] for creating `.env` files and validating environments. -It also provides library methods for connecting environment management workflows with other tools. - -Using these provided tools, you can keep global configuration values in a central location and propagate them throughout your project. -This lets you pass common settings down to different library functions without tightly coupling those settings together. - -## Configuration management rationale - -PWA Studio follows the principle that _all configuration that **can** be environment variables, **should** be environment variables_. - -Environment variables are portable, cross-platform, and reasonably secure. -They can be individually overridden to give the user a great deal of control over a complex system. -The [twelve-factor app][] methodology recommends storing config in the environment as its third factor. - -Many tools use environment variables strictly as edge-case overrides and store their canonical configuration in other formats because -under the strict POSIX definition, environment variables have some limitations: - -- An environment variable name is case insensitive. -- An environment variable's value can only be a string. -- Environment variables cannot be nested nor schematized, so they have no built-in data structures. -- Environment variables all belong to a single namespace, and every running process has access to all of them. - -These drawbacks are serious enough that some applications use alternate formats, such as: - -- `XML` -- `JSON` -- `YAML` -- `INI` / `TOML` -- `.properties` files in Java -- `.plist` files in MacOS -- PHP associative arrays -- Apache directives - -These formats have the following advantages over environment variables: - -1. They are a standard human-readable file format -2. They can support nesting and/or namespacing to organize values -3. They support data types and metadata - -However, none of these formats have _won_ and become an undisputed replacement for environment variables. -Each one has its own set of quirks and undefined behaviors. -None of them are deeply integrated with OS, shell, and container environments, and -they often do not work consistently across language runtimes. - -PWA Studio chooses to use environment variables, while providing simple tools for file format, namespacing, and validation. - -A centralized configurator passes on formatted pieces of the environment to specific tools as parameters, so -these tools do not need to know the specifics of the configuration scheme. -Entry point scripts, such as `server.js` and `webpack.config.js`, can use the [`loadEnvironment()`][] tool to deserialize environment variables into any kind of data structure, while storing persistent values in an `.env` file in the project root directory. - -Buildpack combines the features of several tools: - -- [dotenv][] for managing environment variables with `.env` files -- [envalid][] for describing, validating, and making defaults for settings -- [camelspace][] for easily translating configuration between flat environment variables and namespaced objects - -## Best practices - -The **config rule** in the [twelve-factor app][] methodology distinguishes configuration that "does not vary between deploys" from configuration that does. -It requires that configuration that does change between deploys be stored in the environment. -PWA Studio does not make such a distinction. -For config that must never vary, the PWA project maintainer can hardcode that configuration in the entrypoint scripts what use `loadEnvironment()`. - -To have environment-variable-based configuration management and enjoy the benefits of file format, namespacing, and validation at the same time, it's important to use `loadEnvironment()` in a certain way. - -### Configuration object - -The purpose of a function such as [`loadEnvironment()`][] is to keep configuration organized without tightly coupling a system to a manager object. -To achieve this, it is important to use `loadEnvironment()` and the `Configuration` object it produces at the "top level" or entry point of a program. - -Avoid passing a `Configuration` object directly to other tools. -These tools should be usable without `loadEnvironment()`. -It is always the responsibility of an outer function to pass plain configuration to an inner dependency. - -Use the `Configuration` object only when moving between logic layers: - -**Bad**: passing the `Configuration` object to library methods - -```js -await PWADevServer.configure({ - publicPath: config.output.publicPath, - graphqlPlayground: true, - projectConfig: loadEnvironment(__dirname) -}, config); -``` - -The same principle holds when creating your own utilities. - -**Bad**: expecting a `Configuration` object in a library function - -```js -class MyWebpackPlugin { - constructor(config) { - this.options = config.section('myWebpackPlugin'); - } -} -``` - -**Good**: passing plain objects created by the Configuration object - -```js -const projectConfig = loadEnvironment(__dirname); -await PWADevServer.configure({ - publicPath: config.output.publicPath, - graphqlPlayground: true, - ...projectConfig.sections( - 'devServer', - 'imageService', - 'customOrigin' - ), - ...projectConfig.section('magento') -}, config); -``` - -### Naming convention - -POSIX standard environment variables may not be case sensitive and may not allow very many special characters. - -The best policy is to use `ALL_CAPS_UNDERSCORE_DELIMITED_ALPHANUMERIC_VARIABLE_NAMES` when defining environment variables directly. -**Buildpack will ignore any environment variables which do not follow this convention.** - -Buildpack converts between this strict all-caps format (also known as **SCREAMING_SNAKE_CASE**) and a more convenient JavaScript object which can be nested at any level of delimiter. -When defining new environment variables, make their names long and safely namespace them with prefixes as long as necessary. -`Configuration` objects have `.section()` and `.sections()` methods to create targeted, small JavaScript objects with shorter names. - -### Fallback - -By default, buildpack respects three levels of "fallback" values: - -1. Currently declared environment variables, which can be populated on process startup -2. Values from the `.env` file in the project root -3. Defaults from the metadata in the [Project Environment Definitions][] - -Additional layers of configuration and on-disk fallback are discouraged. -Inside scripts, environment variables may be combined and merged, but -too much fall-through of project configuration can result in unpredictable and hard-to-maintain runtime configuration. - -### Project environment definitions - -All the environment variables expected and/or used by buildpack are defined in [`packages/pwa-buildpack/envVarDefinitions.json`][]. - -This file is used for: - -- Creating a self-documenting `.env` file -- Validating environments -- Deprecating and supporting older settings which have changed - -If you are contributing to the PWA Studio project and want to add new functionality that should be configured via the environment or change any environment configuration, follow these best practices: - -- Define any new variables in the `packages/pwa-buildpack/envVarDefinitions.json` file. - The variable definition object follows the API of [envalid][], with the addition of a `type` property indicating the `envalid` method to use. -- Organize variables into named sections in the `sections` list. -- Use the namespacing practices encouraged by [camelspace][] and `loadEnvironment()`. - - For example, a new utility `goodStuff()` might demand environment variables starting with `GOOD_STUFF_`, - and `packages/pwa-buildpack/envVarDefinitions.json` might include a new section in its `sections` list. -- After making any changes to `packages/pwa-buildpack/envVarDefinitions.json`, record them in the `changes` list in that file. - - - Change entries are objects which include: - - `type`: **Required.** The type of the change, either `removed` or `renamed`. No other types of change need change entries. - - `name`: **Required.** The affected environment variable name. - - `dateChanged`: **Required.** The date the change entry was added, in a format parseable by the JavaScript `Date` constructor. - - `warnForDays`: **Optional**, default `180`. A number of days that the warning should keep logging on every run, counting from the `dateChanged`. The default _and_ maximum is 180 days, so use this property only if you want the change to log for a _shorter_ time than default. This prevents an old, out-of-date warning message from cluttering logs long after the user no longer needs to see it. - - `removed` entries should include a human-readable `reason`. - **After removing a variable definition, leave the `removed` entry permanently** to log an error if the old variable is found, encouraging out-of-date installations to upgrade. - - `renamed` entries should include the old name as `name`, and the new name as `updated`. - They must also include a `supportLegacy` boolean. - If this is `true`, then `loadEnvironment()` will continue to support the old value while logging a warning, until either the new variable name has a value, or the change entry expires. - -[`buildpack` cli]: {%link pwa-buildpack/reference/buildpack-cli/index.md %} -[`loadenvironment()`]: {%link pwa-buildpack/reference/buildpack-cli/load-env/index.md %} -[project environment definitions]: {%link pwa-buildpack/reference/environment-variables/core-definitions/index.md %} - -[`.env` file]: https://www.npmjs.com/package/dotenv -[dotenv]: https://www.npmjs.com/package/dotenv -[twelve-factor app]: https://12factor.net/config -[envalid]: https://npmjs.com/package/envalid -[camelspace]: https://npmjs.com/package/camelspace -[`packages/pwa-buildpack/envvardefinitions.json`]: https://github.com/magento/pwa-studio/blob/develop/packages/pwa-buildpack/envVarDefinitions.json diff --git a/pwa-devdocs/src/pwa-buildpack/index.md b/pwa-devdocs/src/pwa-buildpack/index.md deleted file mode 100644 index 28c6578d9e..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/index.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: PWA Buildpack ---- - -PWA Buildpack is a build and development tool and library for Magento Progressive Web Apps. -Use the PWA Buildpack project to set up and configure your local environment for PWA development. - -## Setup - -Follow the [Project setup tutorial] to set up a PWA development environment. - -If you are having trouble setting up your environment, see the [Troubleshooting page]. - -## Contribute - -Visit the [`pwa-buildpack`] package in the PWA Studio repository to contribute to this project. - -[`pwa-buildpack`]: https://github.com/magento/pwa-studio/tree/master/packages/pwa-buildpack -[Project setup tutorial]: {% link pwa-buildpack/project-setup/index.md %} -[Troubleshooting page]: {% link pwa-buildpack/troubleshooting/index.md %} \ No newline at end of file diff --git a/pwa-devdocs/src/pwa-buildpack/project-setup/index.md b/pwa-devdocs/src/pwa-buildpack/project-setup/index.md deleted file mode 100644 index 66ceb585b4..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/project-setup/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Project setup ---- - -## Documentation unpublished - -Sorry! -We have unpublished this topic because the content was out of date with the current state of the project. - -Please use the instructions under [Venia storefront setup][] as a starting point for working with the PWA Studio tools. - -[Venia storefront setup]: {%link venia-pwa-concept/setup/index.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-custom-origin/index.md b/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-custom-origin/index.md deleted file mode 100644 index 89d9748b8b..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-custom-origin/index.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: create-custom-origin ---- - -The `create-custom-origin` is a [`buildpack`][] CLI subcommand which creates a unique local hostname and trusted SSL certificate for your project. - -Usage example with `npx`: - -```sh -npx @magento/pwa-buildpack create-custom-origin -``` - -This feature requires administrative access, so -it may prompt you for an administrative password at the command line. -It does not permanently elevate permissions for the dev process, but -instead, it launches a privileged subprocess to execute one command. - -{: .bs-callout .bs-callout-info} -**Note:** -This command should be used only in a development environment and never as part of a production deployment process. - -## Why PWA development requires a secure custom origin - -### HTTPS is required - -Some PWA features, such as ServiceWorkers and Push Notifications, are only available on HTTPS secure domains. -Some browsers make exceptions for the domain `localhost`, but this is non-standard. - -HTTPS development is becoming the norm, but -creating a self-signed certificate and configuring your server and browser to support this is a complex process. - -The `create-custom-origin` command automates this process reliably on most operating systems. -It uses [devcert][] to edit your local hostfile, create and manage certificates, and try to configure web browsers to "trust" the certificate. -This prevents security errors from showing up in browsers. - -In the future, browsers will require trust, as well as SSL itself, to enable some features. - -{: .bs-callout .bs-callout-info} -**Note:** -PWADevServer uses OpenSSL to generate these certificates; your operating system must have an `openssl` command of version 1.0 or above to use this feature. - -### Unique domains prevent ServiceWorker collisions - -PWA features, such as ServiceWorkers, use the concept of a 'scope' to separate installed ServiceWorkers from each other. -A scope is a combination of a domain name, port, and path. -If you use `localhost` for developing multiple PWAs, you run the risk of Service Workers overriding or colliding with each other. - -## Customization - -Use environment variables in the `CUSTOM_ORIGIN_` namespace to change the behavior of the `create-custom-origin` command. - -| Environment Variable Name | Default Value | Description | -| --- | --- | --- | -| `CUSTOM_ORIGIN_ENABLED` | `true` | Enable the custom origin feature | -| `CUSTOM_ORIGIN_ADD_UNIQUE_HASH` | `true` | Add a unique hash string to the custom origin. | -| `CUSTOM_ORIGIN_SUBDOMAIN` | | Allows you to manually specify the subdomain prefix of the custom origin instead of using the package name. | -| `CUSTOM_ORIGIN_EXACT_DOMAIN` | | Allows you to specify the _exact_ domain of the custom origin instead of a subdomain under `.local.pwadev`. | - -Set these variables permanently in your `.env` file, or argue them at the command line for overrides: - -```sh -CUSTOM_ORIGIN_EXACT_DOMAIN="my.pwa" \ -npx @magento/pwa-buildpack create-custom-origin . -``` - -### Unique hash - -If `CUSTOM_ORIGIN_ADD_UNIQUE_HASH` is set to `true`, the `create-custom-origin` command adds a unique hash string to the custom origin. -This string is based on the filesystem location. - -This naturally separates domains when running multiple project folders on one developer machine. - -[`buildpack`]: {%link pwa-buildpack/reference/buildpack-cli/index.md %} - -[devcert]: https://github.com/davewasmer/devcert diff --git a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-env-file/index.md b/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-env-file/index.md deleted file mode 100644 index de4a4cf411..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-env-file/index.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: create-env-file ---- - -Whether its a new storefront project or a fresh PWA Studio repository clone, PWA Studio requires a `.env` file to set up the environment for your site. - -The `create-env-file` subcommand for the [`buildpack`][] CLI command automatically creates this file using pre-defined environment variables and default values. - -Usage example with `npx`: - -```sh -npx @magento/pwa-buildpack create-env-file -``` - -This command generates a `.env` file in the specified directory. - -The `.env` file follows the `dotenv` file format and includes documentation comments for the environment variable declarations. -The `create-env-file` command uses the [`envVarDefinitions.json`][] file in the PWA Studio source code to create this file. - -## Command flags - -| Name | Description | -| ---------------- | -------------------------------------------------------------------- | -| `--use-examples` | Use `example` values for all variables in the generated `.env` file. | - -## Defining variables for the `.env` file - -Use any of the following methods to define the generated variables in the `.env` file: - -- Set one or more variables defined in the [`envVarDefinitions.json`][] file before running `create-env-file` to override the `default` values written to the `.env` file. - These values can be set using shell scripting or other OS-specific methods. -- Call `create-env-file` with the `--use-examples` flag to use the `example` values for variables declared in the `envVarDefinitions.json` file. - Calling the `create-env-file` command without this flag still writes the `example` values to the `.env` file, but - the entry is commented out. - -Variables with no environment definitions nor `example` values in the `envVarDefinitions.json` file are declared in the `.env` file with an empty value. - -Example: - -```text -MAGENTO_BACKEND_URL= -``` - -## Programmatic API - -Adding the `@magento/pwa-buildpack` dependency to your project gives you access to the programmatic API for creating the `.env` file. - -### `createDotEnvFile(directory, options)` - -Uses the current environment variables and [`envVarDefinitions.json`][] file to generate the contents of a `.env` file. - -#### Example - -```js -const { createDotEnvFile } = require('@magento/pwa-buildpack'); - -const fileContents = createDotEnvFile(process.cwd()); -``` - -#### Parameters - -| Parameter | Data type | Description | -| --------------------- | -------------------------------------------- | ---------------------------------------------------------- | -| `dirOrEnv` | `string` path or a `process.env`-like object | Provides the path to the project root. | -| `options` | `object` | An object containing additional options. | -| `options.logger` | `object` | The object to use for logging. | -| `options.useExamples` | `boolean` | Whether to populate the `.env` file with `example` values. | - -If `dirOrEnv` is a string and the specified directory contains a `.env` file, it is read before being overwritten to preserve existing variables. - -If `dirOrEnv` is a `process.env`-like object, the `.env` file is not parsed before being overwritten. - -#### Return value - -The return value is the string value of a `.env` file. - -Parse this value using the `dotenv` API or write it out to the filesystem. - -[`buildpack`]: {%link pwa-buildpack/reference/buildpack-cli/index.md %} - -[`envvardefinitions.json`]: https://github.com/magento/pwa-studio/blob/develop/packages/pwa-buildpack/envVarDefinitions.json diff --git a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-project/index.md b/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-project/index.md deleted file mode 100644 index cc1741b3be..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/create-project/index.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: create-project ---- - -The `create-project` sub-command of the [`pwa-buildpack`][] CLI is a [scaffolding][] tool used to create a fresh PWA Studio app in a new project directory. - -Normally this command is used indirectly through the `@magento/pwa` scaffolding tool. -The tool collects the parameter values through its interactive prompt and passes them on to the command as options. - -This tool is also available for developers or third-party automation tools to use directly. - -**Example:** Using the command with `npx`: - -```sh -npx @magento/pwa-buildpack create-project ./new-pwa \ - --name @magezilla/new-pwa \ - --template venia-concept \ - --backend-url https://local.magento \ - --author MageZilla -``` - -This example creates a new project in the `./new-pwa` folder. -The package metadata for the project lists the project name as `@magezill/new-pwa` and the author as `MageZilla`. -It also creates a `.env` file with the backend URL set to `https://local.magento`. - -After creating the project, it installs the package dependencies, including the Venia, Peregrine and Buildpack libraries needed to build the application. - -## Running the command - -Use the `npx` tool to download the current version and execute the command: - -```sh -npx @magento/pwa-buildpack create-project [ ...] -``` - -The first argument in the command is the directory for the new project. -If the directory does not exist, it is created. -If the directory is not empty, files that the tool generates overwrite the existing files. - -The directory can be the current directory `.`, which is the default if no first argument is passed. - -{: .bs-callout .bs-callout-warning} -Do not install buildpack globally on your development system to use this command. -This can cause incompatible versions between a product version and the global version. - -### Command options - -Run `npx @magento/pwa-buildpack create-project --help` to see the list of command options. - -You can specify these options in any order after `buildpack create-project `. - -| Name | Description | -| --------------- | -------------------------------------------------------------------------------------------------------------------------- | -| `--template` | NPM package or directory name of the template to use for the new project. **Currently only `venia-concept` is supported.** | -| `--backend-url` | URL value, set in the `.env` file, of the backing Magento instance to use in developer mode. | -| `--name` | Name for the `package.json` `"name"` field. Must be a legal NPM package name. Defaults to directory name. | -| `--author` | Text for the `package.json` `"author"` field. Usually a name followed by an email address in angle brackets. | -| `--install` | Whether to install dependencies after project creation. Defaults to `true`. | -| `--npm-client` | NPM client used to manage this repository. Both `npm` (the default) and `yarn` are supported. | - -{: .bs-callout .bs-callout-warning} -**Note:** -Do not use this command as part of a production deployment process. -Use it only in a development environment. - -[`pwa-buildpack`]: {%link pwa-buildpack/reference/buildpack-cli/index.md %} -[scaffolding]: {%link pwa-buildpack/scaffolding/index.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/index.md b/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/index.md deleted file mode 100644 index 30eaf469d3..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/index.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: buildpack Command Line Interface ---- - -The `buildpack` command is a command line toolkit with subcommands. - -Running it with no arguments produces the following output: - -```text -buildpack - -Commands: - buildpack create-custom-origin Get or create a secure, unique - hostname/port combination and a - trusted SSL certificate for local - development, which enables all PWA - features. - buildpack create-env-file Generate a .env file in the provided - directory to store project - configuration as environment variables - variables - buildpack load-env Load and validate the current - environment, including .env file if - present, to ensure all required - configuration is in place. - -Options: - --version Show version number [boolean] - --help Show help [boolean] - -Invoke buildpack with a subcommand (eg. `buildpack create-env-file`) and the arguments to that subcommand. -``` - -## Running the `buildpack` command - -### As a project dependency - -A project with the `@magento/pwa-buildpack` dependency installed can use the `buildpack` command in its NPM scripts: - -```json -"scripts": { - "load-env": "buildpack load-env ." -} -``` - -With this example, you can run `npm run-script load-env` or `yarn run load-env` to use the local copy of the `buildpack` CLI. - -### Using `npx` - -Invoke `buildpack` directly using NPM's `npx` tool, which installs packages and runs their CLIs in a single command: - -```sh -npx @magento/pwa-buildpack -``` - -{: .bs-callout .bs-callout-warning} -It is not recommended to globally install buildpack with `yarn global add` or `npm install --global`. -Individual projects should use their own versions, to guarantee expected behavior. - -## Available subcommands - -The `buildpack` CLI provides the following subcommands: - -- [`create-custom-origin`][] - Gets or creates a trusted SSL certificate for local PWA development. -- [`create-env-file`][] - Generates a new `.env` file in the current directory. -- [`load-env`][] - Loads and validates the current environment. - -[`create-custom-origin`]: {%link pwa-buildpack/reference/buildpack-cli/create-custom-origin/index.md %} -[`create-env-file`]: {%link pwa-buildpack/reference/buildpack-cli/create-env-file/index.md %} -[`load-env`]: {%link pwa-buildpack/reference/buildpack-cli/load-env/index.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/load-env/index.md b/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/load-env/index.md deleted file mode 100644 index 6e0ad5b889..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/buildpack-cli/load-env/index.md +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: load-env ---- - -The `load-env` subcommand for the [`buildpack`][] CLI command loads and validates the local `.env` file according to the variable declarations in the [`envVarDefinitions.json`][] file. -This includes any deprecated or changed settings. - -When loading from `.env`, `buildpack` does not override previously declared variables. - -## Command flags - -| Name | Description | -| ----------------- | ----------------------------------------------------------------------------------------- | -| `--core-dev-mode` | Used only by the core PWA Studio repository for quick setups of the core dev environment. | - -The `--core-dev-mode` flag tells `buildpack` to run `buildpack create-env-file --use-examples` if an existing `.env` file does not exist in the given directory path. - -## Usage tips - -- Use the `load-env` command in NPM scripts instead of directly invoking it with `npx` -- Use a command, shell script, or spawned subprocess to override individual environment variables at start time. -- The command does not require a `.env` file to be present. - - If a `.env` file is not present, the environment is still valid if another process or command sets the required variables. - If the file is not present and the variable `NODE_ENV` is not set to `production`, `buildpack` logs a warning. - -## Programmatic API - -Adding the `@magento/pwa-buildpack` dependency to your project gives you access to the programmatic API for loading the `.env` file. - -### `loadEnvironment(dirOrEnv, [logger])` - -Loads a given directory's `.env` file and provides a [configuration object][]. - -#### Example - -```js -const { loadEnvironment } = require('@magento/pwa-buildpack'); - -const configuration = loadEnvironment(process.cwd()); -``` - -#### Parameters - -| Name | Data type | Description | -| ---------- | ------------------------------------- | ---------------------------------------------------------------- | -| `dirOrEnv` | `string` path or `process.env` object | Provides a path to the project root. | -| `logger` | `object` | An optional logger object to use instead of the default console. | - -If the `dirOrEnv` parameter is a `process.env` object, it will not attempt to parse a `.env` file. - -#### Return value - -The `loadEnvironment()` function returns a configuration object. - -### Configuration object - -Use the configuration object returned by `loadEnvironment()` as a single source of truth for configuration. - -#### Properties - -| Name | Alias | Description | -| --------------- | :------: | ------------------------------ | -| `env` | - | The raw environment object | -| `isProduction` | `isProd` | True if `NODE_ENV=production` | -| `isDevelopment` | `isDev` | True if `NODE_ENV=development` | -| `isTest` | - | True if `NODE_ENV=test` | - -#### Methods - -The configuration object provides methods that return settings in specific namespaces. -This lets you pass smaller objects instead of a single, plain object full of global configuration values. - -`section(sectionName)` -: Returns a plain object with environment variables in the `sectionName` namespace. -The property keys are [camelCased][] for convenience. - -`sections(...sectionNames)` -: Returns a plain object with environment variables from the specified namespaces. -The namespaces are assigned to different camelCased properties named after the section name. - -`all()` -: Returns the entire environment object, camelCased for convenience, with no namespace separations. - -### Full example script - -The following example is a script that starts an [UPWARD][] server using configuration values loaded from the environment and `.env` file in the project path. - -```js -import { loadEnvironment } from '@magento/pwa-buildpack'; - -// Give `loadEnvironment` the path to the project root. -// If the current file is in project root, use the Node builtin `__dirname`. -const configuration = loadEnvironment('/Users/me/path/to/project'); - -// `loadEnvironment` has now read the contents of -// `/Users/me/path/to/project/.env` and merged it with any environment -// variables that were alredy set. - -// Create an UPWARD server using env vars that begin with `UPWARD_JS_` -createUpwardServer(configuration.section('upwardJs')); - -// If these environment variables are set: -// -// UPWARD_JS_HOST=https://local.upward/ -// UPWARD_JS_PORT=8081 -// -// then `configuration.section('upwardJs')` produces this object: -// -// { -// host: 'https://local.upward', -// port: '8081' -// } -// -// No other environment variables are included in this object unless they begin -// with `UPWARD_JS_` which is the equivalent of `upwardJs` camel-cased. - - -// The .all() method turns the whole environment into an object, with all -// CONSTANT_CASE names turned into camelCase names. -const allConfig = configuration.all(); - -// This object will have one property for each set environment variable, -// including the UPWARD variables named above. -// But `configuration.all()` does not namespace them, they have longer names: -// -// { -// upwardJsHost: 'https://local.upward', -// upwardJsPort: '8081' -// } -// -// This huge object defeats the purpose of loadEnvironment() and should -// only be used for debugging. - -// Instead, let's create an UPWARD server combining two environment variable -// sections with hardcoded overrides to some values. -createUpwardServer({ - ...configuration.section('upwardJs'), - ...configuration.section('magento'), - bindLocal: true -}); - -// This uses JavaScript object spreading to combine several sections of -// configuration and override a value. -// If the environment contains these values: -// -// UPWARD_JS_HOST=https://local.pwadev -// UPWARD_JS_PORT=443 -// UPWARD_JS_BIND_LOCAL= -// MAGENTO_BACKEND_URL=https://local.magento -// -// Then the above code passes the following object to `createUpwardServer`: -// -// { -// host: 'https://local.pwadev', -// port: '443', -// backendUrl: 'https://local.magento', -// bindLocal: true -// } - - -// The `sections()` method can split an env object into named subsections: -createUpwardServer(configuration.sections('upwardJs', 'magento')); - -// Given the same environment variables as above, this code will pass the -// following to `createUpwardServer`: -// -// { -// upwardJs: { -// host: 'https://local.pwadev', -// port: '443', -// bindLocal: '' // the null string is used as a falsy value -// }, -// magento: { -// backendUrl: 'https://local.magento' -// } -// } -// -// (The above is not the actual config object format for `createUpwardServer`, -// but if it was, that's how you'd make it.) - -// Use the convenience properties `isProd` and `isDev` instead of testing -// `process.env.NODE_ENV` directly: -if (configuration.isDev) { - console.log('Development mode'); -} -``` - -[upward]: {%link technologies/upward/reference-implementation/index.md %} -[`buildpack`]: {%link pwa-buildpack/reference/buildpack-cli/index.md %} -[configuration object]: {%link pwa-buildpack/configuration-management/index.md %} - -[`envvardefinitions.json`]: https://github.com/magento/pwa-studio/blob/develop/packages/pwa-buildpack/envVarDefinitions.json -[camelcased]: https://npmjs.com/package/camelspace diff --git a/pwa-devdocs/src/pwa-buildpack/reference/configure-webpack/index.md b/pwa-devdocs/src/pwa-buildpack/reference/configure-webpack/index.md deleted file mode 100644 index 0badf28d3e..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/configure-webpack/index.md +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: configureWebpack ---- - -## `configureWebpack(options)` - -A function that returns a Webpack configuration object. - -Import and call `configureWebpack()` in your project's `webpack.config.js` file to generate a Webpack configuration object suited to your PWA Studio project and its dependencies. - -**Returns:** -A [Promise][] that resolves to a configuration object for webpack. - -The generated configuration object tells Webpack how to process the project's source code and generate bundles. -It is a [complete Webpack configuration object][] that is ready for immediate use. - -You can also modify it in your `webpack.config.js` before returning it out of your own configure function. - -{: .bs-callout .bs-callout-info} -`configureWebpack()` is asynchronous. -Webpack accepts a Promise for a configuration, so -you can return the result of `configureWebpack` directly out of the exported function in `webpack.config.js`. -If you want to modify the configuration, you must use `await`. - -### Parameters - -| Name | Type | Description | -| ----------------- | ---------- | ------------------------------------------------------------------------ | -| `options` | `Object` | Options for generating the configuration object | -| `options.context` | `String` | _Required._ The path of the project root directory | -| `options.vendor` | `String[]` | A list of module names to force Webpack to include in a "commons" bundle | -| `options.special` | `Object` | An object that maps module names to a set of configuration. | - -{: .bs-callout .bs-callout-info} -To make your project performant, limit the `options.vendor` list to strictly necessary dependencies required by most or all modules. - -### Special flags - -The `options.special` parameter tells `configureWebpack()` to create special configurations for specific modules. - -By default, Webpack treats the source code of your project very differently than the dependency code. -Webpack does so because public NPM modules are not reliably compatible with advanced JavaScript features. -Developers get around this by customizing the Webpack configuration rules. - -`configureWebpack()` offers a simple API: for each module you want to treat special, add these named flags. -It will adjust Webpack configuration to run that module and its files through additional build steps. - -#### `esModules` flag - -If `true`, `configureWebpack()` generates the configuration for processing `.js` files from the named module as ES Modules. -This allows Webpack to use advanced optimizations on them, but -it may fail if the module contains noncompliant code. - -#### `cssModules` flag - -If `true`, `configureWebpack()` generates the configuration for processing `.css` files from the named module as CSS Modules. -This allows Webpack to maintain a separate namespace for every CSS Module, including modules inside dependencies. - -This prevents style collisions between sibling modules, but -it may fail if the module does not actually use CSS Module patterns. - -#### `graphqlQueries` flag - -If `true`, `configureWebpack()` generates the configuration that tells webpack to look for `.graphql` files in the dependency and precompile them for better performance. - -All GraphQL query files in all modules will appear in the GraphQL playground, but -this setting allows you to choose which dependencies have queries you want to debug. - -#### `rootComponents` flag - -If `true`, `configureWebpack()` generates the configuration that tells webpack to look for RootComponent files in a module's `src/RootComponents` or `RootComponents` subdirectories. - -This allows a third-party dependency to provide RootComponents to your app automatically, but -it may slow down the build if you add too many modules that do not have RootComponents. - -#### `upward` flag - -If `true`, `configureWebpack()` generates the configuration that tells weback to look for an `upward.yml` file in a module's root directory and merge it with the project's root `upward.yml` file. - -This lets third-party dependencies contribute to UPWARD behavior, but -it may cause collisions or merge problems if the UPWARD files contradict each other. - -## Example - -The following example is taken from `packages/venia-concept/webpack.config.js`. -It represents a typical setup using `configureWebpack` to generate Webpack config. -It also demonstrates that `configureWebpack` returns a recognizable Webpack object, which you can modify. - -```js -const { configureWebpack } = require('@magento/pwa-buildpack'); - -module.exports = async env => { - const config = await configureWebpack({ - context: __dirname, - vendor: [ - '@apollo/react-hooks', - 'apollo-cache-inmemory', - 'apollo-cache-persist', - 'apollo-client', - 'apollo-link-context', - 'apollo-link-http', - 'informed', - 'react', - 'react-dom', - 'react-feather', - 'react-redux', - 'react-router-dom', - 'redux', - 'redux-actions', - 'redux-thunk' - ], - special: { - // Treat code originating in the `@magento/peregrine` module - // as ES Modules, just like the project source itself. - '@magento/peregrine': { - esModules: true - } - // Treat code originating in the `@magento/venia-ui` as though - // it uses ES Modules, CSS Modules, GraphQL queries, RootComponents, - // and UPWARD definitions. This is the right set of flags for a UI - // library that makes up the bulk of your project. - '@magento/venia-ui': { - cssModules: true, - esModules: true, - graphqlQueries: true, - rootComponents: true, - upward: true - } - }, - env - }); - - // configureWebpack() returns a regular Webpack configuration object. - // You can customize the build by mutating the object here, as in - // this example: - config.module.noParse = [/braintree\-web\-drop\-in/]; - // Since it's a regular Webpack configuration, the object supports the - // `module.noParse` option in Webpack, documented here: - // https://webpack.js.org/configuration/module/#modulenoparse - - return config; -}; -``` - -[complete webpack configuration object]: https://webpack.js.org/configuration/ -[promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise diff --git a/pwa-devdocs/src/pwa-buildpack/reference/environment-variables/core-definitions/index.md b/pwa-devdocs/src/pwa-buildpack/reference/environment-variables/core-definitions/index.md deleted file mode 100644 index 47d1add86d..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/environment-variables/core-definitions/index.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Core environment variable definitions ---- - -Environment variable definitions are used for validation and documentation of the [configuration management system][] of PWA Studio. - -Build scripts normally use the [values set in the current environment][], but it is sometimes necessary to use the definitions themselves, such as when an extension defines its own global config variables. - -There are two ways to access the environment variable definitions object: - -- Third-party code should use the builtin target [`envVarDefinitions`][] when adding definitions. -- Core Buildpack code uses [`getEnvVarDefinitions()`][], which builds environment variable definitions for the project. - It starts with core variables listed below and then calls the `envVarDefinitions` target so installed extensions can add their own variables. - - - -{% include auto-generated/buildpack/reference/envVarDefinitions.md %} - -[configuration management system]: {%link pwa-buildpack/configuration-management/index.md %} -[`envvardefinitions`]: {%link pwa-buildpack/reference/targets/index.md %}#module_BuiltinTargets.envVarDefinitions -[core variables]: {%link pwa-buildpack/reference/environment-variables/core-definitions/index.md %} -[values set in the current environment]: {%link pwa-buildpack/reference/buildpack-cli/load-env/index.md %}#loadenvironmentdirorenv-logge - -[`getenvvardefinitions()`]: https://github.com/magento/pwa-studio/blob/develop/packages/pwa-buildpack/lib/Utilities/getEnvVarDefinitions.js diff --git a/pwa-devdocs/src/pwa-buildpack/reference/environment-variables/definitions-api/index.md b/pwa-devdocs/src/pwa-buildpack/reference/environment-variables/definitions-api/index.md deleted file mode 100644 index c0a2bda81a..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/environment-variables/definitions-api/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Environment variable definition API ---- - - - -{% include auto-generated/pwa-buildpack/lib/Utilities/getEnvVarDefinitions.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/index.md b/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/index.md deleted file mode 100644 index 0b0d698589..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: BuildBus ---- - - - -{% include auto-generated/pwa-buildpack/lib/BuildBus/BuildBus.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/target/index.md b/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/target/index.md deleted file mode 100644 index ae781f66ac..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/target/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Target ---- - - - -{% include auto-generated/pwa-buildpack/lib/BuildBus/Target.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/targetprovider/index.md b/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/targetprovider/index.md deleted file mode 100644 index 3bca7f0d26..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/extension-framework/targetprovider/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: TargetProvider ---- - - - -{% include auto-generated/pwa-buildpack/lib/BuildBus/TargetProvider.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/magento-resolver/index.md b/pwa-devdocs/src/pwa-buildpack/reference/magento-resolver/index.md deleted file mode 100644 index 1fd62b8e0d..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/magento-resolver/index.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: MagentoResolver ---- - -An adapter that configures Webpack to resolve assets using Magento PWA conventions. - -This module generates a configuration object used in the [`resolve`] property of a Webpack config. -The configuration object tells Webpack how to traverse the filesystem structure for assets required in source files. - -Currently, MagentoResolver does very little, but it's likely that the Magento development environment will require custom resolution rules in the future; this utility sets the precedent of the API for delivering those rules. - -## API - -### `configure(options)` - -**Parameters:** - -* `options:` - Configuration object that describes where the PWA storefront folders are located. Must have a `root` property set to the context (root directory) of the project. - -**Return:** - -A [Promise] configuration type for webpack. - -{: .bs-callout .bs-callout-info} -**Note:** -`MagentoResolver.configure()` is asynchronous. - -## Example - -In `webpack.config.js`: - -``` js -const buildpack = require('@magento/pwa-buildpack'); -const MagentoResolver = buildpack.Webpack.MagentoResolver; - -module.exports = async env => { - const config { - /* webpack entry, output, rules, etc */ - - - resolve: await MagentoResolver.configure({ - paths: { - root: __dirname - } - }) - - }; - - return config; -} -``` - - - -{: .bs-callout .bs-callout-tip} -The special `__dirname` variable in Node always refers to the directory containing the currently executing script file. -This is different from the "working directory", which is the current directory of the shell when the current process was started. - -{: .bs-callout .bs-callout-info} -**Note:** -The example provided uses the newer, cleaner `async/await` syntax instead of using Promises directly. - - -[`resolve`]: https://webpack.js.org/configuration/resolve/ -[Promise]: https://webpack.js.org/configuration/configuration-types/#exporting-a-promise diff --git a/pwa-devdocs/src/pwa-buildpack/reference/pwa-dev-server/index.md b/pwa-devdocs/src/pwa-buildpack/reference/pwa-dev-server/index.md deleted file mode 100644 index 44c81717e1..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/pwa-dev-server/index.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: PWADevServer ---- - -A utility for configuring a development OS and a `webpack-dev-server` for PWA development. - -A typical webpack local development environment uses the [`devServer`][] settings in `webpack.config.js` to create a temporary, local HTTP server to show edits in real time. - -## Basic Features - -PWADevServer adds an optimized PWA development server to a Webpack configuration object. - -The dev server provides the following useful features: - -### Hot reload - -The hot reload feature refreshes the page or a relevant subsection of the page whenever you save a change that affects it. -It uses Webpack's [Hot Module Replacement](https://webpack.js.org/concepts/hot-module-replacement/) feature to replace components and stylesheets inline. - -### Proxy server - -The dev server acts as a proxy server for API and media requests to Magento. -It is configured using environment variables. - -The `MAGENTO_BACKEND_URL` environment variable configures the proxy server to accept GraphQL, REST, and media requests and passes them to Magento. - -The proxy server also transforms host and referral headers to make them compatible with Magento settings. - -### Root level ServiceWorker - -The dev server serves a JavaScript file at the root path that registers a ServiceWorker scoped to the whole website. -It can also disable that ServiceWorker when caching would interfere with realtime changes. - -### Verbose debugging - -The dev server adds verbose debugging information to error pages to help with development. - -## Optional Features - -The following dev server features are optional and are available on the initial run and confirmed on subsequent runs. -They are configured in the `.env` file. - -### Custom hostname - -The custom hostname feature uses a local hostname for the current project. -This hostname must be created for the current project by running `buildpack create-custom-origin .`. - -### GraphQL Playground IDE - -The dev server provides a [GraphQL Playground IDE][GraphQL Playground feature] to debug the GraphQL queries in the project. - -### SSL certificate configuration - -The dev server creates and cache a 'self-signed' SSL certificate that allow the use of HTTPS-only features during development. - -{: .bs-callout .bs-callout-info} -**Note:** -Updating the OS security settings to trust the self-signed certificate requires elevated permissions, so -you may be prompted for a password during the setup process. - -### Content transformation - -The content transformation feature masks the Magento 2 domain name in all HTML -attributes, replacing it with the development server domain name. - -## GraphQL Playground feature - -[GraphQL Playground][] is an enhanced version of the in-browser GraphQL debugging tool GraphiQL. - -Enable this feature by setting the `PWADevServerOptions.graphqlPlayground` configuration option to `true`. - -Browse to the `/graphiql` path on your PWADevServer to use this feature. - -[create SSL certificate]: #creating-an-ssl-certificate -[secure and unique hostname for the dev server]: #creating-a-secure-and-unique-hostname -[`devServer`]: https://webpack.js.org/configuration/dev-server/ -[Promise]: https://webpack.js.org/configuration/configuration-types/#exporting-a-promise -[`SecureHostOptions`]: #securehostoptions -[`subdomain: string`]: #subdomain -[`exactDomain: string`]: #exactdomain -[GraphQL Playground feature]: #graphql-playground-feature -[GraphQL Playground]: https://github.com/prisma/graphql-playground diff --git a/pwa-devdocs/src/pwa-buildpack/reference/root-components-plugin/index.md b/pwa-devdocs/src/pwa-buildpack/reference/root-components-plugin/index.md deleted file mode 100644 index ebc966af73..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/root-components-plugin/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: MagentoRootComponentsPlugin ---- - -This plugin creates [unique chunks] for each Root Component in a Magento PWA project and extension. - -For example, given a `RootComponents` directory in a PWA project with the following structure: - -``` sh -├── Page1 -│ └── index.js -├── Page2 -│ └── index.js -└── Page3 - └── index.js -``` - -The plugin creates unique chunks for `Page1`, `Page2`, and `Page3`. -Further webpack optimization techniques, such as [`CommonsChunkPlugin`], can be applied as usual. - -## Example usage - -``` javascript -// webpack.config.js - -const path = require('path'); -const { MagentoRootComponentsPlugin } = require('@magento/pwa-buildpack'); - -module.exports = { - entry: { - main: path.join(__dirname, 'src') - }, - output: { - path: path.join(__dirname, 'dist'), - filename: '[name].js', - chunkFilename: '[name].chunk.js' - }, - plugins: [ - new MagentoRootComponentsPlugin({ - rootComponentsDirs: [path.join(__dirname, 'src/RootComponents')], // optional - manifestFileName: 'roots-manifest.json' // optional - }) - ] -}; -``` - -[unique chunks]: https://webpack.js.org/guides/code-splitting/ -[`CommonsChunkPlugin`]: https://webpack.js.org/plugins/commons-chunk-plugin/ diff --git a/pwa-devdocs/src/pwa-buildpack/reference/serviceworker-plugin/index.md b/pwa-devdocs/src/pwa-buildpack/reference/serviceworker-plugin/index.md deleted file mode 100644 index ab4986a6a7..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/serviceworker-plugin/index.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: ServiceWorkerPlugin ---- - -A webpack plugin for configuring a ServiceWorker for different PWA development scenarios. - -This plugin is a wrapper around the [Google Workbox Webpack Plugin]. -It generates a caching ServiceWorker based on assets emitted by webpack. - -The following configurations are available for this plugin: - -* **normal development** - the ServiceWorker is disabled -* **service worker debugging** - the ServiceWorker and hot-reloading are enabled. - -## API - -### `ServiceWorker(options)` - -Plugin constructor for the `ServiceWorkerPlugin` class. - -#### Parameters - -* **`options: PluginOptions`** - Configuration object for the ServiceWorkerPlugin - -The `PluginOptions` object contains the following properties: - -| Property: Type | Description | -| --------------------------------------- | ---------------------------------------------------------------------------------- | -| `env:`[`EnvironmentObject`] | **Required.** An object that represents the current environment. | -| `paths: object` | **Required.** Map of important project locations. Must at least contain a `root` property set to the context (root directory) of the project. | -| `enableServiceWorkerDebugging: boolean` | Toggles [service worker debugging]. | -| `serviceWorkerFilename: string` | **Required.** The name of the ServiceWorker file this project creates. | -| `runtimeCacheAssetPath: string` | A remote URL or root path to assets the ServiceWorker should cache during runtime. | -{:style="table-layout:auto"} - -The `EnvironmentObject` contains the following properties: -{:#environmentobject} - -| Property: Type | Description | -| --------------- | ------------------------------------------ | -| `mode: string` | Must be **development** or **production**. | -{:style="table-layout:auto"} - -## Example - -In `webpack.config.js`: - -``` js -const path = require('path'); -const buildpack = require('@magento/pwa-buildpack'); -const ServiceWorkerPlugin = buildpack.Webpack.ServiceWorkerPlugin; - -module.exports = async env => { - const config = { - /* webpack config, i.e. entry, output, etc. */ - plugins: [ - /* other plugins */ - new ServiceWorkerPlugin({ - env: { - mode: 'development' - }, - - paths: { - output: path.resolve(__dirname, 'web') - }, - enableServiceWorkerDebugging: true, - serviceWorkerFileName: 'sw.js', - runtimeCacheAssetPath: 'https://cdn.url' - }) - ] - }; - - return config; - -}; - -``` - -## Service worker debugging - -When `PluginOptions.enableServiceWorkerDebugging` is set to `true`, hot reloading is enabled and the ServiceWorker is active in the document root. - -When this value is set to `false`, the ServiceWorker is disabled to prevent cache interruptions when hot reloading assets. - - -[Google Workbox Webpack Plugin]: https://developers.google.com/web/tools/workbox/guides/generate-service-worker/ -[`EnvironmentObject`]: #environmentobject -[service worker debugging]: #service-worker-debugging diff --git a/pwa-devdocs/src/pwa-buildpack/reference/targets/index.md b/pwa-devdocs/src/pwa-buildpack/reference/targets/index.md deleted file mode 100644 index eb5b2ce59e..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/targets/index.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Built-in Targets ---- - -Buildpack's targets follow the same Target API as other packages' targets, but they play a unique role. Buildpack targets are the fundamental "roots" of the PWA Studio Target system. - -All other Targets operate by intercepting other Targets. -BuildBus runs the declare and intercept phases by itself. -But nothing _calls_ targets to run any interceptors until Buildpack begins the process, by directly invoking one of its _own_ targets. - -The Buildpack targets are therefore very generic and low-level. They are meant to be used as building blocks for higher-level feature targets, such as adding routing or navigation logic. - -Even deeper than Buildpack targets are the very similar Hooks that make up [Webpack's plugin system](https://v4.webpack.js.org/api/plugins/). Interceptors can use Buildpack's `webpackCompiler` target to acquire a reference to the Webpack Compiler object for each build, and can then do anything a Webpack plugin can do. -Because of their similarity in form and function, the PWA Studio Targets system integrates seamlessly into the larger Webpack ecosystem as a commerce-driven superset of its functionality. - - - -{% include auto-generated/pwa-buildpack/lib/BuildBus/declare-base.md %} diff --git a/pwa-devdocs/src/pwa-buildpack/reference/transform-requests/index.md b/pwa-devdocs/src/pwa-buildpack/reference/transform-requests/index.md deleted file mode 100644 index 1f1abe35a7..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/reference/transform-requests/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Transform Requests ---- - -The built-in [`transformModules`][] target is a powerful way to customize the build process for a partiular file or set of files. -Many common Targets are implemented using the `transformModules` target and a custom transformer module. - -Interceptors of this target receive a single function as their first argument. This is the `addTransform` function documented below. - - - -{% include auto-generated/pwa-buildpack/lib/WebpackTools/ModuleTransformConfig.md %} - - -[`transformModules`]: {%link pwa-buildpack/reference/targets/index.md %}#module_BuiltinTargets.transformModules diff --git a/pwa-devdocs/src/pwa-buildpack/scaffolding/custom-project-templates/index.md b/pwa-devdocs/src/pwa-buildpack/scaffolding/custom-project-templates/index.md deleted file mode 100644 index 87ea67adee..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/scaffolding/custom-project-templates/index.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: Custom project templates ---- - -PWA Studio [scaffolding tools][] allow you to specify a template to build a new storefront project. -The default template they use is the `venia-concept` project. - -## Buildpack folder - -The `venia-concept` has a `_buildpack` directory in the project root and a script called `create.js` inside that directory. -The presence of `create.js` within the `_buildpack` directory indicates that this project can be used as a template for the [`buildpack create-project`][] command. - -### The `create.js` file - -The `create.js` file defines a function that returns an object with `ignores`, `before`, `visitor`, and `after` properties. -These properties are functions that provide instructions for the buildpack `create-project` command. - -The function defined in `create.js` is passed in an object with the following properties: - -- `fs` - An instance of the [`fs-extra` library][], which provides utilities for most of the common copy operations. -- `tasks` - An object which provides common handlers that template developers can use for globs. -- `options` - An object that contains the parameters used in the `buildpack create-project` command. - -When the create project command executes, it walks the template project's directory tree and applies the instructions provided by the returned object's properties. - -#### `ignores` - -The `ignores` property is an array of [glob patterns][]. -Files that match these patterns are not processed by the create project command. - -Use this property to prevent the create command from processing project-specific or unimportant files. - -### `before` - -The `before` property defines a function that runs before the command walks the directory tree. -Use this property to add pre-processing logic during project creation. - -### `visitor` - -The `visitor` property is a mapping object that maps a glob pattern to a file handler function. -The glob pattern is the map key, and the file handler function is the value associated with that key. - -When the project creation tool walks the directory tree, it looks for files that match each glob pattern and runs the visitor function associated with that pattern. - -Use this property to perform custom transformation logic on a file before copying it to the new project. - -```js -{ - visitor: { - 'package.json': ({ path, targetPath, options }) => { - const pkg = fs.readJsonSync(path); - pkg.name = options.name; - fs.writeJsonSync(targetPath, JSON.stringify(pkg, null, 4)); - } - } -} -``` - -This is an example of a visitor property that targets the template project's `package.json` file and modifies its name before writing it out to the `targetPath`. - -{: .bs-callout .bs-callout-warning} -**Note:** -The `buildpack create-project` command does not perform the actual file copy. -Use the convenient `tasks.IGNORE` and `tasks.COPY` handlers provided by the tool to perform common ignore and copy file tasks. - -### `after` - -The `after` property defines a function that runs after the command walks the directory tree. -Use this property to add post-processing logic during project creation. - -[scaffolding tools]: {%link pwa-buildpack/scaffolding/index.md %} -[`buildpack create-project`]: {%link pwa-buildpack/reference/buildpack-cli/create-project/index.md %} - -[glob patterns]: https://en.wikipedia.org/wiki/Glob_(programming) -[`fs-extra` library]: https://www.npmjs.com/package/fs-extra diff --git a/pwa-devdocs/src/pwa-buildpack/scaffolding/index.md b/pwa-devdocs/src/pwa-buildpack/scaffolding/index.md deleted file mode 100644 index 9665d71141..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/scaffolding/index.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Scaffolding ---- - -Project scaffolding is a technique for auto-generating files to support a specific project structure. -PWA Studio provides scaffolding tools to simplify project creation and help developers get started. - -Developers should use the PWA Studio libraries Magento publishes to the NPM package repository. -Early adopters of the PWA Studio project forked and worked off the project repository, but -this practice is not recommended now that scaffolding tools are available. - -## Venia concept package - -The `venia-concept` package is a good example of a PWA Studio starter application. -Most of its UI and logic come from its `@magento/venuia-ui` and `@magento/peregrine` dependencies, so -it has very little code in its own project folder. - -Since the project structure is small and simple, PWA Studio scaffolding tools use this project as the default template for creating new storefront projects. -Customizing these projects is as simple as importing small pieces of `venia-ui` and combining them with custom code. - -## The `@magento/create-pwa` command - -Using the [`@magento/create-pwa`][] project initializer is the fastest way to get a PWA Studio project set up for development. -It is a user-friendly version of the [`create-project`][] sub-command in the [`pwa-buildpack`][] CLI tool. - -Since the package name begins with `create-`, it is considered a project generator and, -the command can be run as `@magento/pwa`. -Run this project generator directly from the NPM package respository with Yarn: - -```sh -yarn create @magento/pwa -``` - -Or with NPM: - -```sh -npm init @magento/pwa -``` - -This command launches an interactive questionnaire in the command line for configuring different parts of the project. - -[`create-project`]: {%link pwa-buildpack/reference/buildpack-cli/create-project/index.md %} -[`pwa-buildpack`]: {%link pwa-buildpack/reference/buildpack-cli/index.md %} - -[`@magento/create-pwa`]: https://www.npmjs.com/package/@magento/create-pwa diff --git a/pwa-devdocs/src/pwa-buildpack/troubleshooting/index.md b/pwa-devdocs/src/pwa-buildpack/troubleshooting/index.md deleted file mode 100644 index 9f5ba25c7b..0000000000 --- a/pwa-devdocs/src/pwa-buildpack/troubleshooting/index.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Troubleshooting ---- - -This page lists solutions for common issues reported by community members for the PWA Buildpack project. -If you run into any other problems please [create an issue] or let us know in our [Slack channel]. - -To provide more details for your issue, enable verbose console logging. -Instead of `yarn start` run the following command to set a debugging environment variable: - -``` sh -DEBUG=pwa-buildpack:* yarn start -``` - -Paste the result console output into the issue. Thank you! - -## Common issues - -* [Validation errors when running developer mode](#validation-errors) -* [Venia queries to GraphQL produce validation errors](#graphql-validation-errors) -* [Browser displays "Cannot proxy to " error and the console displays `ENOTFOUND`](#cannot-proxy) -* [Webpack hangs for a long time before beginning compilation](#webpack-hangs) -* [Browser cannot resolve the `.local.pwadev` site](#cannot-resolve-site) -* [Browser does not trust the generated SSL certificate](#untrusted-ssl-cert) - -## Resolutions - -**Validation errors when running developer mode**{:#validation-errors} - -Make sure you ran `npx @magento/pwa-buildpack create-env-file packages/venia-concept` in the root directory. -The file that command generates will hold variables for your local development environment. - -**Venia queries to GraphQL produce validation errors**{:#graphql-validation-errors} - -Venia and its GraphQL queries are out of sync with the schema of the connected Magento instance. -Make sure your Magento instance is up to date with the latest from Magento 2.3 development branch. - -To test whether your queries are up to date, run the following command in the project root: - -``` sh -yarn run validate-queries -``` - -**Browser displays "Cannot proxy to " error and the console displays `ENOTFOUND`**{:#cannot-proxy} - -Make sure your Magento store loads in more than one browser. - -If you are running a local DNS server or VPN, add an entry to your hostfile and manually map this domain so NodeJS can resolve it. - -**Webpack hangs for a long time before beginning compilation**{:#webpack-hangs} - -You may have an old version of the `pwa-buildpack` project. -Update your project using the following command: - -``` sh -yarn upgrade -``` - -Make sure you have a current version of openssl on your system using the following command: - -``` sh -openssl version -``` - -The version should be 1.0 or above (or LibreSSL 2, in the case of OSX High Sierra.) - -You can install higher versions of OpenSSL with [Homebrew] on OSX, [Chocolatey] on Windows, or your Linux distribution's package manager. - -**Browser cannot resolve the `.local.pwadev` site**{:#cannot-resolve-site} - -Another program or process has edited your [host file] and removed the entry for your project domain. You can [manually edit your hostfile] to add the entry back, but you should examine your other installed software to see what has overwritten the previous change. - -**Browser does not trust the generated SSL certificate**{:#untrusted-ssl-cert} - -Generating certificates is handled by [devcert][]. It depends on OpenSSL, so make sure you have a current version of openssl on your system using the following command: - -``` sh -openssl version -``` - -The version should be 1.0 or above (or LibreSSL 2, in the case of OSX High Sierra.) - -You can install higher versions of OpenSSL with [Homebrew] on OSX, [Chocolatey] on Windows, or your Linux distribution's package manager. - -If you're running Linux, make sure that `libnss3-tools` (or whatever the equivalent is) is installed on your system. Further information provided in [this section of the devcert readme][]. - -Some users have suggested deleting the `devcert` folder to trigger certificate regeneration. - -* For MacOS users, this folder is usually found at: - ```sh -~/Library/Application Support/devcert - ``` -* For Windows users, this folder is usually found at: - ```text -${User}\AppData\Local\devcert - ``` - -[create an issue]: https://github.com/magento/pwa-buildpack/issues -[Slack channel]: https://magentocommeng.slack.com/messages/C71HNKYS2/team/UAFV915FB/ -[host file]: https://en.wikipedia.org/wiki/Hosts_(file) -[manually edit your hostfile]: https://support.rackspace.com/how-to/modify-your-hosts-file/ -[Homebrew]: https://brew.sh/ -[Chocolatey]: https://chocolatey.org/ -[devcert]: https://github.com/davewasmer/devcert -[this section of the devcert readme]: https://github.com/davewasmer/devcert#skipcertutil diff --git a/pwa-devdocs/src/reference/ui-components/index.md b/pwa-devdocs/src/reference/ui-components/index.md deleted file mode 100644 index 3863ff275f..0000000000 --- a/pwa-devdocs/src/reference/ui-components/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md %} \ No newline at end of file diff --git a/pwa-devdocs/src/releases/index.md b/pwa-devdocs/src/releases/index.md deleted file mode 100644 index c4f27a9d02..0000000000 --- a/pwa-devdocs/src/releases/index.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Releases -redirect_to: https://github.com/magento/pwa-studio/releases/ ---- \ No newline at end of file diff --git a/pwa-devdocs/src/search.md b/pwa-devdocs/src/search.md deleted file mode 100644 index 402661f171..0000000000 --- a/pwa-devdocs/src/search.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -layout: search -title: Search Results -menu_title: Search -permalink: /search/ ---- diff --git a/pwa-devdocs/src/static/fonts/.gitkeep b/pwa-devdocs/src/static/fonts/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pwa-devdocs/src/static/images/.gitkeep b/pwa-devdocs/src/static/images/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pwa-devdocs/src/static/images/contribute.png b/pwa-devdocs/src/static/images/contribute.png deleted file mode 100644 index c2d2c0ab29..0000000000 Binary files a/pwa-devdocs/src/static/images/contribute.png and /dev/null differ diff --git a/pwa-devdocs/src/static/images/getting-started.png b/pwa-devdocs/src/static/images/getting-started.png deleted file mode 100644 index b16a9da4d4..0000000000 Binary files a/pwa-devdocs/src/static/images/getting-started.png and /dev/null differ diff --git a/pwa-devdocs/src/static/images/repos.png b/pwa-devdocs/src/static/images/repos.png deleted file mode 100644 index 8f81546587..0000000000 Binary files a/pwa-devdocs/src/static/images/repos.png and /dev/null differ diff --git a/pwa-devdocs/src/static/images/what-is-pwa.png b/pwa-devdocs/src/static/images/what-is-pwa.png deleted file mode 100644 index 33d59357a5..0000000000 Binary files a/pwa-devdocs/src/static/images/what-is-pwa.png and /dev/null differ diff --git a/pwa-devdocs/src/technologies/basic-concepts/app-shell/index.md b/pwa-devdocs/src/technologies/basic-concepts/app-shell/index.md deleted file mode 100644 index b3da829254..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/app-shell/index.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Application Shell -contributors: - - gavin2point0 ---- - -Magento PWA Studio uses an application shell architecture to shorten the time it takes to load a branded experience in the UI instead of a blank page. - -This approach involves heavily caching the minimal amount of HTML, CSS and JS to load the basic UI of the page before fetching the rest through an API. - -App shell rendering is instantaneous on repeat visits because the majority of the page is in the cache. -It also prevents unnecessary data usage because it removes the need to download static content more than once. - -The following is a simple example of an application shell: - -``` html - - - - - - - - - Document - - - -
    -

    App Shell

    -
    - - - -
    - -
    - -
    - -
    - - - - - - -``` diff --git a/pwa-devdocs/src/technologies/basic-concepts/client-side-caching/index.md b/pwa-devdocs/src/technologies/basic-concepts/client-side-caching/index.md deleted file mode 100644 index e6f414d709..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/client-side-caching/index.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: Client-side caching ---- - -Client-server communication is slow and expensive. -Performance is an important feature for any Progressive Web Application (PWA), so -requests to the server should be minimized. - -Offline mode is also a required feature for a PWA. -In offline mode, the application must be able to serve pages that have been recently viewed. - -These features are implemented with the help of a client-side cache. -This local cache stores data from resources as they are fetched. -Once a resource has been cached, the service worker may consult the cache on subsequent requests for that resource to boost performance. - -## Service Worker caching - -A [service worker][] is a JavaScript file that runs in a separate thread from the main execution thread in a web application. -Service workers can intercept network requests and fetch cached data or store results from a network request into the cache. - -### Venia service worker - -Venia's service worker behavior is defined in the [`src/sw.js`][] file using Google's [Workbox][] library. - -You do not need to use Workbox to define service worker behavior, but -Workbox makes this task easier by removing boilerplate code that is always used when working with service workers. - -Venia uses the following [caching strategies][] with its service worker: - -#### [Stale-while-revalidate][] - -The stale-while-revalidate strategy tells the service worker to use a cached response if it exists. -A separate network request is made for that resource and the cache is updated for future requests. - -This strategy is used when the most up to date version of a resource is not necessary for an application. - -| Route pattern | Description | -| ------------------------------------------------- | -------------------- | -| `/` | The application root | -| `/.\\.js$` | JavaScript files | -| `/\/media\/catalog.*\.(?:png|gif|jpg|jpeg|svg)$/` | Catalog image files | - -#### [Network first][] - -The network first strategy tells the service worker to get a resource from the network first. -If a network connection cannot be made, the service worker uses the cache as a fallback. - -This strategy is used for data that may change frequently on the server. - -| Route pattern | Description | -| ------------- | ----------- | -| `\\.html$` | HTML pages | - -#### [Cache first][] - -The cache first strategy tells the service worker to use the data from the cache. -Unlike the stale-while-revalidate strategy, no network call is made to update the cache. - -If a response is not found in the cache, a network call is made to get the resource and cache the response. - -This strategy is used for non-critical assets that do not get updated very often. - -| Route pattern | Description | -| ------------- | --------------------------------------- | -| `images` | Image files served from the application | - -## Caching in the Apollo GraphQL client - -The Venia implementation storefront uses the Apollo GraphQL client to make requests to the Magento GraphQL endpoint. -It also incorporates the default [`InMemoryCache`][] implementation to add caching abilities to the client. - -The cache is persisted between browser sessions in `window.localstorage` using the [`apollo-cache-persist`][] module. -This lets the Apollo client maintain its cached data even when the user closes the application. - -By default, `InMemoryCache` uses a cache first strategy for all queries. -This strategy is set using the `fetchPolicy` prop on the `Query` component. - -Caching for Apollo is set up in the [`src/drivers/adapter.js`][] file. - -[service worker]: https://developers.google.com/web/ilt/pwa/introduction-to-service-worker -[`src/sw.js`]: https://github.com/magento/pwa-studio/blob/master/packages/venia-concept/src/sw.js -[workbox]: https://developers.google.com/web/tools/workbox/ -[caching strategies]: https://developers.google.com/web/tools/workbox/modules/workbox-strategies -[stale-while-revalidate]: https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#stale-while-revalidate -[network first]: https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#network-falling-back-to-cache -[cache first]: https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-falling-back-to-network -[`inmemorycache`]: https://www.apollographql.com/docs/react/advanced/caching -[`apollo-cache-persist`]: https://github.com/apollographql/apollo-cache-persist -[`src/drivers/adapter.js`]: https://github.com/magento/pwa-studio/blob/master/packages/venia-concept/src/drivers/adapter.js diff --git a/pwa-devdocs/src/technologies/basic-concepts/client-state-reducers-actions/index.md b/pwa-devdocs/src/technologies/basic-concepts/client-state-reducers-actions/index.md deleted file mode 100644 index abd1475659..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/client-state-reducers-actions/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=12 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/component-data-binding/index.md b/pwa-devdocs/src/technologies/basic-concepts/component-data-binding/index.md deleted file mode 100644 index cf9bbec486..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/component-data-binding/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=9 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/container-extensibility/index.md b/pwa-devdocs/src/technologies/basic-concepts/container-extensibility/index.md deleted file mode 100644 index ddd0410da6..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/container-extensibility/index.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Container extensibility ---- - -A **Container** is an HTML element that contains 0 or more [`ContainerChild`] components. -It acts as the target for `magento-loader-layout` operations. - -## Creating a Container - -To create a Container in a React component, add a `data-mid` prop to any DOM element, such as a `div`, `span`, etc. -The value of the `data-mid` prop *must* be a literal string value. -It cannot be a dynamic value or a variable reference. - -**Example:** -``` jsx -
    -``` - -**Note:** -*Composite components, such as a class or function, cannot be used as a Container.* - - -## Extending a Container - -[`ContainerChild`] components are the only allowed children of a Container. -This makes it possible to extend a Container using the `magento-loader-layout` tool from the [PWA Buildpack]. - -`magento-loader-layout` supports the following operations: - -* Remove a container -* Remove a child component in a container -* Insert content before a child component in a container -* Insert content after a child component in a container - - -[`ContainerChild`]: {% link peregrine/reference/container-child/index.md %} -[PWA Buildpack]: {% link pwa-buildpack/index.md %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/content-rendering/index.md b/pwa-devdocs/src/technologies/basic-concepts/content-rendering/index.md deleted file mode 100644 index 6177a15827..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/content-rendering/index.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Content Rendering ---- - -Browsers require HTML to display page content. -Server-side rendering and client-side rendering are two ways a browser can get rendered HTML content for a page. -This topic goes over these two ways of rendering content supported by PWA Studio and UPWARD. - -## Server-side rendering (SSR) - -Server-side rendering (SSR) is a method of providing pre-generated HTML as a response to an HTTP request. - -For example, the content of this website is pre-built from source files. -These files are converted into HTML pages and uploaded into an HTTP hosting server. -When a user visits the site, the server returns the pre-built HTML file for the browser to render. - -Example: - -```html - - - - - - My Website - - -
    Header content
    - Menu content -
    Main body content
    -
    Footer content
    - - -``` - -Server-side languages, such as PHP and Java, can also render custom HTML per request to make the experience more dynamic. -This is how Magento currently works. - -## Client-side rendering (CSR) - -Client-side rendering is another method of delivering HTML content to the browser. -Instead of providing the entire HTML page content on a request, the server returns a page with minimal content. -The page depends on a JavaScript file that finishes rendering the HTML on the page. - -The following is an example of what a bare page response looks like: - -```html - - - - - - My Web App - - -
    - - - -``` - -In this example, the `app.js` script runs after the page loads. -A common behavior for this type of file is to generate an HTML DOM tree and insert it into a root element on the page. -This pattern is often used for single page applications such as a PWA Storefront. - -## Content rendering and Search Engine Optimization (SEO) - -When and how page content renders is an important part of Search Engine Optimization (SEO). - -When a search engine crawler processes a page, it indexes the initial HTML response from the server. -Some crawlers, such as the [Googlebot][], have the ability to execute JavaScript to simulate client-side rendering. -The varying effectiveness of search engines to process client-side rendered content is an important factor to keep in mind when developing your storefront's content rendering strategies. - -Boosting a site's SEO while providing a rich, dynamic experience is a balancing act between server-side rendering and client-side rendering. - -## Content rendering in PWA Studio - -### UPWARD and server-side rendering - -The UPWARD specification supports server-side rendering through it's [JavaScript][] and [PHP][] server implementations. -The specification provide different resolvers that can return HTML content as a response to a request. - -Use the following resolvers in your applications UPWARD configuration file to enable server-side rendering. - -#### FileResolver - -The FileResolver configuration lets you use the contents of a static file in your response body. -You can pre-build static HTML files for your application and map URL to the content using the FileResolver. -This is the fastest way to deliver a server-side rendered HTML response to a request. - -#### TemplateResolver - -The TemplateResolver configuration lets you use templates to create a server-side rendered response. -Templates are more flexible than pre-built static HTML files because they let you use template variables to create the final HTML response. -Server-side rendering performance with the TemplateResolver is dependent on the complexity of the templates it uses. - -### Venia content rendering process - -Venia uses both server-side and client-side rendering to display page content. - -The following is the sequence of events that occur when a browser requests a page from the Venia storefront: - -1. The application's UPWARD server receives the request and checks to see if it is a valid page request. -2. If the request is for a page, the UPWARD server returns a pre-built, server-side rendered HTML response that contains the PWA application shell. -3. After the browser loads the initial application shell, a JavaScript bundle renders the rest of the page content on the client side using React components. - These React components may make additional calls to the UPWARD server to get the data they need to finish rendering. - -[googlebot]: https://en.wikipedia.org/wiki/Googlebot - -[javascript]: https://github.com/magento/pwa-studio/tree/develop/packages/upward-js - -[php]: https://github.com/magento-research/upward-php diff --git a/pwa-devdocs/src/technologies/basic-concepts/critical-path/index.md b/pwa-devdocs/src/technologies/basic-concepts/critical-path/index.md deleted file mode 100644 index 2a398f2a0e..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/critical-path/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=18 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/css-modules/index.md b/pwa-devdocs/src/technologies/basic-concepts/css-modules/index.md deleted file mode 100644 index 7d9e7dbc22..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/css-modules/index.md +++ /dev/null @@ -1,228 +0,0 @@ ---- -title: CSS Modules ---- - -A [CSS Module][] is a CSS file that defines class and animation names that are scoped locally by default. - -CSS modules let you import your `.css` file into a JavaScript Object with the CSS definitions as properties. -It also lets you use the `compose` property to extend and modularize style definitions. - -CSS modules do not have an official specification nor are they a browser feature. -They are part of a compilation process that executes against your project to convert scoped classes and selectors into CSS files that the browser can parse and understand. - -Tools such as [Webpack][] are used to perform this compilation process. - -PWA Studio supports CSS modules out-of-the-box and using them is the recommended approach for styling components. - -## Why you should use CSS modules - -React lets you split the UI into independent and reusable components, which allows you to update small parts of your UI without refreshing the page. - -As React applications grow, the amount of components and layers increases. -Simple style changes can have unintended side effects on different parts of a complex page. - -CSS modules give you the ability to control your element styles in a more granular way. -They allow you to build different layers of styles while building your application using a modular approach. -CSS modules make it easy and fast to achieve tasks such as upgrading buttons, headings, grids, etc. - -For more information on reusable components and code sharing in front end development see: [Block Element Modifier (BEM)][] - -## Webpack configuration - -[Webpack][] uses the Webpack [style-loader][] and [css-loader][] modules to bundle CSS styles using a configuration that looks like the following: - -``` javascript -// webpack configuration -{ - test: /\.css$/, - use: [ - 'style-loader', - { - loader: 'css-loader', - options: { - importLoaders: 1, - localIdentName: '[name]-[local]-[hash:base64:3]', - modules: true - } - } - ] -}, -``` - -The following is an explanation of each `css-loader` configuration: - -`importLoaders` - -: Tells Webpack how many loaders to apply to imported resources before applying `css-loader`. - -`localIdentName` - -: Defines the format of the generated local ident. - In this case, it is a combination of the following values: - - * `[name]` - the component name - * `[local]` - the CSS definition name - * `[hash:base64:3]` - a random base64 hash of 3 digits - - **Example:** `Subtitle-titleHighlighted-rCN` - -`modules` - -: Enables or disables CSS modules. - -For more information about Webpack configuration, follow these links to the official documentation: - -* [Webpack CSS Loader modules documentation][] -* [Webpack CSS Loader composing documentation][] - -## How it works - -The following is a basic example of how styles are used without modules: - -``` css -/* styles.css */ -.heading { color: yellow; background-color: blue; margin: 0 0 1rem; } -.titleHighlighted { padding: 1rem 2rem; text-align: center; } -``` - -``` jsx -// subtitle.js -import React, { Component } from 'react'; -import "./styles.css"; - -class Subtitle extends Component { - render() { - return ( -
    -

    My Title

    -

    My Title

    -
    - ); - } -} - -export default Subtitle; -``` - -This approach is perfectly valid, but it has several downsides as the amount of components and CSS definitions grows. -All your definitions are shared across all components which forces you to reference your elements by its DOM inheritance or create unique definition names. - -To avoid this, you can use CSS modules to create a component with locally scoped styles: - -``` jsx -// subtitle.js - -import React, { Component } from 'react'; -import myStyles from './styles.css'; - -class Subtitle extends Component { - render() { - return ( -
    -

    My Title

    -

    My Title

    -
    - ); - } -} - -export default Subtitle; -``` - -## Creating and composing CSS modules - -Any valid `.css` file can be a CSS module. -The difference is that the style definitions in that file are scoped to specific components instead of globally. - -The `composes` property is used in CSS module files to combine local style definitions. -The following example creates a CSS module that applies the `.heading` style definition wherever `.titleHighlighted` is used. - -``` css -/** ./styles.css */ -.heading { - color: yellow; - background-color: blue; - margin: 0 0 1rem; -} - -.titleHighlighted { - composes: heading; - padding: 1rem 2rem; - text-align: center; -} -``` - -### Composing from another file - -By default, `composes` looks for style definitions in the local file. -To reuse a definition from another file, use the `from` keyword. - -The following example `composes` the `heading` definition with the `baseHeading` definition from the `default_heading.css` file. - -``` css -/* default_heading.css */ -.baseHeading { color: yellow; background-color: blue; margin: 0 0 1rem; } - -/* styles.css */ -.heading { - composes: baseHeading from './default_heading.css'; - font-weight: bold; -} -``` - -## Importing and applying styles - -The syntax for importing a CSS module is the same as importing a JavaScript module. - -``` jsx -import myStyles from './styles.css'; -``` - -The style definitions in the CSS module are available as properties of `myStyles`. -They are used as values in an element's `className` attribute. - -The following example defines a `Subtitle` component which uses the `titleHighlighted` style definition: - -``` jsx -// ./subtitle.js -import React, { Component } from 'react'; -import myStyles from './styles.css'; - -export Subtitle extends Component -{ - render() { - return ( -
    -

    My Subtitle

    -
    - ); - } -} - -export default Subtitle; -``` - -This example assigns a style based on component logic: - -``` jsx - render() { - const { isHighlighted, title } = this.props; - - // we evaluate which class to apply, based on a prop received - const finalStyle = isHighlighted ? myStyles.titleHighlighted : myStyles.heading; - - return( -
    -

    { title }

    -
    - ); - } -``` - -[Webpack]: https://webpack.js.org/ -[CSS Module]: https://github.com/css-modules/css-modules -[style-loader]: https://github.com/webpack-contrib/style-loader -[css-loader]: https://github.com/webpack-contrib/css-loader -[Webpack CSS Loader composing documentation]: https://webpack.js.org/loaders/css-loader/#composing -[Webpack CSS Loader modules documentation]: https://webpack.js.org/loaders/css-loader/#modules -[Block Element Modifier (BEM)]: http://getbem.com/ diff --git a/pwa-devdocs/src/technologies/basic-concepts/graphql/index.md b/pwa-devdocs/src/technologies/basic-concepts/graphql/index.md deleted file mode 100644 index f25684b20d..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/graphql/index.md +++ /dev/null @@ -1,307 +0,0 @@ ---- -Title: GraphQL -contributors: Jstein19 ---- - -## What is GraphQL - -[GraphQL][] is a language for querying and manipulating data. -It is widely viewed as more powerful, flexible, and efficient than REST. - -## Benefits provided by GraphQL - -### Predictable results from your queries - -A GraphQL query returns only data the user asks for in their query. - -### Single request for many results - -A single request made through GraphQL can return any number of resources and their fields by following references between them as defined in the typed schema. - -### Organized data with a typed schema - -A single schema defines how users access data using GraphQL. -These schemas, formatted as JSON objects, let users know exactly how to get the data they need. - -The following is an example of a schema that defines a `Species` type with `name` and `origin` fields: - -``` graphql -type Species { - name: String - origin: Planet -} -type Planet { - name: String -} -``` - -{: .bs-callout .bs-callout-info} -_**Note:** The `origin` field is a `Planet` type, which also has a `name` field._ - -## Why use GraphQL over REST - -While GraphQL and REST are both specifications for constructing and querying APIs, GraphQL has some significant advantages over REST. - -### No versioning - -REST APIs typically have multiple versions, such as v1, v2, etc. -This is because updating endpoints in REST will often impact existing queries. - -With GraphQL, there is no need for versioning, since new types and fields can be added to the schema without impacting existing queries. - -Removing fields is done through deprecation instead of deleting them from the schema. -If an old query tries to read a deprecated field, GraphQL displays a customized warning. - -``` -type ExampleType { - firstName: String - lastName: String - name: String @deprecated(reason: "Split this field into two. Use `firstName` and `lastName`") -} -``` - -This prevents old queries from throwing confusing errors when trying to read outdated fields, lending to code maintainability. - -### Faster and more efficient - -REST APIs typically require loading from multiple URLs. -Imagine a REST API designed to get users and their forum posts. -`users/` would return information like `name` and `user//posts` would have to be queried separately to return the user's `comments`. - -With GraphQL, these `types` and their `fields` are returned using one query, which saves calls to the API. - -In the following schema example, a `User` type contains a `posts` field, which is an array of `Post` types: - -``` graphql -type Query { - user(id: Int): User - # This is our resolver; our entry into the query - # It lets us query `user` with an argument `id` - # And Expects to return a type `User` - # Yes, you can leave comments in schemas! -} - -type User { - id: Int! - name: String - posts: [Post] -} - -type Post { - id: Int! - title: String - author: User -} -``` - -{: .bs-callout .bs-callout-info} -_**Note:** The exclamation mark (!) next to a field in the schema indicates it is `non-nullable`, which means the GraphQL service promises to always return a value for this field on a query._ - -A query for this schema that requests the name and all the post titles for a specific user would look like the following: - -``` graphql -{ - user(id: 12345) { - name - posts { - title - } - } -} -``` - -The data response for the query would look like the following: - -``` -{ - "data": { - "user": { - "name": "Jane Doe" - "posts": [ - { - title: "Hello World" - }, - { - title: "I Love GraphQL" - } - ] - } - } -} -``` - -## Sample queries - -### Simple query - -Imagine a database that simply contains an object `User`, with the fields `name`, `email`, and `phone`. - -``` graphql -type Query { - user: User -} - -type User { - name: String - email: String - phone: String -} -``` - -A simple query requesting this data would look like the following: - - ``` graphql - { - user { - name - email - phone - } - } - ``` - -The response to this query would look like the following: - -``` -{ - "data": { - "user": { - "name": "Jane Doe" - "email": "JaneDoe@example.com" - "phone": "012-345-6789" - } - } -} -``` - -### Custom data query - -What if you don't need the `phone` number from `User`? -The previous query can be rewritten to return specific fields: - -``` graphql -{ - user { - name - email - } -} -``` - -The response only provides the data requested: - -``` -{ - "data": { - "user": { - "name": "Jane Doe" - "email": "JaneDoe@example.com" - } - } -} -``` - - -### Arguments in a query - -Now, what if you had multiple users and needed to grab a specific one using its `id`? -Well, with GraphQL you can pass arguments into the query: - -``` -{ - user(id: 12345) { - id - name - email - } -} -``` - -The response would look like the following: - -``` -{ - "data": { - "user": { - "id": "12345" - "name": "Jane Doe" - "email": "JaneDoe@example.com" - } - } -} -``` - -{: .bs-callout .bs-callout-info} -_**Note:** The `id` field is requested in the response in this example, but this is optional. It is used here to demonstrate that the correct user is returned._ - -### Query connected resources - -In this example, imagine that in our database a `User` is associated with multiple hobbies. -The schema would look like the following: - -``` graphql -type Query { - user: User -} - -type User { - name: String - email: String - phone: String - hobbies: [Hobby] -} - -type Hobby { - name: String - frequency: String -} -``` - -The following query requests the hobbies associated with a specific user: - -``` -{ - user(id: 12345) { - name - email - phone - hobbies { - name - frequency - } - } -} -``` - -The response would look like the following: - -``` -{ - "data": { - "user": { - "name": "Jane Doe" - "email": "JaneDoe@example.com" - "phone": "012-345-6789" - "hobbies": [ - { - "name": "painting", - "frequency": "weekly" - }, - { - "name": "video games", - "frequency": "daily" - } - ] - } - } -} -``` - -Notice how the user's `hobbies` are returned in an `array` as defined in the schema. - -## Learn more - -This topic just covers the basics of GraphQL. -To learn more, visit the [GraphQL][] website. - -[GraphQL]: https://graphql.org/ \ No newline at end of file diff --git a/pwa-devdocs/src/technologies/basic-concepts/index.md b/pwa-devdocs/src/technologies/basic-concepts/index.md deleted file mode 100644 index 4442f20ccf..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/index.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Basic Concepts ---- - -The tools provided by the Magento PWA Studio project allows you to create websites that are fast, mobile-friendly, and reliable. -This topic lists the basic concepts you need to know to work with the Magento PWA Studio tools. - -## Application shell - -An application shell provides the basic user interface structure for a progressive web application. - -For more information, see [Application shell][]. - -## Service worker - -A service worker is a script that runs in the background. -Progressive web applications use service workers for caching and resource retrieval. -[ _[Help write this topic][service worker]_ ] - -## Component data binding - -Component data binding refers to the way data flows between the source and a UI component. -Progressive web applications use data binding patterns to connect dynamic data with the user interface. -[ _[Help write this topic][component data binding]_ ] - -## GraphQL - -GraphQL is a specification for a data query language client side and a service layer on the server side. -It is used to request and push data in a progressive web application. - -For more information, see [GraphQL][]. - -## CSS modules - -CSS modules are modular and reusable CSS styles. -This allows you to develop components with styles that do not conflict with external style definitions. - -For more information, see [CSS modules][]. - -## Client state, reducers, and actions - -Client state, reducers, and actions are [Redux][] concepts used to manage and handle the state of a web application. -[ _[Help write this topic][client state, reducers, and actions]_ ] - -## Loading and offline states - -Loading and offline are both states that must be handled by progressive web applications. -[ _[Help write this topic][loading and offline states]_ ] - -## Container extensibility - -Writing extensible containers allow others to re-use and alter your container without modifying the source. - -For more information, see [Container extensibility][]. - -## Performance patterns - -Performance is an important feature for a progressive web app. -There are many strategies and patterns available to help boost the performance of a PWA. -[ _[Help write this topic][performance patterns]_ ] - -## Root components and routing - -The root component of an application is the DOM node under which all other nodes are managed by React. -Routing is the ability to map a URL pattern to the appropriate handler. -[ _[Help write this topic][root components and routing]_ ] - -## Critical path - -The critical path for rendering refers to the steps the browser takes to process the HTML, CSS, and JavaScript files to display a website. -Optimizing the critical path is important to get the best performance out of a progressive web application. -[ _[Help write this topic][critical path]_ ] - -[container extensibility]: {%link technologies/basic-concepts/container-extensibility/index.md %} -[graphql]: {%link technologies/basic-concepts/graphql/index.md %} -[css modules]: {%link technologies/basic-concepts/css-modules/index.md %} -[application shell]: {%link technologies/basic-concepts/app-shell/index.md %} - -[redux]: https://redux.js.org/introduction/core-concepts -[service worker]: https://github.com/magento/pwa-studio -[component data binding]: https://github.com/magento/pwa-studio -[client state, reducers, and actions]: https://github.com/magento/pwa-studio -[loading and offline states]: https://github.com/magento/pwa-studio -[performance patterns]: https://github.com/magento/pwa-studio -[root components and routing]: https://github.com/magento/pwa-studio -[critical path]: https://github.com/magento/pwa-studio diff --git a/pwa-devdocs/src/technologies/basic-concepts/loading-offline-states/index.md b/pwa-devdocs/src/technologies/basic-concepts/loading-offline-states/index.md deleted file mode 100644 index a06aeb5592..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/loading-offline-states/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=13 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/performance-patterns/index.md b/pwa-devdocs/src/technologies/basic-concepts/performance-patterns/index.md deleted file mode 100644 index d092770e54..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/performance-patterns/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=16 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/root-components-routing/index.md b/pwa-devdocs/src/technologies/basic-concepts/root-components-routing/index.md deleted file mode 100644 index 9f731b7933..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/root-components-routing/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=17 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/service-worker/index.md b/pwa-devdocs/src/technologies/basic-concepts/service-worker/index.md deleted file mode 100644 index 59ee2d2d7e..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/service-worker/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: ---- - -{% include content-not-available.md issue=14 %} diff --git a/pwa-devdocs/src/technologies/basic-concepts/state-management/index.md b/pwa-devdocs/src/technologies/basic-concepts/state-management/index.md deleted file mode 100644 index c506303bab..0000000000 --- a/pwa-devdocs/src/technologies/basic-concepts/state-management/index.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: State management ---- - -## What is state management - -An application, such as a PWA storefront, uses state data to render dynamic content to the user. -State management describes the way the application handles changing state data as a result of user interactions. - -Interactions, such as clicking on a button or loading the page, modify the state and update the appearance or behavior of the application. - -For example, a shopper clicks on a button to add an item to the shopping cart. -The application needs a way to add that item to the shopping cart while the shopper continues to browse the application. -It also needs to update the visual components that use shopping cart data to reflect the new state. - -## Local versus global state - -Local and global are the two different types of state a component can depend on. - -Local state data is any data scoped within a component or its children components. -This type of data is not shared with a component's parent or peer data. -Otherwise, that data should be [lifted][]. - -For example, a button component's disabled state is never used outside that component, so -it is categorized as local state data. - -```jsx -const MyButton = () => { - const [isDisabled, setIsDisabled] = useState(false); - - const handleClick= useCallback(() => setIsDisabled(true),[]) - - return ; -} -``` - -Global state data is any data made available to components in the entire application. -Components that depend on a global state value subscribe to changes for that value and re-render themselves. -Most components do not depend on the entire global state. -Instead, a component only uses small pieces of the entire global state. - -Shopping cart data is an example of global state data that components in different levels of the application use and modify. - -## Common state management technologies - -There are many libraries and framework features that implement state management. -This section describes two such technologies used in the PWA Studio project. - -### Redux - -[Redux][] is a state management design pattern and library. -It promotes the idea of a global object tree that contains the state of the whole application. -This object is known as a [store][]. - -The store is a read-only object, which can only be updated by dispatching a [reducer][] function. -Reducer functions accept the current state and an [action][] object as parameters and returns the next state. - -Application components are able to [dispatch][] various actions to update the state. -Components can also [subscribe][] to state changes to update their appearance or behavior. - -Early versions of PWA Studio used the Redux library directly as the primary mechanism for managing application state, -and the Redux pattern can be seen in hooks such as [`useRestResponse()`][]. - -Currently, PWA Studio abstracts away its Redux implementation details using Peregrine hooks and context providers. -This opens up the possibility of the project replacing Redux in Peregrine with another state management library without breaking state dependent components, such as those in Venia. - -PWA Studio allows you to customize reducers and enhancers. -The following example uses `combineReducers()` to combine the default Peregrine reducers with custom reducers specific to the project and uses the combined reducers when creating the Redux store. - -```jsx -// Example src/store.js file - -import { combineReducers, createStore } from 'redux'; -import { enhancer, reducers } from '@magento/peregrine'; - -import myReducers from './lib/reducers'; - -// You can add your own reducers here and combine them with the Peregrine exports. -const rootReducer = combineReducers({ ...reducers, ...myReducers }); - -export default createStore(rootReducer, enhancer); -``` - -### React hooks - -React version 16.8 introduced the concept of [hooks][]. -Hooks allow [function components][] to manage their own internal state by letting them use the same component lifecycle features available to class components. - -Earlier versions of React only allowed class components to manage state, -so stateful classes often became complex and hard to understand. -Hooks help developers to decompose large components into smaller functions that are focused on specific logic, such as fetching data. - -Since PWA Studio favors using function components over classes, it uses many of React's [built-in hooks][] in its Venia and Peregrine libraries. -The Peregrine library also provides [custom React hooks][] for storefront developers. -These hooks contain common Magento storefront logic such as state management. - -## State management in PWA Studio - -State management in PWA Studio is a mix of the Redux library, React hooks, and React context providers. -The Redux library is the underlying technology that powers state management behind the scenes, but -components do not interact with the global store directly. -Instead, components that need global state data use React hooks and context providers to read or update the current state. - -### Context providers - -React components look and behave as a result of their props. -Normally, this means an application needs to explicitly pass state data as a prop down the React application tree to components that need that data. -This is known as _prop drilling_. - -To avoid prop drilling, React provides the [Context][] feature. -The Context feature allows an application to define a value and make it available to its descendants without passing it down the tree. - -A Context object contains a Provider and Consumer property. -A `Context.Provider` component defines the shared data for its children, and -a corresponding `Context.Consumer` acquires the data and subscribes to any changes. - -PWA Studio uses the Context feature to provide application state data to storefront components through the [`PeregrineContextProvider`][] component. -Wrapping an application with the `PeregrineContextProvider` lets its components access different slices of the entire application state. - -{% raw %} - -```jsx -// Example src/index.js - -import React from 'react'; -import ReactDOM from 'react-dom'; - -import { Adapter } from '@magento/venia-drivers'; -import { PeregrineContextProvider } from '@magento/peregrine'; - -import store from './store'; // This was defined in the previous example -import MyApplication from `./src/components/MyApplication`; - -const apiBase = new URL('/graphql', location.origin).toString(); - -ReactDOM.render( - - - - - , - document.getElementById('root') -); - -``` - -{% endraw %} - -### Global state slices - -Peregrine exposes global state data in slices through the `PeregrineContextProvider` component and custom React hooks. -A state data slice is a subset of values from the global state. -Each slice contains data about a specific part of the application, such as the shopping cart state or user session state. - -To access a global state slice, wrap the `PeregrineContextProvider` around the main application (as shown in the previous example). - -Next, import the appropriate [context hook][] and decompose the array returned by the hook function call. -The decomposed array yields the state data and an API object to update that state. - -```jsx -// Example src/components/MyWelcomeMessage/myWelcomeMessage.js - -import { useUserContext } from '@magento/peregrine/lib/context/user'; - -const MyWelcomeMessage = () => { - const [userContext, userContextApi] = useUserContext(); - - const {isSignedIn, currentUser} = userContext; - const { firstname, lastname } = currentUser; - - if(isSignedIn){ - return Welcome {firstname} {lastname}!; - } - - return null; - -} - -export default MyWelcomeMessage; -``` - - -[`userestresponse()`]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/hooks/useRestResponse.js -[`peregrinecontextprovider`]: https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/PeregrineContextProvider/peregrineContextProvider.js -[context hook]: https://github.com/magento/pwa-studio/tree/develop/packages/peregrine/lib/context - -[redux]: https://redux.js.org/introduction/getting-started -[store]: https://redux.js.org/glossary#store -[reducer]: https://redux.js.org/glossary#reducer -[action]: https://redux.js.org/basics/actions -[dispatch]: https://redux.js.org/api/store#dispatchaction -[subscribe]: https://redux.js.org/api/store#subscribelistener -[hooks]: https://reactjs.org/docs/hooks-intro.html -[function components]: https://reactjs.org/docs/components-and-props.html#function-and-class-components -[built-in hooks]: https://reactjs.org/docs/hooks-reference.html -[custom react hooks]: https://reactjs.org/docs/hooks-custom.html -[context]: https://reactjs.org/docs/context.html -[lifted]: https://reactjs.org/docs/lifting-state-up.html diff --git a/pwa-devdocs/src/technologies/contribute/index.md b/pwa-devdocs/src/technologies/contribute/index.md deleted file mode 100644 index bacfbe9b11..0000000000 --- a/pwa-devdocs/src/technologies/contribute/index.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Contributing ---- - -Thank you for your interest in contributing to the PWA Studio project! - -Before you start, please take a moment to read through the following guidelines: - -- [Code of Conduct][] -- [Support][] - -## Terms - -**Core Team** -: The Magento core engineering/product team working on the PWA Studio project. - -**Community Maintainer** -: A community point of contact approved by the Core Team to help with project administration. - -Current list of maintainers: - -- [Jordan Eisenburger](https://github.com/Jordaneisenburger) -- [Lars Roettig](https://github.com/larsroettig) - -**Community Advisory Board** -: Consists of Community Maintainer(s) and Core Team members who help drive prioritization and scoping for community driven **help wanted** features and enhancements. - -**Directly Responsible Individual** -: The assigned developer for a specific issue. -This person is responsible for ensuring the issue is completed in a reasonable amount of time and to a certain standard. - -## Ways to contribute - -- [Identify and create issues](#identify-and-create-issues) -- [Select a groomed issue](#select-a-groomed-issue) -- [Help answer community questions](#help-answer-community-questions) - -### Identify and create issues - -If you encounter an issue while using PWA Studio or you have a suggestion for a new feature, let us know by [creating an issue][]. -Provide as much detail as you can to help us reproduce or analyze the issue before prioritizing it. - -When the issue is created, it is placed in the **Backlog** column of the [Community Backlog][] project. -Contact someone from the Community Advisory Board to bring the issue to our attention and we will add the **help wanted** label to it. - -_Please avoid creating GitHub issues asking for help on bugs in your own project that are outside the scope of this project._ - -#### Grooming new issues - -Every week, the Community Advisory Board meets to look at the **Backlog** column of the Community Backlog project. -The board grooms the backlog issues and moves issues that are well-defined and has value to the **Prioritized** column. - -If an issue does not provide enough details or provides no value, we will leave a comment and give you an opportunity to respond. -If there is no response before the next grooming session, the issue is closed. - -### Select a groomed issue - -The main way to contribute to the project is by working on an issue. -Look through the **Prioritized** column in the [Community Backlog][] for issues that are available for you to work on. - -_Do not attempt to work on something unrelated to the issues inside the **Prioritized** column._ - -If you see an issue you would like to work on in the **Prioritized** column, notify a Community Maintainer in the issue comments (by using @) to let them know you are interested. -The Community Maintainer will follow up with you to make sure you understand the scope of the changes being asked for in the issue. - -After the Community Maintainer assigns the issue to you, it is moved to the **In Progress** column of the [Community Backlog][] to prevent others from picking up the issue. - -#### Working on the solution - -As a contributer, you should familiarize yourself with the project's [coding standards and conventions][]. - -The issue will provide you with guidance for what we think the solution should look like. -If you are unsure about anything, reach out to anyone in the Community Advisory Board and we will provide more details. - -To get your contribution accepted, you must sign [Adobe's Contributor License Agreement (CLA)](https://opensource.adobe.com/cla.html). -You only need to sign the CLA once. - -#### PR review process - -After you submit your PR, the Community Advisory Board will assign one or more reviewers to look over your solution and ensure quality and adherence to standards. -As the Directly Responsible Individual for the issue, you are expected to address all feedback before the issue is sent to our QA and merged. - -If at any point in the review cycle you have commitments preventing you from addressing feedback, or -if there is a suggestion you do not understand, please let us know! -We are happy to pair program or complete those changes for you to help push the PR across the finish line. - -If you would like to do a demo of your PR at our weekly community sync on Fridays, let a Community Maintainer know so you can be added to the schedule. - -### Help answer community questions - -Another way to help contribute to this project is to help answer community questions about PWA Studio. - -Our community is growing every day, and people are evaluating or trying out PWA Studio for the first time. -Join our [#pwa Slack channel][] and help out fellow community members with their questions or share your experiences working with PWA Studio! - -[code of conduct]: CODE_OF_CONDUCT.md -[support]: SUPPORT.md -[community backlog]: https://github.com/magento/pwa-studio/projects/3 -[#pwa slack channel]: https://magentocommeng.slack.com/archives/C71HNKYS2 -[creating an issue]: https://github.com/magento/pwa-studio/issues/new/choose -[coding standards and conventions]: https://github.com/magento/pwa-studio/wiki/Project-coding-standards-and-conventions diff --git a/pwa-devdocs/src/technologies/magento-compatibility/index.md b/pwa-devdocs/src/technologies/magento-compatibility/index.md deleted file mode 100644 index fee5103e80..0000000000 --- a/pwa-devdocs/src/technologies/magento-compatibility/index.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Magento compatibility ---- - -This page lists PWA Studio versions and their compatible Magento core version. - - - -{% include auto-generated/magento-compatibility.md %} - -## What compatibility means - -If you are working directly with the PWA Studio repository, make sure the version you are working with is compatible with your Magento backend. - -GraphQL queries in Venia are a main source of incompatibility between versions. -Breaking GraphQL schema changes in Magento require an update to the GraphQL queries used in the Venia storefront. - -## Incompatibility scenarios - -- A developer has the latest PWA Studio, such as **2.1.0** or greater, but the `MAGENTO_BACKEND_URL` still points to a Magento 2 instance running **2.3.0**. -- A developer is running an older version of PWA Studio, such as **2.0.0**, but the `MAGENTO_BACKEND_URL` points to a Magento 2 instance running **2.3.1**. - -## Compatibility checks - -Since **2.1.0**, PWA Studio includes a query validation step during the build process. -This step reports on any GraphQL incompatibility it encounters. - -## Solving compatibility issues - -Developers have two options for solving compatibility issues: - -- Upgrade or downgrade the PWA Studio version to match the Magento 2 backend version -- Upgrade or downgrade the backend Magento 2 version to match the PWA Studio version diff --git a/pwa-devdocs/src/technologies/overview/images/pwa-studio-developer-overview.png b/pwa-devdocs/src/technologies/overview/images/pwa-studio-developer-overview.png deleted file mode 100644 index 8c5b20d8ca..0000000000 Binary files a/pwa-devdocs/src/technologies/overview/images/pwa-studio-developer-overview.png and /dev/null differ diff --git a/pwa-devdocs/src/technologies/overview/index.md b/pwa-devdocs/src/technologies/overview/index.md deleted file mode 100644 index 1876869653..0000000000 --- a/pwa-devdocs/src/technologies/overview/index.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Overview ---- - -This page provides a brief description of a Progressive Web App (PWA) and its relationship to the Magento PWA Studio project. - -## What is a Progressive Web App - -A Progressive Web App, or PWA, is a web application that uses modern web technologies and design patterns to provide a reliable, fast, and engaging user experience. - -The following features define a basic PWA website: - -- **Fast** - PWA sites use a variety of performance optimization strategies to provide a responsive experience or load content fast, even on slow networks. -- **Secure** - PWA sites use HTTPS connections for enhanced security. -- **Responsive** - PWA sites implement responsive design strategies to provide a consistent experience on desktops, tablets, and mobile devices. -- **Cross-browser compatible** - PWA sites work equally well on all modern browsers, such as Chrome, Edge, Firefox, Safari. -- **Offline Mode** - PWA sites cache content to ensure that some content can be served when a user is offline. -- **Mobile "Install"** - Mobile users can add PWA sites to their home screens and even receive Push notifications from the site. -- **Shareable content** - Each page in a PWA site has a unique URL that can be shared with other apps or social media. - -## What is the Magento PWA Studio project - -![pwa studio overview][] - -The Magento PWA Studio project is a set of developer tools that allow for the development, deployment, and maintenance of a PWA storefront on top of Magento 2. -It uses modern [tools and libraries][] to create a build system and framework that adheres to the Magento principle of extensibility. - -The Magento PWA Studio project provides the following tools: - -- **[pwa-buildpack][] CLI tools** - Contains the main build and development tools for a Magento PWA. -- **[Peregrine][] hooks and components** - Contains a collection of useful components and custom React hooks for a Magento PWA. -- **[Venia][] store and visual components** - The Venia package contains a proof of concept Magento 2 storefront built using the PWA Studio tools. - It also provides visual components you can use in your own projects. -- **[UPWARD][]** - A specification for a file that determines the behavior of the application server. - The project provides [UPWARD-JS][], which is a JavaScript implementation of an UPWARD server. -- **[pwastudio.io][]** - The project provides documentation to help guide developers towards creating a Magento PWA storefront. -- **Shared Magento server** - Developers have access to a Magento application running in the Cloud to help jumpstart storefront development. - This server contains sample data and is maintained by the team to ensure that you are developing on the latest version of Magento. - This shared instance is open to all PWA Studio developers. - -[tools and libraries]: {% link technologies/tools-libraries/index.md %} -[pwa-buildpack]: {% link pwa-buildpack/index.md %} -[peregrine]: {% link peregrine/index.md %} -[venia]: {% link venia-pwa-concept/index.md %} -[upward]: {% link technologies/upward/index.md %} -[upward-js]: {% link technologies/upward/reference-implementation/index.md %} -[pwa studio overview]: {%link technologies/overview/images/pwa-studio-developer-overview.png %} - -[pwastudio.io]: https://pwastudio.io diff --git a/pwa-devdocs/src/technologies/storefront-architecture/buildtime/index.md b/pwa-devdocs/src/technologies/storefront-architecture/buildtime/index.md deleted file mode 100644 index 625efab799..0000000000 --- a/pwa-devdocs/src/technologies/storefront-architecture/buildtime/index.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: Buildtime architecture ---- - -The build architecture of PWA Studio is the system used to compile JavaScript and CSS source code into a production-ready PWA storefront application. - -## Magento store dependency - -PWA Studio is part of Magento's [service-oriented architecture][] vision. -This vision minimizes dependencies by separating the merchant-facing store admin and the shopper-facing storefront application. -Separating these two applications minimizes the dependencies between them. - -The Venia build system respects this principle by running the build process independent from the Magento core application. -However, the build system does use the Magento API at compilation time for additional validation and optimization of storefront code. - -## Repository organization - -Unlike Magento themes, the source code for a PWA Studio storefront does not need to be located within the Magento application code. -A PWA Studio storefront and its backing Magento server are two separate applications, so -their codebase is separate from each other. - -The Venia concept storefront uses the `yarn` package for dependency management, but -storefronts built using PWA Studio can also use NPM to manage dependencies and run scripts. - -Early adopters of PWA Studio have cloned the [`pwa-studio` repository][] and made direct customizations to the Venia concept source. -This can lead to conflicts when updating to the latest version of the codebase. -The preferred approach is to add PWA Studio tools and libraries as dependencies in a project. - - - -## Build pipeline - -The build pipeline is the mechanism that consumes the project source code to generate production-ready files. -This process includes code [transpilation][] and smart script bundling. -Like most modern Web compilation tools, it is built on [NodeJS][]. - -The main tools used for the build pipeline are [Babel][] and [Webpack][]. -The Buildpack library provides a convenient API for configuring these tools, but the underlying API for building a Magento PWA is a direct configuration of Babel and Webpack. - -The Venia example storefront project contains an opinionated build pipeline setup, using Buildpack's `configureWebpack` API, but -developers can also use the PWA-Studio build libraries and configurations to define custom pipelines. - -### Venia build steps - -The following sections provide insight into the processes that make up Venia's build pipeline. - -#### Starting a build - -Venia's build process begins at the command prompt. -It is compatible with OSX and most Linux environments that use a `bash` shell. - -{: .bs-callout .bs-callout-warning} -Windows support is an ongoing project. - -PWA Studio projects use [NPM scripts][] to organize frequently used commands. -These `yarn run` commands are found in the `scripts` section of the Venia storefront's [`package.json`][] file. - -Use the `build` command to start the build process: - -```sh -yarn run build -``` - -#### Cleanup step - -The build process runs a `clean` script to remove old artifacts from the Venia concept's `dist` directory before generating the code. - -#### Environment validation - -The next phase uses the `buildpack load-env` command to load and validate the `.env` file, which describes the store project configuration. -This file is found in the root directory of the Venia concept project. - - - -{: .bs-callout .bs-callout-info} -If there is no `.env` file in your project, create one with the `buildpack create-env-file` command. - - - -#### Query validation - -After the environment validation phase, the build runs the `validate-queries` script. -This script uses the [`graphql-cli-validate-magento-pwa-queries`][] tool to analyze the GraphQL queries in the project and validates them against the schema downloaded from the configured Magento instance. - -{: .bs-callout .bs-callout-info} -The connected Magento instance is defined by the `MAGENTO_BACKEND_URL` environment variable. - -#### Webpack execution - -The final step in the build process uses the webpack CLI (`webpack`) to process files into bundles. -The `webpack.config.js` file in the storefront project's root configures webpack to use external tools, such as Babel and Workbox, during file processing and bundle creation. - -The artifacts generated by webpack are located in the `dist` folder. -These are static files ready to be served from an HTML document's app shell. - -When a browser loads these files, it launches a single-page application that is the Venia storefront. - -### Other build features - -The following build features are used mainly in a development environment. -They are not part of the normal production build process. - -#### Watch mode - -The `watch` script launches a development server and a persistent compiler process that monitors the source code for changes. -When a change is detected, it initiates an incremental rebuild instead of a full build to keep the application in the browser up to date. - -This feature allows you to make edits in the code and see the changes in the application without going through the full build process. - -#### Linting and testing - -The Venia concept project also contains scripts for formatting (`yarn run prettier`), style analysis (`yarn run lint`), and running unit tests (`yarn test`). - -Use these scripts to keep your codebase well-formatted and test functionality. - -[nodejs]: https://nodejs.org/en/about/ -[webpack]: https://webpack.js.org/ -[transpilation]: https://en.wikipedia.org/wiki/Source-to-source_compiler -[babel]: https://babeljs.io -[npm scripts]: https://docs.npmjs.com/misc/scripts -[service-oriented architecture]: https://en.wikipedia.org/wiki/Service-oriented_architecture -[`package.json`]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-concept/package.json -[`graphql-cli-validate-magento-pwa-queries`]: https://github.com/magento/pwa-studio/tree/develop/packages/graphql-cli-validate-magento-pwa-queries -[`pwa-studio` repository]: https://github.com/magento/pwa-studio/ diff --git a/pwa-devdocs/src/technologies/storefront-architecture/index.md b/pwa-devdocs/src/technologies/storefront-architecture/index.md deleted file mode 100644 index d05d37a6e1..0000000000 --- a/pwa-devdocs/src/technologies/storefront-architecture/index.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Storefront architecture ---- - -Unlike a Magento theme, which is dependent on the core Magento application, a PWA Studio storefront exists on a different application layer from Magento. -The storefront still communicates with the core Magento application, but it is not tightly coupled with it. - -The following sections provide information about Magento architecture designs that enable PWA Studio storefront development. - -## Headless architecture overview - -Headless architecture refers to the idea of separating the presentation layer from the data and business logic layer. -Decoupling these two layers give merchants the ability to make changes to the frontend without modifying code for the backend services. - -In the context of PWA Studio, the storefront is the frontend application and Magento is the connected backend service. -A PWA Studio storefront does not use any of Magento's frontend theme assets, layout files, or scripts. -Instead, it defines its own frontend files and uses Magento's GraphQL and REST services to send or request data. - -For more information about headless eCommerce, read the Magento blog post titled [The Future Is Headless][]. - -## Magento microservices - -Microservice architecture is a design pattern that separates an application into independent, deployable services. -Each independent service communicates with the others through lightweight APIs. -This is known as **service isolation**. - -Magento services, such as those for customers, product catalog, and checkout, provide an API through [service contracts][]. -PWA Studio storefronts interact with these services through [Magento's GraphQL][] and REST services. - -For more information about Magento's research on service isolation, see [Magento Service Isolation Vision][]. - -[the future is headless]: https://magento.com/blog/best-practices/future-headless -[magento's graphql]: https://github.com/magento/graphql-ce -[magento service isolation vision]: https://github.com/magento/architecture/blob/master/design-documents/service-isolation.md -[service contracts]: https://devdocs.magento.com/guides/v2.3/extension-dev-guide/service-contracts/service-contracts.html diff --git a/pwa-devdocs/src/technologies/storefront-architecture/runtime/index.md b/pwa-devdocs/src/technologies/storefront-architecture/runtime/index.md deleted file mode 100644 index 45f0a612c1..0000000000 --- a/pwa-devdocs/src/technologies/storefront-architecture/runtime/index.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Runtime architecture ---- - -A PWA Studio storefront's runtime architecture describes how each of its pieces interact with Magento when it is deployed. - -The following sections describe characteristics for the runtime architecture of storefronts built using PWA Studio. -Many of these characteristics follow Magento's vision for [service isolation][]. - -## API-only relationships - -A PWA Studio storefront application communicates with Magento using its external API. -Those external API services communicate with Magento's internal service modules and returns any results through that same external API. - -**GraphQL** is the preferred API to use for client data and store behavior. -[GraphQL API][] coverage increases with every Magento release, but -until full coverage is complete, developers can use the [**REST API**][] to fill in existing coverage gaps. - -To make secure, admin-authorized calls, configure the storefront's [UPWARD][] server to make the request using REST or RPC. - -Use **HTTPS** when passing requests through the UPWARD server to static and media resources in Magento. - -## One-way coupling - -The coupling between a PWA Studio storefront and Magento should go in one direction. -The storefront has a dependency on Magento, which is attached as a service, but -the Magento application should not have a dependency on the storefront. - -## Decoupled deployments - -A PWA Studio storefront and its backing Magento instance should be deployed as separate instances on separate hardware. -Using [UPWARD][] allows you to deploy these applications using different technology stacks with the dependency configured at build-time. - -Another option is to deploy the storefront to the Magento server directly using the [PHP implementation of UPWARD][]. -This is a possible option if the Magento instance is hosted in the [Magento cloud][]. - -## Storefront replacement mechanism - -A PWA Studio storefront replaces Magento's frontend theme. - -Since the coupling between the storefront and Magento is one way, Magento does not know to direct front end traffic to the storefront application. -This means that the Magento frontend theme, such as Luma, is still available by connecting directly to the Magento server. - -Use a [reverse proxy][] in your Magento server to route incoming frontend traffic to the storefront application. -If the storefront application is deployed in the same server as Magento, which can be the case if you are using [Magento cloud][] hosting, then the `magento-upward-connector` module handles the frontend replacement. - -[upward]: {% link technologies/upward/index.md %} -[magento cloud]: {%link tutorials/cloud-deploy/index.md %} - -[service isolation]: https://github.com/magento/architecture/blob/master/design-documents/service-isolation.md -[php implementation of upward]: https://github.com/magento-research/upward-php -[reverse proxy]: https://en.wikipedia.org/wiki/Reverse_proxy -[graphql api]: https://devdocs.magento.com/guides/v2.3/graphql/ -[**rest api**]: https://devdocs.magento.com/guides/v2.3/rest/bk-rest.html diff --git a/pwa-devdocs/src/technologies/theme-vs-storefront/index.md b/pwa-devdocs/src/technologies/theme-vs-storefront/index.md deleted file mode 100644 index 814ef2baa4..0000000000 --- a/pwa-devdocs/src/technologies/theme-vs-storefront/index.md +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: Magento theme vs PWA storefront ---- - -A traditional Magento store uses theme components to define the look and feel of the front-end store. -Magento's PWA Studio introduces a different approach for creating a custom front-end experience using storefront applications. - -This topic compares the traditional Magento theme development approach with a more modern approach of developing a Magento storefront using PWA Studio tools. - -## Definitions - -### Magento theme - -A Magento theme is a type of [Magento component][] that defines how a store looks. -It is deeply integrated with the Magento application and depends on the core Magento code for functionality. - -A Magento theme is always built on top of an existing parent theme. -Out of the box, Magento provides the **Blank** and **Luma** themes that developers extend or customize to create custom storefronts. - -All Magento themes inherit from a parent theme. -At the top of the inheritance chain is the Magento Blank theme, which provides the base files for a theme. -Every other theme builds on, overrides, or customizes these files. - -For more information on Magento themes, see the Magento 2 [Frontend Developer Guide][]. - -### Magento storefront application - -A Magento storefront application is a [progressive web app][] built using PWA Studio tools. - -It is made up of an application shell that exists in the browser and a [middle tier service layer][] that sits between the shell and a [headless Magento][] backend. - -Unlike a Magento theme, a storefront application does not inherit from a parent theme. -Instead, the application is composed of [React][] modules that provide the different pieces of functionality. -These pieces can be swapped out to change behavior or even removed entirely. - -For an example of a storefront application, read about the [Venia][] storefront, a reference implementation created using PWA Studio tools. - -### Components - -Both Magento theme and PWA storefront application use pieces that are known as **components**, but -each approach uses a different definition of this term. - -In Magento theme development, _components_ mostly refers to [Magento UI Components][]. -These components are standard UI elements, such as tables, buttons, and dialogs, that Magento provides to make theme development easier. - -In PWA Studio, _components_ refers to [React][] components. -React components are modular pieces that make up a React application, such as a Magento PWA storefront. - -## Dependency management - -A Magento theme uses a [Composer][] file to specify its dependencies and relies on Magento's file resolution mechanism to make sure the required theme files are available. - -PWA Studio uses [Yarn][] for dependency management and validation scripts to make sure it is compatible with the backend Magento server. - -## Inheritance vs modularity - -Since Magento themes inherit from a parent theme, the effort needed to create a custom storefront is dependent on the additional customizations needed on top of a base theme. -Some themes build off **Luma** or other existing themes and apply minimal customizations, such as logo and color changes, to create a unique look for a store. -Other themes use **Blank** as the base and require more customization work. - -This inheritance approach tightly couples a Magento theme with the themes up its inheritance chain. -As a result, parent theme updates can lead to unexpected side effects for its dependent child themes. - -Magento PWA storefront development uses a more modular approach for creating a storefront. - -Instead of starting with a base theme and customizing the pieces, a developer puts together a storefront from scratch using different React modules. -This approach provides greater flexibility and control during the storefront creation process. - -Since they are independent and modular, side effects from updating each piece is minimized. -Non-breaking updates can be applied to other modules while keeping others to a stable version. - -## Required skillset - -The skillset required to work with Magento themes is different from the skillset required for a PWA storefront because of the technologies used in each approach. - -### Magento frontend developers - -In addition to knowing standard JS libraries, such as jQuery and KnockoutJS, Magento theme developers need general knowledge about Magento component development and specialized knowledge about its templating and layout system. - -The following table is a summary of general skills needed for Magento theme development: - -| Skill | Description | -| -------------------------------- | ----------------------------------------------------------- | -| PHP | The primary language of the Magento codebase | -| JavaScript (JS) | Core web language | -| [jQuery][] | A JS library used for things such as DOM manipulations | -| [KnockoutJS][] | JS framework used for binding data models to the UI | -| Cascading Style Sheets ([CSS][]) | Defines the style for a websites | -| Leaner Style Sheets ([Less][]) | Language extension for CSS | -| XML | Format used by Magento for configuration and layout | -| [Magento layouts][] | Layouts represent the structure for a page | -| [Magento templates][] | Templates define how layout blocks are presented on a page | -| [Magento UI library][] | Frontend library for Magento theme developers | -| [Magento UI components][] | Another frontend library for Magento theme developers | -| [Composer][] | Package and dependency manager | -{:style="table-layout: auto;"} - -### Magento PWA storefront developers - -The barrier for entry for a PWA Studio developer is lower than a Magento theme developer. -PWA Studio development requires less Magento-specific knowledge to create a custom storefront, and -the tools and concepts it uses are more common and standard among the general front-end developer community. - -The following table is a summary of general skills needed for PWA storefront development: - -| Skill | Description | -| ------------------------------------- | --------------------------------------------------- | -| JavaScript (JS) | Core web language | -| [React][] | A JS library for building user interfaces | -| [Redux][] | A JS library for handling application state | -| [GraphQL][] | An API query language | -| [webpack][] | Project assets bundler | -| Cascading Style Sheets ([CSS][]) | Defines the style for a websites | -| [CSS modules][] | Locally scoped style definitions | -| JavaScript Object Notation ([JSON][]) | Data-interchange format | -| [Peregrine][] | React components library provided by the PWA Studio | -| [Yarn][] | JS package and dependency manager | -{:style="table-layout: auto;"} - -[progressive web app]: {%link technologies/overview/index.md %} -[Venia]: {%link venia-pwa-concept/index.md %} -[middle tier service layer]: {%link technologies/upward/index.md %} -[GraphQL]: {%link technologies/basic-concepts/graphql/index.md %} -[CSS modules]: {%link technologies/basic-concepts/css-modules/index.md %} -[Peregrine]: {%link peregrine/index.md %} - -[Magento component]: https://devdocs.magento.com/guides/v2.1/extension-dev-guide/bk-extension-dev-guide.html -[headless Magento]: https://magento.com/blog/best-practices/future-headless -[KnockoutJS]: https://knockoutjs.com/ -[jQuery]: https://jquery.com/ -[Less]: http://lesscss.org/ -[CSS]: https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/css-topics/css-overview.html -[Magento UI library]: https://magento-devdocs.github.io/magento2-ui-library/ -[Magento layouts]: https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/layouts/layout-overview.html -[Magento templates]: https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/templates/template-overview.html -[Magento UI components]: https://devdocs.magento.com/guides/v2.3/ui_comp_guide/bk-ui_comps.html -[React]: https://reactjs.org/ -[Redux]: https://redux.js.org/ -[JSON]: https://www.json.org/ -[webpack]: https://webpack.js.org/ -[Yarn]: https://yarnpkg.com/ -[Composer]: https://getcomposer.org/doc/00-intro.md -[Frontend Developer Guide]: https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/bk-frontend-dev-guide.html diff --git a/pwa-devdocs/src/technologies/tools-libraries/images/pwa-tools-technology-overview.png b/pwa-devdocs/src/technologies/tools-libraries/images/pwa-tools-technology-overview.png deleted file mode 100644 index e938c1f966..0000000000 Binary files a/pwa-devdocs/src/technologies/tools-libraries/images/pwa-tools-technology-overview.png and /dev/null differ diff --git a/pwa-devdocs/src/technologies/tools-libraries/index.md b/pwa-devdocs/src/technologies/tools-libraries/index.md deleted file mode 100644 index 06cbe1844a..0000000000 --- a/pwa-devdocs/src/technologies/tools-libraries/index.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: Tools and libraries ---- - -![tools and technology overview][] - -To work with the utilities provided by the Magento PWA Studio project, you should be familiar with the tools and libraries listed in the following table: - -| | Contributor | Frontend developer | Sysadmin/Devops/Backend developer | -| ------------------------- | :-------------------------------------------: | :-------------------------------------------: | :------------------------------------------------: | -| [PHP](#php) | | | help_outline | -| [JavaScript](#javascript) | check_box | check_box | help_outline | -| [webpack](#webpack) | check_box |help_outline | | -| [React](#react) | check_box | check_box | | -| [Redux](#redux) | check_box | help_outline | | -| [GraphQL](#graphql) | check_box | check_box | check_box | -| [Workbox](#workbox) | check_box | check_box | | - -## PHP - -[PHP][] is the core language used in the Magento application, but -it is not one used by the main PWA Studio project. -In general, you do not need to know PHP to work with PWA Studio tools. - -If your storefront requires heavy customizations to the Magento backend, you will need to know PHP to make the necessary backend changes. - -## JavaScript - -[JavaScript][] is a programming language used to add logic and interactive behaviors to web applications. -JavaScript is the primary language used in the PWA Studio project, and -knowing how to develop with it is necessary for using PWA Studio in your own projects. - -For frontend development, browser compatibility is important for creating a consistent experience. -Different web browsers have different version of JavaScript installed, so -developers should build their applications with this in mind. - -For backend developers, scripts and services in PWA Studio are created using [node.js][]. -It is the environment used in the PWA Studio project, but -it is not a required one for your own projects. - -## webpack - -[webpack][] is a configuration-driven asset bundler and optimizer for JavaScript applications. - -webpack's primary function is to create one or more bundles from the dependencies in your project's modules. -webpack is also able to transform, package, or optimize resources and assets using plugins. -This allows you to extend webpack's functionality beyond JavaScript bundling. - -The [pwa-buildpack][] library contains webpack tools for setting up a development or production environment. -The configuration for these tools are found in a project's `webpack.config.js` file. - -webpack is not a required library for your own projects, but -it is recommended for the development and performance benefits it provides. - -## React - -[React][] officially describes itself as a _JavaScript library for building user interfaces_. -The library provides the following features that make PWA development easier: - -- **Simple** - The React library does one thing: build a user interface. - It does this without making assumptions about the underlying technology stack. - This flexibility gives you the freedom to choose the appropriate solutions for the rest of your project. - -- **Declarative** - Creating a complex user interface is difficult when working directly with the DOM API. - React allows you to describe how your interface should look for a specific application state, and - the library takes care of rendering the UI correctly when the state changes. - -- **Modular** - React encourages developers to create modular and reusable components. - Taking a modular approach to development makes your code easier to debug and maintain. - -### Hooks - -[React hooks][] are a feature introduced in React 16.8. -They allow the use of state and logic encapsulation without using class components. - -Since hooks allow you to store state inside functional components, they are a good alternative to using [Redux](#redux). - -The [Peregrine][] library provides custom hooks for common storefront behaviors and logic. -Developers must be familiar with using hooks to get the most out of the PWA Studo library. - -## Redux - -[Redux][] is a JavaScript library used for managing state in a web application. - -It provides a global store object that holds application state that multiple components depend on. -Components that plug into the store have direct access to the specific state data they need. - -This library is often paired with React to alleviate the problem of passing data down multiple component layers. - -{: .bs-callout .bs-callout-warning} -Redux is currently being refactored out of the [Venia example storefront][] in favor of [React hooks](#hooks). -However, Redux is still a valid library for managing state in your own projects. - -## GraphQL - -[GraphQL][] is a specification for a data query language on the client side and a service layer on the server side. -It is often seen as an alternative to using [REST][] endpoints. - -One of the main advantages GraphQL has over REST is that a single GraphQL endpoint can accommodate requests for any combination of X, Y, and Z pieces of data, -whereas REST requires specialized endpoints for different data request combinations. -Unlike REST, which can require multiple server requests to aggregate data, -a single GraphQL request returns only the data needed and nothing more. - -Performance is an important metric for PWAs. -Using GraphQL improves this by reducing the number of server calls and the amount of data returned. - -The [Venia example storefront][] uses the [Apollo client][] to fetch data from a GraphQL endpoint, but -with a little extra work, it is possible to use alternative client libraries in your own project. - -## Workbox - -Google's [Workbox][] library provides modules that make it easy to work with [service workers][]. -It is useful for boosting performance by controlling cache behavior and enables offline mode, which is a requirement for any Progressive Web Application. - -[pwa-buildpack]: {% link pwa-buildpack/index.md %} -[tools and technology overview]: {%link technologies/tools-libraries/images/pwa-tools-technology-overview.png %} -[venia example storefront]: {% link venia-pwa-concept/index.md %} -[peregrine]: {%link peregrine/index.md %} - -[webpack]: https://webpack.js.org/ -[react]: https://reactjs.org/ -[redux]: https://redux.js.org/ -[graphql]: https://graphql.org/ -[rest]: https://en.wikipedia.org/wiki/REST -[javascript]: https://developer.mozilla.org/en-US/docs/Learn/JavaScript -[node.js]: https://nodejs.org/en/about/ -[php]: https://php.net/ -[react hooks]: https://reactjs.org/docs/hooks-intro.html -[apollo client]: https://www.apollographql.com/docs/react/why-apollo/ -[workbox]: https://developers.google.com/web/tools/workbox/ -[service workers]: https://developers.google.com/web/fundamentals/primers/service-workers/ diff --git a/pwa-devdocs/src/technologies/upward/images/upward-server-diagram.png b/pwa-devdocs/src/technologies/upward/images/upward-server-diagram.png deleted file mode 100644 index b28e7d4f7e..0000000000 Binary files a/pwa-devdocs/src/technologies/upward/images/upward-server-diagram.png and /dev/null differ diff --git a/pwa-devdocs/src/technologies/upward/index.md b/pwa-devdocs/src/technologies/upward/index.md deleted file mode 100644 index f8d8127dae..0000000000 --- a/pwa-devdocs/src/technologies/upward/index.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: UPWARD ---- - -**UPWARD** is an acronym for Unified Progressive Web App Response Definition. -An UPWARD definition file describes how a web server delivers and supports a Progressive Web Application. - -UPWARD definition files provide details about server behavior using platform-independent, [declarative][] language. -This lets a Progressive Web Application run on top of an UPWARD-compliant server in any language on any tech stack because the application is only concerned about the HTTP endpoint behavior from the UPWARD server. - -The main purpose of an UPWARD server is to do the following: - -1. Receive a request from the [application shell][] -1. Determine the appropriate service or process to handle the request -1. Get the results from the service or process -1. Build the HTTP response from the results -1. Send the response back to the application shell - -## Where UPWARD belongs in the PWA architecture - -An UPWARD server sits between a PWA and its resources, such as Magento. -It acts as the backend service for a PWA frontend that is able to proxy requests to connected services or serve static files. - -![UPWARD server diagram]({% link technologies/upward/images/upward-server-diagram.png %}) - -See [RATIONALE.md][] in the `upward-spec` package for a more detailed explanation of the need for an UPWARD server. -### UPWARD definition file - -An UPWARD server uses a definition file to determine the appropriate process or service for a request from an application shell. -It describes how the server should handle a request and build the response for it. - -A PWA project can include an UPWARD definition file to specify its service dependencies. -Using this definition file, an UPWARD server can be created using any language. -The [`upward.yml`][] file in the Venia storefront package is an example of an UPWARD definition file, and -the [upward-js][] server is JavaScript implementation of that specification. - -A PWA project can also use a definition file to discover the services for an existing UPWARD server and build around that specification. - -## Characteristics of an UPWARD server - -UPWARD server implementations need to have the following characteristics: - -### Idempotent - -Requests sent to an UPWARD server are [idempotent][]. -This means that a request to the server has no side effects, so -it does not matter if you send the same request multiple times to the server. - -### Provide a simple communication strategy for services - -All services provided by the server are available through a single data exchange strategy, such as GraphQL. -Limiting the methods of communication between a PWA and its resources simplifies PWA development. -It removes the responsibility of knowing how to work with different external resources and -allows developers to concentrate on using a single, familiar technology. - -### Contain no business logic - -Having business logic spread across multiple architectural layers is an antipattern that harms testability. -The declarative nature of an UPWARD specification prevents the creation of arbitrary business logic on the server. -It pushes this logic into re-usable templates or queries, the frontend application, or the backend services, so it cannot hide in the middle tier. - -### Stateless - -Since an UPWARD server cannot contain business logic, it also cannot hold a local state. -This responsibility is also moved to the frontend or backend layer. - -### Secure - -UPWARD server implementations must serve data over [HTTPS][] to protect the information and privacy of PWA users. - -### Support caching - -An UPWARD server itself is not a cache, -but it must serve static resources from [edge servers][] when possible. -This supports the need for content that a PWA can [cache and reuse when offline][]. - ---- - -**Next:** [Reference Implementation][] - -[choreograph]: https://en.wikipedia.org/wiki/Service_choreography -[application shell]: https://developers.google.com/web/fundamentals/architecture/app-shell -[declarative]: https://en.wikipedia.org/wiki/Declarative_programming -[gateway]: https://docs.microsoft.com/en-us/azure/architecture/patterns/gateway-aggregation -[HTTPS]: https://developers.google.com/web/fundamentals/security/encrypt-in-transit/why-https -[edge servers]: https://en.wikipedia.org/wiki/Content_delivery_network -[idempotent]: https://developer.mozilla.org/en-US/docs/Glossary/Idempotent -[RATIONALE.md]: https://github.com/magento/pwa-studio/blob/master/packages/upward-spec/RATIONALE.md -[`upward.yml`]: https://github.com/magento/pwa-studio/blob/master/packages/venia-concept/upward.yml -[upward-js]: https://github.com/magento/pwa-studio/tree/master/packages/upward-js -[cache and reuse when offline]: https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/ - -[Reference Implementation]: {% link technologies/upward/reference-implementation/index.md %} diff --git a/pwa-devdocs/src/technologies/upward/reference-implementation/index.md b/pwa-devdocs/src/technologies/upward/reference-implementation/index.md deleted file mode 100644 index dbcb395f7b..0000000000 --- a/pwa-devdocs/src/technologies/upward/reference-implementation/index.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Reference Implementation ---- - -The [upward-js][] package is a reference implementation of the [UPWARD][] specification built using JavaScript. -This package is able to run as standalone server or as an Express/Connect middleware. - -{: .bs-callout .bs-callout-info } -If you followed the instructions for [Setting up Venia][], it automatically sets up and uses this implementation as its application shell server. - -## Installation - -Use the following command to install upward-js in your project: - -```sh -yarn add @magento/upward-js -``` - -## Usage - -Use the command line, server API, or middleware API to launch the upward-js server. - -### Command line - -You can make this project available to the command line by installing it globally: - -```sh -yarn global add @magento/upward-js -``` - -Launch the server in the foreground using the following command: - -```sh -upward-js-server -``` - -This command does not take arguments. -Instead, it uses the following environment variables for configuration: - -| Variable | Required | Description | -| ----------------------- | -------- | ------------------------------------------- | -| `UPWARD_JS_UPWARD_PATH` | Yes | The path to the server definition file. | -| `UPWARD_JS_BIND_LOCAL` | Yes | This must be set to 1. | -| `UPWARD_JS_LOG_URL` | No | Prints the bound URL to stdout if set to 1. | -{:style="table-layout:auto"} - -### Server API - -Require `server` from `@magento/upward-js` in your Node script to import the server into your project. - -Example: - -``` js -const { server } = require('@magento/upward-js'); - -const { app } = upward({ - upwardPath: './my-upward-server.yml' -}) - -app.listen(8000); -``` - -### Middleware API - -Use `middleware` from `@magento/upward-js` to use the middleware into your project. -This middleware is compatible with Express 4, Connect, and other frameworks that use this common pattern. -It returns a Promise for a function which handles request/response pairs. - -Example: - -``` js -const express = require('express'); -const { middleware } = require('@magento/upward-js'); - -const app = express(); - -app.use(otherMiddlewaresMaybe); - -app.use(middleware('./my-upward-server.yml')); -``` - -You can also pass an `IOAdapter` as a second argument to the middleware. - -[upward-js]: https://github.com/magento/pwa-studio/tree/master/packages/upward-js - -[UPWARD]: {% link technologies/upward/index.md %} -[Setting up Venia]: {% link venia-pwa-concept/setup/index.md %} diff --git a/pwa-devdocs/src/technologies/versioning/index.md b/pwa-devdocs/src/technologies/versioning/index.md deleted file mode 100644 index ae398c49d7..0000000000 --- a/pwa-devdocs/src/technologies/versioning/index.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: Versioning strategy ---- - -## Rules for incrementing the version - -PWA Studio follows [Semantic Versioning][] rules when incrementing the version for each release. - -According to the Semantic Versioning specifications, given the `MAJOR.MINOR.PATCH` version number format: - -* **MAJOR** version increases happen when there are changes to the [public API][]. -* **MINOR** version increases happen when functionality is added while preserving backwards compatibility. -* **PATCH** version increases happen for backwards-compatible bug fixes. - -See [Semantic Versioning][] documentation for specific details about the type of changes allowed within each version. - -## Public API - -PWA Studio considers the following to be part of its public API: - -### Published Venia and Peregrine components - -Venia and Peregrine make their components available through their `index.js` files. -Any component exported through this file is considered public API. - -Sub-components can be found inside component directories. -These components are not part of the public API unless they are exported in the component's `index.js` file. - -### Component props - -React components use props as input data to define how they look and behave. - -Since props affect how a component renders or acts, the props used by published PWA Studio components are considered public API. - -[Semantic Versioning]: https://semver.org/ -[public API]: #public-api diff --git a/pwa-devdocs/src/tutorials/cloud-deploy/index.md b/pwa-devdocs/src/tutorials/cloud-deploy/index.md deleted file mode 100644 index a9d07ae044..0000000000 --- a/pwa-devdocs/src/tutorials/cloud-deploy/index.md +++ /dev/null @@ -1,244 +0,0 @@ ---- -title: Magento Cloud deployment ---- - -## Prerequisites - -- An existing Magento Cloud project -- Composer -- Yarn or NPM -- A [Magento PWA Studio][] storefront managed by NPM or Yarn. - You are not required to publish to npmjs.com, but - NPM or Yarn should be able to access your project code through Git. - -For this tutorial, the [`@magento/venia-concept`][] package for the [Venia storefront][] is used as a template, but any PWA available though NPM with an UPWARD compatible YAML file is supported. - -These instructions provide a method for building your application bundle in the Magento Cloud, but -you can get the same results by building locally with the same environment variables as your targeted production environment, and then checking your local build artifacts into source control. - -{: .bs-callout .bs-callout-warning} -Magento Cloud does not support node processes, so you cannot use UPWARD-JS to serve your storefront project. -You must use the [magento2-upward-connector][] module with [UPWARD-PHP][] to deploy your storefront in Magento Cloud. - -## Add Composer dependencies - -Use the `composer` CLI command to include the UPWARD module in the Magento installation: - -```sh -composer require magento/module-upward-connector -``` - -This command modifies the `composer.json` file and adds the package entry to the `require` section of the `composer.json` file. - -```json -"magento/module-upward-connector": "^1.0.1" -``` - -## Add Venia sample data (optional) - -The Venia storefront works best with the Venia sample data installed. There is an [automated script](https://pwastudio.io/venia-pwa-concept/install-sample-data/) in the `@magento/venia-concept` package, or you can follow the manual steps here. - -If you are deploying your own custom storefront, you may skip this step and continue to the next section. - -### Add sample data repository information - -Use the `composer` CLI to add the sample data repositories to the `composer.json` file: - -```sh -composer config repositories.catalog-venia vcs https://github.com/PMET-public/module-catalog-sample-data-venia -``` - -```sh -composer config repositories.configurable-venia vcs https://github.com/PMET-public/module-configurable-sample-data-venia -``` - -```sh -composer config repositories.customer-venia vcs https://github.com/PMET-public/module-customer-sample-data-venia -``` - -```sh -composer config repositories.tax-venia vcs https://github.com/PMET-public/module-tax-sample-data-venia -``` - -```sh -composer config repositories.sales-venia vcs https://github.com/PMET-public/module-sales-sample-data-venia -``` - -```sh -composer config repositories.media-venia vcs https://github.com/PMET-public/sample-data-media-venia -``` - -These commands add the following entries to the `composer.json` file: - -```json -"catalog-venia": { - "type": "vcs", - "url": "https://github.com/PMET-public/module-catalog-sample-data-venia" - -}, - "configurable-venia": { - "type": "vcs", - "url": "https://github.com/PMET-public/module-configurable-sample-data-venia" - - }, - "customer-venia": { - "type": "vcs", - "url": "https://github.com/PMET-public/module-customer-sample-data-venia" - - }, - "tax-venia": { - "type": "vcs", - "url": "https://github.com/PMET-public/module-tax-sample-data-venia" - - }, - "sales-venia": { - "type": "vcs", - "url": "https://github.com/PMET-public/module-sales-sample-data-venia" - - }, - "media-venia": { - "type": "vcs", - "url": "https://github.com/PMET-public/sample-data-media-venia" - - }, -``` - -### Require the sample data modules - -Run the following `composer` CLI commands to install the sample data modules into Magento: - -```sh -composer require magento/sample-data-media-venia:dev-master -``` - -```sh -composer require magento/module-catalog-sample-data-venia:dev-master -``` - -```sh -composer require magento/module-configurable-sample-data-venia:dev-master -``` - -```sh -composer require magento/module-customer-sample-data-venia:dev-master -``` - -```sh -composer require magento/module-tax-sample-data-venia:dev-master -``` - -```sh -composer require magento/module-sales-sample-data-venia:dev-master -``` - - -These commands modify the `composer.json` file and adds the sample data modules to the `require` section: - -```json -"magento/module-catalog-sample-data-venia": "dev-master", -"magento/module-configurable-sample-data-venia": "dev-master", -"magento/module-customer-sample-data-venia": "dev-master", -"magento/module-tax-sample-data-venia": "dev-master", -"magento/module-sales-sample-data-venia": "dev-master", -"magento/sample-data-media-venia": "dev-master", -``` - -## Install dependencies - -### Composer dependencies - -_Optional_: If you manually modified the `composer.json` file to make the changes described in the previous steps, update your `composer.lock` with these new dependencies: - -```sh -composer update -``` - -## Specify Cloud server environment - -{: .bs-callout .bs-callout-info} -If you build your project locally and check the build artifacts into your Magento Cloud project, skip the **Install NPX and Yarn** and **Update build hooks** sections. - -### Install NPX and Yarn - -If your project supports Yarn, which is the case for `venia-concept`, add the following entry to the `.magento.app.yaml` file. - -```yaml -dependencies: - nodejs: - yarn: "*" -``` - -### Update build hooks - -The `venia-concept` storefront uses a newer version of Node than the default environment provides. -It also uses Yarn to install its dependencies. - -The following update to the `hooks.build` section of `.magento.app.yaml` installs NVM and the latest LTS release of Node. - -It also uses NPX to run the `buildpack` CLI tool with the `create-project` sub-command to scaffold the application using the `venia-concept` template. -After scaffolding completes, it installs and builds the application and moves the build artifact to a persistent area on the file system. - -```yaml -hooks: - # We run build hooks before your application has been packaged. - build: | - set -e - - unset NPM_CONFIG_PREFIX - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.35.1/install.sh | bash - export NVM_DIR="$HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - nvm install --lts=dubnium - - npx @magento/pwa-buildpack create-project /tmp/pwa --template venia-concept --backend-url https://[your-cloud-url-here] --name Venia --author Magento --install false --npm-client yarn - cd /tmp/pwa - # Override this environment variable at runtime given all scaffolded dependencies are devDependencies - NODE_ENV=development yarn install --ignore-optional - yarn build - cp -p -r dist/ "$HOME/pwa" - cd $HOME - - php ./vendor/bin/ece-tools build:generate - php ./vendor/bin/ece-tools build:transfer -``` - -### Add required environment variables - -Use the Magento Cloud GUI or modify the `variables.env` entry in `.magento.app.yaml` to add any required environment variables. - -The following table lists the required environment variables for the Venia storefront: - -| Name | Value | -| ------------------------------------ | ------------------------------------------------------------------------------------------------------- | -| `CONFIG__DEFAULT__WEB__UPWARD__PATH` | `/app/pwa/upward.yml` (absolute path to UPWARD YAML configuration) | -| `NODE_ENV` | `production` | -| `MAGENTO_BACKEND_URL` | `https://[your-cloud-url-here]` | -| `CHECKOUT_BRAINTREE_TOKEN` | `` | -| `MAGENTO_BACKEND_EDITION` | `EE` (enable Magento Commerce features) | -| `IMAGE_OPTIMIZING_ORIGIN` | `backend` (use Fastly for image optimization) | - -## Commit modified files - -Commit all changes to the following files: - -- `.magento.app.yaml` -- `composer.json` -- `composer.lock` - -## Push changes - -Push your local changes for your deployment and wait for it to complete. - -## Congratulations - -You have installed a PWA storefront on the Cloud! - -You should be able to navigate to the frontend URL of your Cloud instance and see your PWA storefront. - -[magento pwa studio]: http://pwastudio.io -[`@magento/venia-concept`]: https://www.npmjs.com/package/@magento/venia-concept -[venia storefront]: https://pwastudio.io/venia-pwa-concept/ -[create a `package.json`]: https://docs.npmjs.com/cli/init - -[magento2-upward-connector]: https://github.com/magento-research/magento2-upward-connector -[upward-php]: https://github.com/magento-research/upward-php diff --git a/pwa-devdocs/src/tutorials/create-taglist-component/images/hard-coded-list.png b/pwa-devdocs/src/tutorials/create-taglist-component/images/hard-coded-list.png deleted file mode 100644 index 2989374909..0000000000 Binary files a/pwa-devdocs/src/tutorials/create-taglist-component/images/hard-coded-list.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/create-taglist-component/images/real-data-list.png b/pwa-devdocs/src/tutorials/create-taglist-component/images/real-data-list.png deleted file mode 100644 index d814cc9046..0000000000 Binary files a/pwa-devdocs/src/tutorials/create-taglist-component/images/real-data-list.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/create-taglist-component/images/styled-list.png b/pwa-devdocs/src/tutorials/create-taglist-component/images/styled-list.png deleted file mode 100644 index 3749601fc3..0000000000 Binary files a/pwa-devdocs/src/tutorials/create-taglist-component/images/styled-list.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/create-taglist-component/images/unstyled-list.png b/pwa-devdocs/src/tutorials/create-taglist-component/images/unstyled-list.png deleted file mode 100644 index 0a2de1d559..0000000000 Binary files a/pwa-devdocs/src/tutorials/create-taglist-component/images/unstyled-list.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/create-taglist-component/index.md b/pwa-devdocs/src/tutorials/create-taglist-component/index.md deleted file mode 100644 index e3d2778273..0000000000 --- a/pwa-devdocs/src/tutorials/create-taglist-component/index.md +++ /dev/null @@ -1,463 +0,0 @@ ---- -title: Create a tag list component ---- - -This tutorial provides the steps for creating a tag list component for a storefront. -For this tutorial, the tag list is added to the product details page in the Venia storefront. - -## Prerequisites - -Before you start this tutorial, make sure you have a storefront development environment set up. - -The general steps provided by this tutorial can apply to different kinds of setup, but -the specific details assumes that you followed the steps in the [Venia storefront setup][] topic to set up a storefront for development. - -## Step 1. Create component directory and files - -Inside your project's directory for components, create a new directory called **TagList**. -In the `pwa-studio` project, this directory is `packages/venia-ui/lib/components`. - -Inside the **TagList** directory, create empty files with the following names: - -- `index.js` -- `tag.css` -- `tag.js` -- `tagList.css` -- `tagList.js` - -{: .bs-callout .bs-callout-info} -These names follow the [naming conventions][] used in the `pwa-studio` project. - -## Step 2. Define the `Tag` module - -The `Tag` module is responible for rendering a single tag in the tag list. - -Open the `tag.js` file and add the following content: - -```jsx -import React from 'react'; - -// Use the prop-types module for type checking -import { string } from 'prop-types'; - -// This is a component responsible for rendering a single tag -const Tag = props => { - - // Destructure the props object into variables - const { value } = props; - - // Return the tag string inside a list item element - return
  • {value}
  • ; -} - -// Define the props this component accepts -Tag.propTypes = { - value: string -} - -// Make this function the default exported of this module -export default Tag; -``` - -## Step 3. Define the `TagList` module - -The `TagList` module accepts an array of strings and returns a `div` container with a list of tags. -This module is the default module exported by the `index.js` file. - -Open the `tagList.js` file and add the following content: - -```jsx -import React from 'react'; - -import { arrayOf, string } from 'prop-types'; - -// Import the previously defined Tag component -import Tag from './tag'; - -// This is the main tag list component -const TagList = props => { - - // Destructure the props object into variables - const { tagArray } = props; - - // Convert the array of tag strings into a list of Tag components - const tagList = tagArray.map(value => { - return ; - }) - - // Returns the list of Tag components inside a ul container - return
      {tagList}
    ; -} - -TagList.propTypes = { - // tagArray is expected to be an array of strings - tagArray: arrayOf(string) -} - -export default TagList; -``` - -## Step 4. Expose the module's public API - -Open the component's `index.js` file and add the following content: - -```js -export { default } from './tagList'; -``` - -Exporting modules from your component's `index.js` file is a commond standard in a React project. -It allows a component to import this component using its directory name. - -## Step 5. Add component to the product details page - -Find the component that renders the product details page in your storefront project and insert the TagList component into the page. - -In the `pwa-studio` project, this component is defined in the following file: - -```text -packages/venia-ui/lib/components/ProductFullDetail/productFullDetail.js -``` - -At the top of this file, import the TagList component: - -```jsx -import TagList from '../TagList'; -``` - -If you are using the default Venia ProductFullDetail component you can insert TagList into the **Product Description** section: - -```diff -
    -

    - Product Description -

    - -+ -
    -``` - -Now, when you visit a product detail page, it will show a list with the hard coded strings. - -![TagList with hard coded strings](images/hard-coded-list.png) - -## Step 6. Connect to real product data - -To make this component useful, it needs to show actual product-specific data. -Clicking each tag should display other similarly tagged items. - -For this tutorial, the TagList component will list the product's categories. - -### Edit the GraphQL query - -Venia's ProductFullDetail component gets the product data from the GraphQL query defined in: - -```text -packages/venia-ui/lib/queries/getProductDetail.graphql -``` - -Edit the `categories` entry for this query and add the following: - -```diff - categories { - id - breadcrumbs { - category_id - } -+ name -+ url_path - } -``` - -Appending this to the query adds a `categories` object to the returned data. -This object contains information on the name and URL paths for each category. - -### Pass the categories data into the TagList component - -Open the file for the product detail component and update the code: - -```diff -
    -

    - Product Description -

    - -- -+ -
    -``` - -This replaces the hard coded data with actual product-specific data, but -now, the `tagArray` prop has been replaced with a `categories` prop that the component does not know how to handle. - -### Update TagList - -Open `tagList.js` and update the component to accept the new `categories` prop: - -```diff - import React from 'react'; - --import { arrayOf, string } from 'prop-types'; -+import { arrayOf, shape, string } from 'prop-types'; - - // Import the previously defined Tag component - import Tag from './tag'; - - // This is the main tag list module - const TagList = props => { - - // Destructure the props object into variables -- const { tagArray } = props; -+ const { categories } = props; - -- // Convert the array of tag strings into a list of Tag components -- const tagList = tagArray.map(value => { -- return ; -+ // Convert the array of category objects into a list of Tag components -+ const tagList = categories.map(keyword => { -+ return ; - }) - - // Returns the list of Tag components inside a div container - return
      {tagList}
    ; - } - - TagList.propTypes = { -- // tagArray is expected to be an array of strings -- tagArray: arrayOf(string) -+ // categories is expected to be an object with a name and url_path string properties -+ categories: arrayOf( -+ shape({ -+ name: string.isRequired, -+ url_path: string.isRequired -+ }) -+ ) - } - - export default TagList; -``` - -Now, when you load the product details page, it lists the categories for that specific product: - -![List with real category data](images/real-data-list.png) - -## Step 7. Incorporate other Venia components - -Tags often look like buttons and provide a way to view other items that have the same tag when clicked. -Use the components provided by the PWA Studio libraries to add this feature. - -### Update Tag component - -Open `tag.js` and update the component to use existing Venia components: - -```diff - import React from 'react'; -+import Button from '../Button'; -+import { Link } from '@magento/venia-drivers'; - - // Use the prop-types module for type checking --import { string } from 'prop-types'; -+import { string, shape } from 'prop-types'; - -+const categoryUrlSuffix = '.html'; - - // This is a module responsible for rendering a single tag - const Tag = props => { - - // Destructure the props object into variables - const { value } = props; - -+ const { name, url_path } = value; -+ const url = `/${url_path}${categoryUrlSuffix}`; - -- // Return the tag string inside a list item element -- return
  • {value}
  • ; -+ // Return the tag as a Link component wrapped around a Button -+ return ( -+ -+ -+ -+ ); - } - - // Define the props this component accepts - Tag.propTypes = { -- value: string -+ value: shape({ -+ name: string.isRequired, -+ url_path: string.isRequired -+ }) - } - - // Make this function the default exported module for this file - export default Tag; -``` - -This update imports existing PWA Studio components and uses them to compose a tag button that acts as a link. - -### Update TagList component - -Since the Tag component no longer returns the tag inside a list item element, the TagList component needs to be updated to pass in the keyword object and replace the `ul` container with a `div` container: - -```diff --const tagList = categories.map(keyword => { -- return ; -+const tagList = categories.map(category => { -+ return ; - }); --return
      {tagList}
    -+return
    {tagList}
    -``` - -Now, when you open the product detail page, you see the tags listed horizontally and clicking on one takes you to that category's page. - -![Unstyled list of tag buttons](images/unstyled-list.png) - -## Step 8. Style the components - -With the click functionality in place, the last step is to add custom styles to make the tags stand out. - -### Define the TagList style - -A product can fall into multiple categories, so -the TagList style must accomodate for any number of categories. - -#### `tagList.css` - -Open the `tagList.css` file and add the following content: - -```css -.root { - display: flex; - flex-wrap: wrap; -} -``` - -This entry defines the root container of a TagList component as a [flexbox][] that wraps. -This prevents the Tags from overflowing off the side of the page. - -#### `tagList.js` - -Open the `tagList.js` file and make the following changes to the component. - -**Change 1:** Import the `mergeClasses()` function and the `tagList.css` file: - -```diff - import { arrayOf, shape, string } from 'prop-types'; - -+import { mergeClasses } from '../../classify'; -+import defaultClasses from './tagList.css'; - - import Tag from './tag'; -``` - -**Change 2:** Use the `mergeClasses()` function to merge custom classes passed into the component: - -```diff - const { categories } = props; - -+const classes = mergeClasses(defaultClasses, props.classes); -``` - -{: .bs-callout .bs-callout-info} -The `mergeClasses()` function is used for merging a component's default classes with custom class overrides. - -**Change 3:** Set the `className` property of the `div` container to the `root` class: - -```diff --return
    {tagList}
    -+return
    {tagList}
    -``` - -**Change 4:** Update the prop types with classes: - -```diff - TagList.propTypes = { - // tagArray is expected to be an array of strings - tagArray: arrayOf(string) -+ classes: shape({ -+ root: string -+ }) - } -``` - -### Define the Tag styles - -Tags need to stand out from the surrounding text and look button-like. - -#### `tag.css` - -Open the `tag.css` file and add the following content: - -```css -.root { - border: solid 1px #2680eb; - padding: 3px 9px; - margin: 5px; - border-radius: 5px; -} - -.content { - color: #2680eb; - font-size: 0.875rem; -} -``` - -#### `tag.js` - -Open the `tag.js` file and make the following changes to the component. - -**Change 1:** Import the `mergeClasses()` function and the `tag.css` file: - -```diff - import Button from '../Button'; -+import { mergeClasses } from '../../classify'; -+import defaultClasses from './tag.css'; - import { Link } from '@magento/venia-drivers'; -``` - -**Change 2:** Use the `mergeClasses()` function to merge custom classes passed into the component and create a new `buttonClasses` object: - -```diff - const { value } = props; - -+const classes = mergeClasses(defaultClasses, props.classes); -+ -+const buttonClasses = { -+ root_lowPriority: classes.root, -+ content: classes.content -+}; -``` - -The `buttonClasses` object is used to override the styles in the Button component. -The component expects a specific shape for the `classes` prop that the `buttonClasses` object fits. - -**Change 3:** Set the styles for the Link and Button component: - -```diff - return ( -- -- -- -+ -+ -+ - ); -``` - -## Congratulations - -You just created a new storefront components using PWA Studio libraries and conventions. - -![Final styled tag list component](images/styled-list.png) - -[venia storefront setup]: <{%link venia-pwa-concept/setup/index.md %}> - -[naming conventions]: https://github.com/magento/pwa-studio/wiki/Project-coding-standards-and-conventions#file-naming-and-directory-structure - -[flexbox]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox diff --git a/pwa-devdocs/src/tutorials/enable-sass-less-support/index.md b/pwa-devdocs/src/tutorials/enable-sass-less-support/index.md deleted file mode 100644 index dd6dad33cf..0000000000 --- a/pwa-devdocs/src/tutorials/enable-sass-less-support/index.md +++ /dev/null @@ -1,187 +0,0 @@ ---- -title: Enable SASS or LESS support ---- - -This tutorial provides the steps to enable SASS or LESS support in your storefront project. - -Use these Webpack configurations to add support for SASS and LESS alongside [CSS Modules][]. - -## Add SASS support - -### Step 1. Install dependencies - -Use a package manager, such as `yarn` or `npm`, to install the SASS loader as a dev dependency. - -```sh -yarn add --dev sass-loader node-sass -``` - -### Step 2. Modify the Webpack configuration - -Edit `webpack.config.js` and add a new `config` rule entry: - -```diff - - config.plugins = [ - ...config.plugins, - new DefinePlugin({ - /** - * Make sure to add the same constants to - * the globals object in jest.config.js. - */ - UNION_AND_INTERFACE_TYPES: JSON.stringify(unionAndInterfaceTypes), - STORE_NAME: JSON.stringify('Venia') - }), - new HTMLWebpackPlugin({ - filename: 'index.html', - template: './template.html', - minify: { - collapseWhitespace: true, - removeComments: true - } - }) - ]; -+ -+ config.module.rules.push({ -+ test: /\.s[ca]ss$/, -+ use: [ -+ 'style-loader', -+ { -+ loader: 'css-loader', -+ options: { -+ modules: true, -+ sourceMap: true, -+ localIdentName: '[name]-[local]-[hash:base64:3]' -+ } -+ }, -+ 'sass-loader' -+ ] -+ }); -``` - -### Step 3. Create a SASS file and import it in a component - -Create the `myComponent.scss` file: - -```scss -$button-color: #ff495b; -$button-color-hover: #ff9c1a; - -.root { - padding: 15px; -} - -.button { - color: $button-color; - - &:hover { - color: $button-color-hover; - } -} -``` - -Create a component and import the SASS file: - -```jsx -import React from 'react'; -import defaultClasses from './myComponent.scss'; - -const MyComponent = () => ( -
    - -
    -); - -export default MyComponent; -``` - -## Add LESS support - -### Step 1. Install dependencies - -Use a package manager, such as `yarn` or `npm`, to install the LESS loader as a dev dependency. - -```sh -yarn add --dev less-loader less -``` - -### Step 2. Modify the Webpack configuration - -Edit `webpack.config.js` and add a new `config` rule entry: - -```diff - - config.plugins = [ - ...config.plugins, - new DefinePlugin({ - /** - * Make sure to add the same constants to - * the globals object in jest.config.js. - */ - UNION_AND_INTERFACE_TYPES: JSON.stringify(unionAndInterfaceTypes), - STORE_NAME: JSON.stringify('Venia') - }), - new HTMLWebpackPlugin({ - filename: 'index.html', - template: './template.html', - minify: { - collapseWhitespace: true, - removeComments: true - } - }) - ]; -+ -+ config.module.rules.push({ -+ test: /\.less$/, -+ use: [ -+ 'style-loader', -+ { -+ loader: 'css-loader', -+ options: { -+ modules: true, -+ sourceMap: true, -+ localIdentName: '[name]-[local]-[hash:base64:3]' -+ } -+ }, -+ 'less-loader' -+ ] -+ }); -``` - -### Step 3. Create a LESS file and import it on your component - -Create the `myComponent.less` file: - -```less -@button-color: #ff495b; -@button-color-hover: #ff9c1a; - -.root { - padding: 15px; -} - -.button { - color: @button-color; - - &:hover { - color: @button-color-hover; - } -} -``` - -Create a component and import the LESS file: - -```jsx -import React from 'react'; -import defaultClasses from './myComponent.less'; - -const MyComponent = () => ( -
    - -
    -); - -export default MyComponent; -``` - -[css modules]: <{%link technologies/basic-concepts/css-modules/index.md %}> diff --git a/pwa-devdocs/src/tutorials/hello-upward/adding-react/index.md b/pwa-devdocs/src/tutorials/hello-upward/adding-react/index.md deleted file mode 100644 index b3064769c5..0000000000 --- a/pwa-devdocs/src/tutorials/hello-upward/adding-react/index.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: Adding React ---- - -This tutorial teaches you how to add webpack to your UPWARD project and use it to create a React application. - -This tutorial builds on the project described in the previous [Using the TemplateResolver][] topic. - -## Install dependencies - -Add babel, webpack, and react dependencies to the project: - -```sh -yarn add @babel/core @babel/preset-env babel-loader webpack webpack-cli @babel/preset-react react react-dom -``` - -In addition to installing React, this command installs [babel][] configurations and [webpack][]. - -In general, React components are written using ES6([ECMAScript 2015][]) and [JSX][] syntax for the convenience and ease of readability they provide. -Using [babel][] and [webpack][] is a common way to incorporate ES6 and JSX into a React project. - -## Modify template - -Modify the `hello-world.mst` template to replace the original message with a "root" DOM node for the React application: - -{% raw %} - -```diff -{{> templates/open-document}} - - {{ title }} - - {{> templates/open-body}} - -- Hello Template World! -+
    Loading...
    -+ -+ - - {{> templates/close-document}} -``` - -{% endraw %} - -This update renders a loading message in the root DOM and executes the `app.js` script after the browser parses the HTML document. - -## Create webpack config - -Create a `webpack.config.js` file to configure webpack behavior: - -```js -const path = require('path'); - -module.exports = { - mode: 'development', - entry: './src/hello-world.js', - output: { - filename: 'app.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.js$/, - exclude: /node_modules/, - loader: 'babel-loader' - } - ] - } -}; -``` - -This configuration file tells webpack to transpile all JavaScript files using babel and bundle `src/hello-world.js` with its dependencies into `dist/app.js`. - -## Create babel config - -Create a `.babelrc` file to configure babel: - -```text -{ - "presets": ["@babel/preset-env","@babel/preset-react"] -} -``` - -This configuration file tells babel what presets to use during JavaScript transpilation. -The presets used in this example, `@babel/preset-env` and `@babel/preset-react`, are common React development presets. - -## Create the React application - -Create a `src` directory in your project's root directory and a `hello-world.js` file inside that directory with the following content: - -```jsx -import React from 'react'; -import ReactDOM from 'react-dom'; - -class App extends React.Component { - render() { - return

    Hello React World!

    ; - } -} - -ReactDOM.render(, document.getElementById('root')); -``` - -This file defines an `App` React component that returns a "Hello React World!" message wrapped inside `h1` tags. -It uses the `ReactDOM` module to inject the content of the application into the "root" DOM element in the document. - -## Make the application script publicly available - -Edit the `spec.yml` file to add a new URL pattern to check in the ConditionalResolver and a new `appScript` object. - -```diff -... - -response: - resolver: conditional - when: - - matches: request.url.pathname - pattern: '^/?$' - use: helloWorld - - matches: request.url.pathname - pattern: '^/hello-world/?$' - use: helloWorld -+ - matches: request.url.pathname -+ pattern: '^/js/app.js' -+ use: appScript - default: notFound - -helloWorld: -... - -notFound: -... - -+ appScript: -+ inline: -+ status: -+ resolver: inline -+ inline: 200 -+ headers: -+ resolver: inline -+ inline: -+ content-type: -+ resolver: inline -+ inline: 'application/javascript' -+ body: -+ resolver: file -+ file: -+ resolver: inline -+ inline: './dist/app.js' -+ encoding: -+ resolver: inline -+ inline: 'utf-8' -``` - -This update uses a [FileResolver][] which instructs the UPWARD server to respond with the contents of `dist/app.js` when there is a request for the `js/app.js` path. - -## Create the bundle and start the server - -Create the `dist/app.js` bundle from `src/hello-world.js` and start the UPWARD server: - -```sh -npx webpack && node server.js -``` - -When webpack bundles `src/hello-world.js` into `dist/app.js`, it includes its dependencies, such as React and ReactDOM. - -When you navigate to the server, you will see the React application render the "Hello React World!" message using the App component. - -[Using the TemplateResolver]: {%link tutorials/hello-upward/using-template-resolver/index.md %} - -[ecmascript 2015]: http://www.ecma-international.org/ecma-262/6.0/index.html -[jsx]: https://reactjs.org/docs/introducing-jsx.html -[babel]: https://babeljs.io/ -[webpack]: https://webpack.js.org/ -[FileResolver]: https://github.com/magento/pwa-studio/tree/develop/packages/upward-spec#fileresolver diff --git a/pwa-devdocs/src/tutorials/hello-upward/simple-server/index.md b/pwa-devdocs/src/tutorials/hello-upward/simple-server/index.md deleted file mode 100644 index c547099779..0000000000 --- a/pwa-devdocs/src/tutorials/hello-upward/simple-server/index.md +++ /dev/null @@ -1,214 +0,0 @@ ---- -title: Creating a simple server ---- - -This tutorial teaches the basics of reading and writing an UPWARD specification file by creating a simple web server that returns a "Hello World" string. - -## Prerequisites - -- [Node][] >= 10.14.1 -- [Yarn][] (recommended) or [NPM][] - -## Initial setup - -1. Create the project directory and navigate into it: - - ```sh - mkdir hello-upward && cd hello-upward - ``` - -1. Use Yarn or NPM to initialize the project's `package.json` file: - - ```sh - yarn init -y - ``` - - Running this command creates a `package.json` file in your current directory. - The `package.json` file contains information about your project, such as name, version, dependencies, and runnable commands. - - The `-y` parameter is used in this tutorial to skip the interactive session. - Omit this parameter if you want to fill out information about your project during initialization. - -1. Install the `@magento/upward-js` and `express` packages: - - ```sh - yarn add @magento/upward-js express - ``` - - The [`upward-js`][] package contains modules for deploying an UPWARD-compliant server. - - [Express][] is a web framework for Node.js. - It is a dependency for the `upward-js` modules used in this tutorial. - -## Create the initial UPWARD spec - -An UPWARD server requires an [UPWARD specification][] file to tell it how to respond to requests. -Create a new file called `spec.yml` with the following content: - -```yml -status: response.status -headers: response.headers -body: response.body - -response: - resolver: inline - inline: - status: - resolver: inline - inline: 200 - headers: - resolver: inline - inline: - content-type: - resolver: inline - inline: 'text/string' - body: - resolver: inline - inline: 'Hello World!' -``` - -The first three lines set the `status`, `headers`, and `body` values required for an UPWARD server response. -These values are set by traversing a decision tree defined in the specification file. - -In this example, they are set to the `response.status`, `response.headers`, and `response.body` values defined in the `response` object. -These values are set using an UPWARD [InlineResolver][], which resolves the value of the `inline` property to a literal value. - -When passed to an UPWARD server, this file instructs the server to respond with a `200 OK` status code, content of type `text/string`, and a value of `Hello World!` in the response body for every request. - -## Create and run the server - -Create a `server.js` file with logic for starting the Node implementation of an UPWARD server. - -```js -const { createUpwardServer } = require('@magento/upward-js'); - -createUpwardServer({ - upwardPath: 'spec.yml', - bindLocal: true, - logUrl: true, - port: 8080 -}); -``` - -This file imports the `createUpwardServer` module from the `@magento/upward-js` package and uses it to start a web server. - -The script specifies the location of the UPWARD specification file through the `upwardPath` configuration and sets the port number of the server to `8080`. -The `logUrl` configuration tells the script to display the URL of the server and `bindLocal` tells it to create and bind to local HTTP server. - -Use `node` to run the server script: - -```sh -node server.js -``` - -When the server starts, the URL for the server is displayed in the terminal. - -```sh -> node server.js - -http://0.0.0.0:8080/ -``` - -Navigate to this URL in your browser to see the "Hello World!" message. - -## Define a 404 response - -When you browse to the server, every path request returns the same message. -To restrict this message to a specific path, use a ConditionalResolver. - -Edit `spec.yml` and replace the InlineResolver content of the `response` object with a [ConditionalResolver][] to define which paths return "Hello World!". - -```diff -status: response.status -headers: response.headers -body: response.body - -response: -- resolver: inline -- inline: -- status: -- resolver: inline -- inline: 200 -- headers: -- resolver: inline -- inline: -- content-type: -- resolver: inline -- inline: 'text/string' -- body: -- resolver: inline -- inline: 'Hello World!' -+ resolver: conditional -+ when: -+ - matches: request.url.pathname -+ pattern: '^/?$' -+ use: helloWorld -+ - matches: request.url.pathname -+ pattern: '^/hello-world/?$' -+ use: helloWorld -+ default: notFound -``` - -This code tells the server to look at the requested URL path and check to see if it matches the root or `/hello-world` path. -If it matches, the server uses an object called `helloWorld` to resolve the response. -For all other paths, the server resolves the response using the `notFound` object. - -After the `response` object, define the following `helloWorld` and `notFound` objects in the `spec.yml` file: - -```yml -helloWorld: - inline: - status: - resolver: inline - inline: 200 - headers: - resolver: inline - inline: - content-type: - resolver: inline - inline: 'text/string' - body: - resolver: inline - inline: 'Hello World!' - -notFound: - inline: - status: - resolver: inline - inline: 404 - headers: - resolver: inline - inline: - content-type: - resolver: inline - inline: 'text/string' - body: - resolver: inline - inline: 'Page not found!' -``` - -Now, when you start the server and navigate to the application, only the root and `/hello-world` path return the "Hello World!" message. -All other paths return the `404` response. - -Valid URLS: - -* `http://0.0.0.0:8080/` -* `http://0.0.0.0:8080/hello-world` - -Examples of invalid URLS: - -* `http://0.0.0.0:8080/goodbye-world` -* `http://0.0.0.0:8080/something-else` - -**Next:** [Rendering web pages using the TemplateResolver][] - -[upward specification]: https://github.com/magento/pwa-studio/tree/master/packages/upward-spec -[node]: https://nodejs.org -[yarn]: https://yarnpkg.com/en/ -[npm]: https://www.npmjs.com/get-npm -[express]: https://expressjs.com/ - -[`upward-js`]: {% link technologies/upward/reference-implementation/index.md %} -[Rendering web pages using the TemplateResolver]: {% link tutorials/hello-upward/using-template-resolver/index.md %} -[InlineResolver]: https://github.com/magento/pwa-studio/tree/develop/packages/upward-spec#inlineresolver -[ConditionalResolver]: https://github.com/magento/pwa-studio/tree/develop/packages/upward-spec#conditionalresolver diff --git a/pwa-devdocs/src/tutorials/hello-upward/using-template-resolver/index.md b/pwa-devdocs/src/tutorials/hello-upward/using-template-resolver/index.md deleted file mode 100644 index 72874149dc..0000000000 --- a/pwa-devdocs/src/tutorials/hello-upward/using-template-resolver/index.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: Using the TemplateResolver ---- - -In this tutorial, you will learn how to use the [TemplateResolver][] in your UPWARD specification file to serve an HTML page rendered server-side. - -This tutorial builds on the project described in the previous [Creating a simple server][] tutorial. - -## Create web page templates - -In your project directory, create a `templates` directory. This directory will house [Mustache][] template files for the different pieces of the HTML page. - -**`open-document.mst`** - -```mustache - - - - - -``` - -This template partial creates the beginning of the HTML response. -The `head` tag is left open to allow custom metadata, such as title, scripts, and styles. - -**`open-body.mst`** - -```mustache - - -``` - -This template partial closes the `head` tag and begins the `body` tag of the HTML response. - -**`close-document.mst`** - -```mustache - - -``` - -This template partial closes the `body` and `html` tag for the HTML response. - -**`hello-world.mst`** - -{% raw %} - -```mustache -{{> templates/open-document}} - - {{ title }} - - {{> templates/open-body}} - - Hello Template World! - - {{> templates/close-document}} -``` - -{% endraw %} - -This template uses the previously defined template partials to create a complete HTML response. -The body contains the "Hello Template World!" message in bold and sets the page title to a `title` variable, which is available through the template context. - -## Add TemplateResolver - -Modify the `helloWorld` object in the `spec.yml` file and replace the simple text response to an actual HTML page. - -```diff -helloWorld: - inline: - status: - resolver: inline - inline: 200 - headers: - resolver: inline - inline: - content-type: - resolver: inline -- inline: 'text/string' -+ inline: 'text/html' - body: -- resolver: inline -- inline: 'Hello World!' -+ resolver: template -+ engine: mustache -+ template: './templates/hello-world.mst' -+ provide: -+ title: -+ resolver: inline -+ inline: 'This is the page title!' -``` - -This new code replaces the InlineResolver with a TemplateResolver in the response body. -This TemplateResolver configuration sets the rendering engine to `mustache`, since the templates created previously are in Mustache format. -It also provides the `title` variable to the context during template render. - -Now, when you start the server and navigate to the root or `/hello-world` path, you get an actual HTML webpage instead of text. -View the page source for the page to see the HTML rendered from the templates. - -**Next:** [Adding React to the server][] - -[Creating a simple server]: {%link tutorials/hello-upward/simple-server/index.md %} -[Adding React to the server]: {%link tutorials/hello-upward/adding-react/index.md %} - -[Mustache]: https://mustache.github.io/mustache.5.html -[TemplateResolver]: https://github.com/magento/pwa-studio/tree/develop/packages/upward-spec#templateresolver diff --git a/pwa-devdocs/src/tutorials/index.md b/pwa-devdocs/src/tutorials/index.md deleted file mode 100644 index bde89e5c52..0000000000 --- a/pwa-devdocs/src/tutorials/index.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Tutorials ---- - -This section contains links to tutorials that will help you become familiar with the different tools provided by PWA Studio. - -## Recommended tutorials - -### UPWARD - -This three part tutorial provides an introduction to the concepts introduced in the UPWARD spec. -By the end of this tutorial, you should have a simple React application running on top of an UPWARD server. - -1. [Creating a simple UPWARD server][] - Teaches the very basics of reading and writing an UPWARD specification file for your projects -2. [Using the TemplateResolver][] - Introduces the concept of using templates and the TemplateResolver to keep your UPWARD specification file lean -3. [Adding React][] - Add React and Webpack into your UPWARD project - -### Magento Cloud deployment - -[Magento Cloud deployment][] - Provides steps for deploying a PWA Studio storefront into the Magento Cloud. -This tutorial uses the Venia example storefront to illustrate the general process. - -[creating a simple upward server]: <{%link tutorials/hello-upward/simple-server/index.md%}> -[using the templateresolver]: <{%link tutorials/hello-upward/using-template-resolver/index.md%}> -[adding react]: <{%link tutorials/hello-upward/adding-react/index.md%}> -[magento cloud deployment]: <{%link tutorials/cloud-deploy/index.md %}> diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/add-a-static-route/images/hellow-world-jsx.png b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/add-a-static-route/images/hellow-world-jsx.png deleted file mode 100644 index dd41c14e82..0000000000 Binary files a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/add-a-static-route/images/hellow-world-jsx.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/add-a-static-route/index.md b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/add-a-static-route/index.md deleted file mode 100644 index bd277ce20d..0000000000 --- a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/add-a-static-route/index.md +++ /dev/null @@ -1,278 +0,0 @@ ---- -title: Add a static route ---- - -Magento's built in CMS system and [PageBuilder][] feature lets you create highly customized content pages for your storefront, but -sometimes you need a page that fulfills a specific function, such as a checkout or login page. - -This tutorial provides steps for creating a custom, static route for these types of functional pages. - -By the end of this tutorial, you will know how to: - -- Define a custom React component to render route content -- Override Venia components -- Add a new static route that renders the custom React component - -For more information on routing, see [Routing][]. - -{: .bs-callout .bs-callout-info} -This tutorial requires you to have a project set up using the steps provided in the [Project Setup][] tutorial. - -## Create a components directory - -If your project does not already have one, create a `components` directory under your `src` directory. -This directory will hold your project's custom components. - -```sh -mkdir -p src/components -``` - -## Define a custom React component - -Every route needs a component to render the content. -For this tutorial, you will define a component that renders a simple message on the page. -This component will be assigned a route in a later step. - -### Create component directory - -Create the directory to hold the code for a custom Foo component. - -```sh -mkdir -p src/components/Foo -``` - -### Create `foo.js` module - -Inside the Foo component directory, create a `foo.js` file with the following content: - -```jsx -/* src/components/Foo/foo.js */ - -import React, { useEffect } from 'react'; - -const Foo = () => { - - return ( -

    Hello World JSX

    - ); -} - -export default Foo; -``` - -### Create `index.js` file - -Inside the Foo component directory, create an `index.js` file that exports the Foo component. -This pattern of exposing the module through the `index.js` file is the same pattern used in the Venia UI package. - -```js -/* src/components/Foo/index.js */ - -export {default} from './foo'; -``` - -## Overriding Venia components overview - -As described in the [Project Structure][] topic, a new project set up using the scaffolding command imports the entire Venia app as a single component. -To replace the [Routes][] component, which is imported and used in Venia's [App][] component, you need to: - -1. Define a new Routes component -2. Make a copy of the App component that imports your new Routes component -3. Import your project's App component in your `src/index.js` file - -Copies of the Routes and App components are found in your project's `node_modules` directory. - -## Override Routes component - -The Routes component is responsible for deciding which components to use for rendering non-Magento routes. -To override this component, you need to copy the source code into your project and make the necessary modifications. - -### Create Routes directory - -Create a Routes directory under components. This will hold your project's version of the Routes component. - -```sh -mkdir -p src/components/Routes -``` - -### Copy over Routes component code - -Get a copy of the `routes.js` file from the `node_modules` directory: - -```sh -cp node_modules/@magento/venia-ui/lib/components/Routes/routes.js src/components/Routes -``` - -### Update Routes's module imports - -Open the `routes.js` file and update the relative import statements to use components from the Venia UI package. - -```diff -- import { fullPageLoadingIndicator } from '../LoadingIndicator'; -- import MagentoRoute from '../MagentoRoute'; -+ import { fullPageLoadingIndicator } from '@magento/venia-ui/lib/components/LoadingIndicator'; -+ import MagentoRoute from '@magento/venia-ui/lib/components/MagentoRoute'; - -- const CartPage = lazy(() => import('../CartPage')); -- const CheckoutPage = lazy(() => import('../CheckoutPage')); -- const CreateAccountPage = lazy(() => import('../CreateAccountPage')); -- const Search = lazy(() => import('../../RootComponents/Search')); -+ const CartPage = lazy(() => import('@magento/venia-ui/lib/components/CartPage')); -+ const CheckoutPage = lazy(() => import('@magento/venia-ui/lib/components/CheckoutPage')); -+ const CreateAccountPage = lazy(() => import('@magento/venia-ui/lib/components/CreateAccountPage')); -+ const Search = lazy(() => import('@magento/venia-ui/lib/RootComponents/Search')); -``` - -### Import your custom component - -Import your custom Foo component in the `routes.js` file. -Use lazy loading to load your component only when it is needed. - -Since the module is exposed through it's `index.js` file, you only need to refer to the component directory in the import declaration. - -```diff - const Search = lazy(() => import('@magento/venia-ui/lib/RootComponents/Search')); -+ const Foo = lazy(() => import('../Foo')); -``` - -### Add custom route - -Add a new route entry inside the Switch component and assign the Foo component for rendering that route: - -```diff - - -+ -+ -+ - - - - - - - - - - - - - - - - - -``` - -### Create Routes component's `index.js` file - -Create an `index.js` file for your custom Routes component to expose your `routes.js` module using the directory name. - -```js -/* src/components/Routes/index.js */ - -export {default} from './routes'; -``` - -## Override the App component - -The App component is the project's main application entry point. -The steps for overriding this component is the same as the ones for overriding the Routes component. - -### Create App directory - -Create an **App** directory to hold your project's copy of Venia's App component code. - -```sh -mkdir -p src/components/App -``` - -### Copy over App component's modules - -The `app.js` file in Venia's App component imports and uses the Routes component, so copy this file into your project. - -```sh -cp node_modules/@magento/venia-ui/lib/components/App/app.js src/components/App -``` - -If you look at the [`index.js` file for Venia's App component][], its default export is not `app.js`. -The default export for this component is `container.js`, which is a container for the `app.js` module, so copy the `container.js` file into your project. - -```sh -cp node_modules/@magento/venia-ui/lib/components/App/container.js src/components/App -``` - -### Update App modules' imports - -Open the `app.js` file and update the relative import statements to use components from the Venia UI package. -Skip updating the Routes import to use this project's version of the Routes component. - -```diff -- import { HeadProvider, Title } from '../Head'; -- import Main from '../Main'; -- import Mask from '../Mask'; -- import Navigation from '../Navigation'; -+ import { HeadProvider, Title } from '@magento/venia-ui/lib/components/Head'; -+ import Main from '@magento/venia-ui/lib/components/Main'; -+ import Mask from '@magento/venia-ui/lib/components/Mask'; -+ import Navigation from '@magento/venia-ui/lib/components/Navigation'; - import Routes from '../Routes'; -- import { registerMessageHandler } from '../../util/swUtils'; -- import { HTML_UPDATE_AVAILABLE } from '../../constants/swMessageTypes'; -- import ToastContainer from '../ToastContainer'; -- import Icon from '../Icon'; -+ import { registerMessageHandler } from '@magento/venia-ui/lib/util/swUtils'; -+ import { HTML_UPDATE_AVAILABLE } from '@magento/venia-ui/lib/constants/swMessageTypes'; -+ import ToastContainer from '@magento/venia-ui/lib/components/ToastContainer'; -+ import Icon from '@magento/venia-ui/lib/components/Icon'; -``` - -Open the `container.js` file and update the relative import statements to use components from the Venia UI package. -Skip updating the App module from `app.js` to use this project's version of the that module. - -```diff - import App from './app'; -- import { useErrorBoundary } from './useErrorBoundary' -+ import { useErrorBoundary } from '@magento/venia-ui/lib/components/App/useErrorBoundary' -``` - -### Create App component's `index.js` file - -Create an `index.js` file for your custom App component and set your version of `container.js` as the default export. - -```js -/* src/components/App/index.js */ - -export {default} from './container'; -``` - -## Import new App component - -Open your project's `src/index.js` file and update the import for the App component to use your custom App component. - -```diff -- import App, { AppContextProvider } from '@magento/venia-ui/lib/components/App'; -+ import { AppContextProvider } from '@magento/venia-ui/lib/components/App'; -+ import App from './components/App`; -``` - -## View route content - -Start your dev server using `yarn start` or `yarn develop` and navigate to the `/foo` route. - -You should see the following content on the page: - -![hello world jsx][] - -## Congratulations - -You just created a static route in your storefront project! - -[routing]: <{%link peregrine/routing/index.md %}> -[project setup]: <{%link tutorials/pwa-studio-fundamentals/project-setup/index.md %}> -[hello world jsx]: <{%link tutorials/pwa-studio-fundamentals/add-a-static-route/images/hellow-world-jsx.png %}> -[pagebuilder]: <{%link pagebuilder/index.md %}> -[project structure]: <{%link tutorials/pwa-studio-fundamentals/index.md %}> -[routes]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/Routes/routes.js -[app]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/App/app.js -[`index.js` file for venia's app component]: https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/App/index.js diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/css-modules/index.md b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/css-modules/index.md deleted file mode 100644 index e25f4e0223..0000000000 --- a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/css-modules/index.md +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: CSS Modules ---- - -If you used the scaffolding tool to set up your PWA Studio storefront project, then [CSS Modules][] are supported out of the box without additional configuration. - -This tutorial provides some guidance on using CSS modules in your components. -If you require more in depth information on CSS modules, see the [CSS Modules][] topic or [specification repository][]. - -## Defining and using CSS modules - -CSS modules are CSS files which are imported and treated as JavaScript modules. - -The recommended naming convention for classes is camelCase naming because it looks cleaner when paired with dot notation(e.g. `style.className`). -Kebab-case naming can produce unexpected behavior when accessing the class name using dot notation. -Use bracket notation(e.g. `style['class-name']`) if you intend to use kebab-case. - -Example: `foo.css` - -```css -.root { - padding: 3rem 1rem 1rem; - text-align: center; -} - -.title { - text-transform: uppercase; -} - -.title, -.greeting { - padding-bottom: .5rem; -} - -.spacer { - max-width: 500px; - border-color: #ddd; - border-top: 0; - margin: 36px auto; -} - -.label { - color: #666; - padding-bottom: 8px; - font-style: italic; - font-size: 14px; -} -``` - -Import CSS files as you would a JavaScript module and use dot or bracket notation to access the file name. - -Example: `foo.js` - -```jsx -import React from 'react'; - -import classes from './foo.css'; - -const Foo = props => { - return ( -
    -

    Foo Component

    -
    -

    A child component with propTypes & CSS Modules:

    - -
    - ); -} - -export default Foo; -``` - -## CSS modules in Venia UI components - -Venia UI components let you pass in a `classes` prop with a specific [prop type shape][] to override the class names used to render its elements. - -Example: `myButtonWrapper.css` - -```css -.content { - /* content class style override */ -} - -.root { - /* root class style override */ -} - -.root_highPriority { - /* root_highPriority class style override */ -} - -.root_lowPriority { - /* root_lowPriority class style override */ -} - -.root_normalPriority { - /* root_normalPriority class style override */ -} -``` - -With the CSS modules feature, you can import a CSS file as an object and pass it in as a prop to Venia UI components. -This lets you override the style for the specific classes the component expects. -To find out what classes you can override on a component, see the reference documentation or prop type in the source code. - -For example, Venia's [Button][] component lets you override the classes specified in the `myButtonWrapper.css` exampe file. - -Example: `myButtonWrapper.js` - -```jsx -import React from 'react'; - -import Button from '@magento/venia-ui/lib/components/Button'; - -import buttonOverrides from './myButtonWrapper.css'; - -const MyButtonWrapper = props => { - return ; -}; - -export default MyComponent; -``` - -This component uses the [`useState()` React hook][] to keep track of an internal boolean state value. -It defines a `toggleStatus()` function to toggle this boolean state, which is called when the user clicks the rendered Button component. -When the status value changes, the text on the button also changes. - -### Export component from the index file - -Create a `src/components/MyComponent/index.js` file with the following content to set the default component export for the `MyComponent` directory. - -```js -export {default} from './myComponent' -``` - -## Add component to the storefront - -Add this button to your application's Header component using steps similar to the steps described in the [Modify the site footer][] tutorial. - -## Access global state data - -Use Peregrine state context hooks to access and modify the global application state. -Peregrine provides access to the global application state in slices through its various [context hooks][]. - -For this tutorial, use the `useAppContext()` hook imported from `@magento/peregrine/lib/context/app`. - -When you call this hook, it returns an object containing application-specifc data and an API object containing functions for updating the data specific to this global state slice. - -```diff -- import React, { useState, useCallback } from 'react'; -+ import React, { useCallback } from 'react'; -+ import {useAppContext} from '@magento/peregrine/lib/context/app' - - import Button from "@magento/venia-ui/lib/components/Button"; - - const MyComponent = () => { -- const [booleanStatus, setBooleanStatus] = useState(false); -+ const [appState, appApi] = useAppContext(); -+ -+ const booleanStatus = appState.overlay; -+ -+ const { toggleDrawer } = appApi; - - const toggleStatus = useCallback(() => { -- setBooleanStatus(previousStatus => !previousStatus); -+ toggleDrawer('myComponent'); - }); - - const text = booleanStatus ? 'On' : 'Off'; - - return ; - }; - - export default MyComponent; -``` - -These change swaps the `booleanStatus` value from an internal value to the `overlay` value in the application state slice. -It also updates the `toggleStatus()` function to call `toggleDrawer()` from the application state API. -This function updates the `overlay` value, which is used when rendering the Mask component. - -When you go to your storefront, you will see the button rendered by your component in the header. -Click this button to activate the mask overlay and update the button text. - -Since the button text now depends on a global state value, other components can toggle the text value through global state updates. -Click on the shopping cart icon to activate the mask overlay and see the button text update from "Off" to "On". - -[project setup]: <{%link tutorials/pwa-studio-fundamentals/project-setup/index.md %}> -[state management]: <{%link technologies/basic-concepts/state-management/index.md %}> -[modify the site footer]: <{%link tutorials/pwa-studio-fundamentals/modify-site-footer/index.md %}> - -[`usestate()` react hook]: https://reactjs.org/docs/hooks-reference.html#usestate -[context hooks]: https://github.com/magento/pwa-studio/tree/develop/packages/peregrine/lib/context diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/foo-footer-link.png b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/foo-footer-link.png deleted file mode 100644 index 9c0579404f..0000000000 Binary files a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/foo-footer-link.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/footer-component-selected.png b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/footer-component-selected.png deleted file mode 100644 index efcb88262e..0000000000 Binary files a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/footer-component-selected.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/react-dev-tools.png b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/react-dev-tools.png deleted file mode 100644 index 49e3963c32..0000000000 Binary files a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/react-dev-tools.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/web-dev-tools.png b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/web-dev-tools.png deleted file mode 100644 index 726e72471e..0000000000 Binary files a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/images/web-dev-tools.png and /dev/null differ diff --git a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/index.md b/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/index.md deleted file mode 100644 index 352e78a803..0000000000 --- a/pwa-devdocs/src/tutorials/pwa-studio-fundamentals/modify-site-footer/index.md +++ /dev/null @@ -1,277 +0,0 @@ ---- -title: Modify the Footer component ---- - -One way to customize a storefront is to modify its UI components. -This tutorial provides the steps for modifying Venia's **Footer** component by adding a link to the existing content. - -By the end of this tutorial, you will know how to override different pieces of Venia to add your customizations. - -{: .bs-callout .bs-callout-info} -This tutorial requires you to have a project set up using the steps provided in the [Project Setup][] tutorial. - -## Steps overview - -When modifying any storefront component from the default Venia storefront, follow these basic steps: - -1. Identify the component you want to update and its render chain -1. Make a copy of the target component and the components in its render chain in your project -1. Update dependencies in your project to use the new copies - -## Identify the target component - -The first step in modifying anything in the Venia storefront is to identify the component whose content you want to modify. - -### Using React DevTools - -[React DevTools][] is a browser plugin for React developers. -It gives you the ability to navigate and inspect component nodes in the React DOM tree. - -After you install React DevTools in your browser, open your storefront and your browser's web developer tools. - -{: .bs-callout .bs-callout-info} -For this tutorial, Chrome's web developer tools are used, but these steps can be generally applied to other browsers. - -![Chrome dev tools][] - -In Chrome, the React DevTools is accessed through a dropdown on the top right of the developer tools panel. -Read the React DevTools plugin documentation find out how to access this tool in your browser. - -![React DevTools in Chrome][] - -Use the React DevTools to select content in the footer element to see which component renders it. -For this tutorial, select the **Footer** component. - -![Footer component selected][] - -## Identify the render chain - -The render chain is the path in the React DOM tree that starts in the **App** or a **Root Component** and ends at the target component. -These are the components you need to copy into your project to make modifications. - -Use the React DevTools to navigate the React DOM tree and find the render chain of the target component. -Ignore React context providers and consumers because they are often just used as a content wrapper. - -For this tutorial, the render chain for the Footer component in the Venia storefront is `App -> Main -> Footer`. -You can verify this by looking at the source for the [Main][] and [App][] components. -Main imports and renders the Footer component, and App imports and renders the Main component. - -### Root components - -Static imported components, such as Header, Footer, and side Navigation, have render chains that begin in **App**, but content that is specific to a route have render chains that begin at a **Root Component**. - -Root components are dynamically loaded components associated with a Magento page type or route. -A list of Venia's root components can be found in the [RootComponent][] directory in the PWA Studio project. - -## Create component directories - -If your project does not already have one, create a `components` directory under your `src` directory. -This directory will hold your project's components. - -```sh -mkdir -p src/components -``` - -Next, create directories for each component in the render chain. -These directories will hold copies of the component source code from Venia. - -```sh -mkdir -p src/components/App && \ -mkdir -p src/components/Main && \ -mkdir -p src/components/Footer -``` - -## Copy components - -Make a copy of the components in the render chain from the `node_modules` directory. - -### Copy App component - -The App component is the main entry point for the storefront application. -It imports and renders the Main component, which renders the Footer component. - -```sh -cp node_modules/@magento/venia-ui/lib/components/App/app.js src/components/App -``` - -If you look at the [`index.js` file for Venia's App component][], its default export is not `app.js`. -The default export for this component is `container.js`, which is a container for the `app.js` module, so copy the `container.js` file into your project. - -```sh -cp node_modules/@magento/venia-ui/lib/components/App/container.js src/components/App -``` - -### Copy Main component - -The Main component imports and renders the Header, Footer, and route-specific components. -Copy this component from `node_modules` into your project. - -```sh -cp node_modules/@magento/venia-ui/lib/components/Main/main.js src/components/Main -``` - -### Copy Footer component - -The Footer component is the target component you will modify for this tutorial. -Copy this component from the `node_modules` directory into your project. - -```sh -cp node_modules/@magento/venia-ui/lib/components/Footer/footer.js src/components/Footer -``` - -## Add a link to the Footer - -Open `src/components/Footer/footer.js` and make the following modifications to add a link to the footer element. - -Import **Link** from Venia's driver component. - -```diff - import { useFooter } from '@magento/peregrine/lib/talons/Footer/useFooter'; -+ -+ import { Link } from '@magento/venia-ui/lib/drivers'; - - import { mergeClasses } from '../../classify'; -``` - -Use the Link component to create a link to an internal route defined in the [Add a static route tutorial][]: - -```diff -