Add a new environment variable
Environment variables provide values that may vary across different instances of the same project. The value of this variable can vary between development, staging, and production environments.
Background
In PWA Studio storefront projects, the .env
file in the project's root directory lists the environment variables and their values.
For example, the MAGENTO_BACKEND_URL
environment variable tells your storefront project which Adobe Commerce or Magento Open Source instance it uses during runtime.
These variables are available to your Node scripts, but for security reasons, PWA Studio limits which variables your frontend code can access.
This tutorial teaches you how to create a package which provides a React component that uses an environment variable.
Tasks overview
- Initialize the project
- Create the PlaceholderImage component
- Create and register the intercept file
- Define the intercept file
- Test on a local instance
Initialize the project
Use npm init
or yarn init
to create a new JavaScript package project for this tutorial.
Since this is a standalone project, you do not need to create this inside a storefront project.
Edit the package.json
file so it looks like the following:
Copied to your clipboard{"name": "PlaceholderImage","version": "1.0.0","license": "MIT","peerDependencies": {"@magento/pwa-buildpack": "^7.0.0","@magento/venia-ui": "^5.0.0","react": "^16.14.0"}}
Create the PlaceholderImage component
Create a React component that renders an image from an image placeholder service source provided by an environment variable.
Copied to your clipboardmkdir -p src/components/PlaceholderImage && touch src/components/placeholderImage.js
Inside the placeholderImage.js
, add the following content:
Copied to your clipboardimport React from "react";const PlaceholderImage = (props) => {const { width = 300, height = 300 } = props;const urlTemplate = process.env.IMAGE_PLACEHOLDER_SERVICE_URL;if (!urlTemplate) {console.error("Image placeholder service not defined!");return null;}const finalUrl = urlTemplate.replace("${w}", width).replace("${h}", height);return <img src={finalUrl} />;};export default PlaceholderImage;
The PlaceholderImage component uses the value of the IMAGE_PLACEHOLDER_SERVICE_URL
environment variable as a template for the final image source url.
It replaces instances of ${w}
and ${h}
in the template with the width
and height
prop values.
Most image placeholder services let you specify the image dimensions in the url but in different ways.
For example, a 300x400 image request can look like <url>/300/400
or <url>/300x400
.
This template approach adds support for these different services by letting you specify what the final URL looks like.
Make the component importable
To use this component in other projects, you must export it from this package, so
make the following modifications to the package.json
file:
Copied to your clipboard{"name": "PlaceholderImage","version": "1.0.0","license": "MIT",+ "main": "src/components/PlaceholderImage/placeholderImage.js","peerDependencies": {"@magento/pwa-buildpack": "^7.0.0","@magento/venia-ui": "^5.0.0","react": "^16.14.0"}}
Create and register the intercept file
You can create the intercept file anywhere in your project.
For this tutorial, create this file under src/targets
.
Copied to your clipboardmkdir -p src/targets && touch src/targets/intercept.js
Set the value for pwa-studio.targets.intercept
in your project's package.json
file to tell the build process where to find the intercept file.
Copied to your clipboard{"name": "PlaceholderImage","version": "1.0.0","license": "MIT","main": "src/components/PlaceholderImage/placeholderImage.js","peerDependencies": {"@magento/pwa-buildpack": "^7.0.0","@magento/venia-ui": "^5.0.0","react": "^16.14.0"- }+ },+ "pwa-studio": {+ "targets": {+ "intercept": "src/targets/intercept"+ }+ }}
Define the intercept file
The intercept file is where you tap into PWA Studio's extensibility framework and add your modifications.
In your intercept file, add the following content:
Copied to your clipboardmodule.exports = (targets) => {const buildpackTargets = targets.of("@magento/pwa-buildpack");buildpackTargets.envVarDefinitions.tap((defs) => {defs.sections.push({name: "PlaceholderImage settings",variables: [{name: "IMAGE_PLACEHOLDER_SERVICE_URL",type: "str",desc: "Service URL for image placeholders",},],});});buildpackTargets.specialFeatures.tap((featuresByModule) => {featuresByModule["PlaceholderImage"] = {esModules: true,};});};
When this file runs, it taps into the envVarDefinitions
target from the available targets in @magento/pwa-buildpack
and passes in an intercept function.
The intercept function appends a new definition to the core environment variable definitions, which allows frontend code access to the IMAGE_PLACEHOLDER_SERVICE_URL
environment variable.
Test on a local instance
Install this package in a local storefront project to use the PlaceholderImage component.
Copied to your clipboardyarn add --dev link:/path/to/your/project
This adds a devDependencies
entry to your storefront project's package.json
that looks like the following:
Copied to your clipboard"@storybook/react": "~5.2.6",+ "PlaceholderImage": "link:/path/to/your/project","apollo-cache-persist": "~0.1.1",
Create environment variable entry
In your project's .env
file, create an entry for IMAGE_PLACEHOLDER_SERVICE_URL
.
Copied to your clipboardIMAGE_PLACEHOLDER_SERVICE_URL=http://www.loremflickr.com/${w}/${h}
The PlaceholderImage component uses this value to compute the source when it renders the image.
Create a demo page
Create a demo page component to render the ImagePlaceholder component.
Copied to your clipboardmkdir -p src/components/PlaceholderImageDemo && touch src/component/PlaceholderImageDemo/placeholderImageDemo.js
Inside placeholderImageDemo.js
, add the following content:
Copied to your clipboardimport React from "react";import PlaceholderImage from "PlaceholderImage";const PlaceholderImageDemo = () => {return <PlaceholderImage width={200} height={300} />;};export default PlaceholderImageDemo;
Add a static route
If you used the project scaffolding tool in PWA Studio 8.0.0 or above, your project will have a local-intercept.js
file.
If you do not have this file, use the same earlier steps to create and register the intercept file.
Inside your storefront's intercept file, add the following content to add a new static route for your demo page:
Copied to your clipboardfunction localIntercept(targets) {targets.of("@magento/venia-ui").routes.tap((routes) => {routes.push({name: "Placeholder Image demo page",pattern: "/placeholder-image-demo",exact: true,path: require.resolve("./src/components/PlaceholderImageDemo/placeholderImageDemo.js"),});return routes;});}module.exports = localIntercept;
Check out the page
Now, when you start your project, you can navigate to /placeholder-image-demo
and see the PlaceholderImage component in action.