Getting Started
About Stencil
Transitioning to Stencil
Installing Stencil
Authentication & Tokens
Running Stencil Locally
Advanced Installation Options
Handlebars and Stencil
Handlebars.js
Handlebars Helpers
Stencil Object Model
Stencil Objects

Implementing a Custom React.js Checkout to Cornerstone using the BigCommerce Checkout SDK

Tutorial Overview

This tutorial will take you through the steps to implement a custom checkout built with React to the Cornerstone Theme. The checkout will utilize BigCommerce’s Checkout SDK. This tutorial assumes Cornerstone 2.4.0 as a starting point.

Checkout Example NOT production ready!

Please note that the provided checkout example is a good starting and reference point, but is NOT production ready. You should not use this custom checkout in production as it stands.

Steps to Implement a Custom React Checkout in Cornerstone

Tutorial Prerequisites

Before beginning this tutorial, you will need to have the Stencil CLI installed.

If you do not yet have Stencil CLI installed, complete the steps in Installing Stencil.

Compatible with Cornerstone versions below 3.0

This tutorial is not currently compatible with Cornerstone versions 3.0.0 and above. If you would like to implement this checkout on your Cornerstone theme using the steps in this tutorial, you need to be developing on a Cornerstone theme below version 3.0.0. The tutorial assumes Cornerstone 2.4.0 as a starting point.

Install Dependencies

The React app used to demonstrate the Checkout SDK has a few additional dependencies. In your theme directory (e.g. /stencil/cornerstone), run the following command:

npm install --save react react-dom react-text-mask classnames accounting babel-preset-react css-loader node-sass sass-loader style-loader @bigcommerce/checkout-sdk

Update webpack.common.js

The React app includes .jsx files which will not be resolved using the default webpack configuration in Cornerstone. Additionally, loaders must be registered for .jsx and .scss files.

Note: Cornerstone 2.0 and above uses Webpack 4 which does not use a webpack.conf.js file like earlier Webpack versions. Instead, we will modify webpack.common.js.

Register .jsx and .scss loaders

In webpack.common.js, add the following objects to the rules array:

{
  test: /\.jsx$/,
  exclude: /node_modules/,
  use: {
      loader: "babel-loader",
      options: {
          presets: ['react'],
      },
  }
},

{
  test: /\.scss$/,
  use:  [
      'style-loader',
      {
          loader: 'css-loader',
          options: {
              modules: true
          }
      },
      'sass-loader'
  ],
},

Next, in webpack.common.js, add the following property to the resolve object:

extensions: ['.js', '.jsx']

Add React Checkout Components to Theme

  1. Clone or download BigCommerce’s Checkout SDK JS Example outside of your theme directory

git clone https://github.com/bigcommerce/checkout-sdk-js-example.git

If the above command fails, and you are accessing GitHub anonymously, give the URL this alternate prefix:

git clone git@github.com:bigcommerce/checkout-sdk-js-example.git

  1. In your theme directory, navigate to /assets/js/ and create a checkout-app directory (i.e. /assets/js/checkout-app)

  2. Copy the contents of /checkout-sdk-js-example/src into your new /assets/js/checkout-app directory

Import Dependencies

Edit /assets/js/app.js and add the following lines toward the beginning with the other import statements:

import React from 'react';
import ReactDOM from 'react-dom';
import Checkout from './checkout-app/Checkout/checkout';

Define a Function to Initialize React

Edit /assets/js/app.js and add the following lines to the end:

window.initReact = function initReact() {
    ReactDOM.render(
        React.createElement(Checkout, null, null),
        document.getElementById('checkout-app')
    );
};

Customize the Checkout Template

  1. Edit /templates/pages/checkout.html and add the following lines between {{{ footer.scripts }}} and {{/partial}}
<script src="{{cdn 'assets/dist/theme-bundle.main.js'}}"></script>
 
<script type="text/javascript" defer>
    // Exported in app.js
    window.initReact();
</script>
  1. In /templates/pages/checkout.html, replace {{{ checkout.checkout_content }}} with the following:

<div id="checkout-app"></div>

Congratulations!

You should now be able to view your example React checkout by running the stencil start command in your theme directory and navigating to your storefront at http://localhost:3000.

You can make further customizations to the checkout by modifying the React components in /assets/js/checkout-app.

Examples of files after completing this tutorial
webpack.common.js
LodashPlugin = require('lodash-webpack-plugin'),
path = require('path'),
webpack = require('webpack');

// Common configuration, with extensions in webpack.dev.js and webpack.prod.js.
module.exports = {
bail: true,
context: __dirname,
entry: {
  main: './assets/js/app.js',
},
module: {
  rules: [
      {
          test: /\.js$/,
          include: /(assets\/js|assets\\js|stencil-utils)/,
          use: {
              loader: 'babel-loader',
              options: {
                  plugins: [
                      'dynamic-import-webpack', // Needed for dynamic imports.
                      'lodash', // Automagically tree-shakes lodash.
                      'transform-regenerator', // Transforms async and generator functions.
                  ],
                  presets: [
                      ['env', {
                          loose: true, // Enable "loose" transformations for any plugins in this preset that allow them.
                          modules: false, // Don't transform modules; needed for tree-shaking.
                          useBuiltIns: true, // Tree-shake babel-polyfill.
                      }],
                  ],
              },
          },
      },
      {
          test: /jquery-migrate/,
          use: 'imports-loader?define=>false',
      },
      {
          test: /\.jsx$/,
          exclude: /node_modules/,
          use: {
              loader: "babel-loader",
              options: {
                  presets: ['react'],
              },
          }
      },
      {
          test: /\.scss$/,
          use:  [
              'style-loader',
              {
                  loader: 'css-loader',
                  options: {
                      modules: true
                  }
              },
              'sass-loader'
          ]
      }
  ],
},
output: {
  chunkFilename: 'theme-bundle.chunk.[name].js',
  filename: 'theme-bundle.[name].js',
  path: path.resolve(__dirname, 'assets/dist'),
},
plugins: [
  new CleanPlugin(['assets/dist'], {
      verbose: false,
      watch: false,
  }),
  new LodashPlugin, // Complements babel-plugin-lodash by shrinking its cherry-picked builds further.
  new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery',
  }),
],
resolve: {
  alias: {
      'jquery-migrate': path.resolve(__dirname, 'node_modules/jquery-migrate/dist/jquery-migrate.min.js'),
      jstree: path.resolve(__dirname, 'node_modules/jstree/dist/jstree.min.js'),
      lazysizes: path.resolve(__dirname, 'node_modules/lazysizes/lazysizes.min.js'),
      pace: path.resolve(__dirname, 'node_modules/pace/pace.min.js'),
      'slick-carousel': path.resolve(__dirname, 'node_modules/slick-carousel/slick/slick.min.js'),
      'svg-injector': path.resolve(__dirname, 'node_modules/svg-injector/dist/svg-injector.min.js'),
      sweetalert2: path.resolve(__dirname, 'node_modules/sweetalert2/dist/sweetalert2.min.js'),
  },
  extensions: ['.js', '.jsx'],
},
};

Additional Resources