This is the pre-release documentation site for the Magento PWA project. To provide feedback or contribute content, check out the pwa-devdocs repository.

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:

{
    "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:
    class Example {
      anInstanceProperty = 52;
    }
    
  • transform-object-rest-spread - Transforms the rest and spread properties for objects to let you use the following syntax:
    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_DOMAIN - 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:

MAGENTO_BACKEND_DOMAIN=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:

require('dotenv').config();

This imports the 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_DOMAIN environment variable:

console.log(process.env.MAGENTO_BACKEND_DOMAIN);

Import Webpack and pwa-buildpack libraries

Append the following content to webpack.config.js to import the Webpack and pwa-buildpack libraries:

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:

const path = require('path');

const themePaths = {
    src: path.resolve(__dirname, 'src'),
    assets: path.resolve(__dirname, 'web'),
    output: path.resolve(__dirname, 'web/js'),
};

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:

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: '[name].js',
            chunkFilename: '[name].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.phase,
                 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:

if (env.phase === "development") {
    config.devServer = await PWADevServer.configure({
        publicPath: process.env.MAGENTO_BACKEND_PUBLIC_PATH,
        backendDomain: process.env.MAGENTO_BACKEND_DOMAIN,
        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.phase 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:

"scripts": {
    "start" : "webpack-dev-server --progress --color --env.phase development",
    "test": "echo \"Error: no test specified\" && exit 1"
}

This allows you to start a development server using the npm start command. The --env.phase development argument sets the mode property to development in the configuration function exported from webpack.config.js.

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.