mjyocca / sfdx-spa-staticresource-bundler-guide

Guided tutorials & examples of how to implement SPA (Single Page Applications) w/ your salesforce sfdx project

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

☁️ SFDX SPA StaticResource Bundler Guide πŸš€

Guided tutorials/examples of how to implement SPA (Single Page Applications) w/ your salesforce sfdx project.

πŸŽ’ Outline

Additional Docs

πŸ‘‹ Introduction

The point of this guide is showcase strategies across different tools/scaffolding/frameworks, how to bundle and deploy to salesforce. Additionally when possible automate this process πŸ”₯

When building SPA's on salesforce, our main objective is to:

  1. Build our applications in modern javascript/typescript etc.
  2. Run our build tooling to transpile (convert to old syntax), bundle and minify our source code to the force-app/main/default/staticresource/ directory.
  3. Deploy our development/production builds to our salesforce orgs/or package them.

πŸ“ˆ Toolchain Visualized

πŸ”§ Tooling

There are several open source build-tooling options available out there but webpack and rollup seem to be the most predominant/favorabale. If not possible w/ chosen scaffolding can always resort to scripting. In the examples we'll be using webpack but similar results can be accomplished with rollup.

πŸ“ Before our build runs

frontend-app
β”œβ”€β”€ README.md
β”œβ”€β”€ package.json
β”œβ”€β”€ node_modules
β”œβ”€β”€ src
|   β”œβ”€β”€ app.js
|   β”œβ”€β”€ components
|   └── library

app.js Example Source code (react)

class Square extends React.Component {
  render() {
    return <button className="square">{this.props.value}</button>;
  }
}

πŸ“ After our build runs

frontend-app
β”œβ”€β”€ README.md
β”œβ”€β”€ package.json
β”œβ”€β”€ node_modules
β”œβ”€β”€ dist
β”‚   β”œβ”€β”€ 0.bundle.js
β”‚   β”œβ”€β”€ app.bundle.js
|   └── app.css
β”œβ”€β”€ src
|   β”œβ”€β”€ app.js
|   β”œβ”€β”€ components
|   └── library

app.bundle.js Transpiled/Bundled code

var Square = /*#__PURE__*/ function (_React$Component) {
  _inherits(Square, _React$Component);
  var _super = _createSuper(Square);
  function Square() {
    _classCallCheck(this, Square);
    return _super.apply(this, arguments);
  }
  _createClass(Square, [
    {
      key: "render",
      value: function render() {
        return /*#__PURE__*/ React.createElement(
          "button",
          {
            className: "square",
          },
          this.props.value
        );
      },
    },
  ]);
  return Square;
};

☁️ Quickstart - How to apply this to a Salesforce sfdx project

Steps

  • Create a sfdx project
  • Create our frontend project in a new sub-directory
  • Setup the project tooling where we'll point the build destination in our staticresources dir
  • Create a [foldername].resource-meta.xml file for each direct child folder/file inside of our staticresources directory. (Either during the build process or post build)
  • πŸ”₯ Finally deploy those files to your salesforce org πŸ”₯

Step 1: Create a sfdx project

In the terminal type in

sfdx force:project:create --projectname salesforce-project

:filefolder: _Sfdx project we just created

salesforce-project
β”œβ”€β”€ README.md
β”œβ”€β”€ sfdx-project.json
β”œβ”€β”€ .sfdx
β”œβ”€β”€ .vscode
β”‚   β”œβ”€β”€ extensions.json
β”‚   └── settings.json
β”œβ”€β”€ force-app
|   └── main
|       └── default
|           β”œβ”€β”€ aura
|           β”œβ”€β”€ classes
|           β”œβ”€β”€ objects
|           └── staticresources
β”œβ”€β”€ manifest
|   └── package.xml

In order to deploy later on you'll need to authorize your salesforce dev/hub org.

Step 2: Create and setup our frontend project inside of our root salesforce-project

mkdir src

and then change into that new directory

cd src

This is when you can decide if you want to setup a scaffolding/framework of your choosing. For sake of demonstration we'll go w/ a vanilla 🍦 js example.

Create our npm package.json to track our dependencies and add our scripts

npm init -y

Create a index.js file inside of the src directory

/* If want to include polyfills */
import "core-js/stable";
import "regenerator-runtime/runtime";

const app = () => {
  const root = document.createElement("div");
  root.innerHtml = `Hello World`;
  return root;
};
document.body.appendChild(app());

Step 3: Setup our projects tooling with webpack

Install dev dependencies

npm install --save-dev webpack webpack-cli babel-loader @babel/core @babel/preset-env

Install dependencies

npm install --save core-js@3
# Inside of root directory
touch webpack.config.js

Setup our webpack config, can copy and paste from below

webpack.config.js

const path = require("path");

module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "[name].bundle.js",
    // will output all assets that run through webpack in our staticresources directory
    path: path.resolve(__dirname, "force-app/main/default/staticresources/app"),
  },
  /*
    When webpack runs, it'll read the contents of your files. When it encounters either a `import` or a `require` statement, it will run the regex test rule to determine to run each loader
    on the current file. So example below, all js files will run through babel so we can use the latest and greatest syntax features. However you will need add polyfills to work in older browsers
  */
  rules: [
    {
      test: /\.js$/,
      exclude: /node_modules/,
      use: {
        loader: "babel-loader",
        options: {
          presets: [
            "@babel/preset-env",
            {
              useBuiltIns: "usage",
              corejs: 3,
            },
          ],
        },
      },
    },
  ],
};

Modify the package.json (in your src directory) file and add a script

"scripts": {
  "build": "webpack --config webpack.config.js"
}

Step 4: Create our [foldername].resource-meta.xml file

We then place these files and assets in our local sfdx staticresources project directory along w/ a [foldername].resource-meta.xml file.

app.resource-meta.xml

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
  <cacheControl>Public</cacheControl>
  <contentType>application/zip</contentType>
</StaticResource>

This file is needed so salesforce knows how to compress and store them in the salesforce provided cdn to use throughout your visualforce pages and lightning components.


Run the script, either through the terminal or if using vscode can click on npm scripts button

npm run build

πŸ“ What the current project should look like

salesforce-project
β”œβ”€β”€ README.md
β”œβ”€β”€ sfdx-project.json
β”œβ”€β”€ .sfdx
β”œβ”€β”€ .vscode
β”‚   β”œβ”€β”€ extensions.json
β”‚   └── settings.json
β”œβ”€β”€ force-app
|   └── main
|       └── default
|           β”œβ”€β”€ aura
|           β”œβ”€β”€ classes
|           β”œβ”€β”€ objects
|           └── staticresources
|               β”œβ”€β”€ app ** WHERE our Bundled Assets Will Go
|               └── app.resource-meta.xml
β”œβ”€β”€ src
|   β”œβ”€β”€ node_modules
|   β”œβ”€β”€ package.json
|   └── index.js
β”œβ”€β”€ manifest
|   └── package.xml

Step 5: Deploy to your salesforce Org (make sure you authenticated an org)

run in your terminal

sfdx force:source:deploy -p force-app/main/default/staticresources/app

If you wish to automate the above tutorial, take a look at the Vanilla Project Webpack example.

quick note

Staticresources have a 5mb limit per folder and a 250mb limit org wide. With this limitation and to avoid issues down the line, the examples/guides are strutured to only include production/shipping code in the staticresource folders. Read more here.

πŸ”₯ Examples πŸ”₯

If you prefer to set up your own JavaScript toolchain from scratch.

If you prefer lightning-web-components (Open Source) as your frontend framework of choice and create-lwc-app for your project scaffolding πŸ”₯

Coming Soon - Can create a similar scaffolding to create-react-app starting from the vanilla project example. Guide on creating your own project tooling


🍻 Cheers!

Submit a pull request to contribute

or

Submit a issue if you would like to see more examples or update current ones

About

Guided tutorials & examples of how to implement SPA (Single Page Applications) w/ your salesforce sfdx project