Cloud Build Process and Artifacts

As part of every deployment, Craft Cloud assembles all the code and configuration required to run your PHP application and build front-end assets.

Everything about the build process is dictated by your repository, and the craft-cloud.yaml config file.

PHP #

Your project’s composer.json and composer.lock files determine what PHP packages are installed. By default, Cloud expects both files to be at the root of your repository—but your Composer root can be customized. If either file is missing, the build will fail.

Cloud installs packages by running composer install.

Node #

Similarly, Cloud looks for package.json and package-lock.json files at the root of your repository (or at a path set in your config file). Unlike the PHP build step, if package-lock.json is missing, this step is skipped (but the deployment will continue).

The builder also requires that you set a node-version in your Cloud config file.

Build Command #

Cloud executes the build script via npm run build after installing the listed packages with npm clean-install. You can change which script is run with the npm-script setting in craft-cloud.yaml—or the directory the command is run in with node-path.

Special environment variables are exposed to your Node build process:

  • CRAFT_CLOUD_CDN_BASE_URL: The root URL of your environment’s storage bucket.
  • CRAFT_CLOUD_BUILD_ID: This build’s UUID. You will receive a new build ID for each deployment—even if they have the same GIT_SHA.
  • GIT_SHA: The current commit hash being built.
  • CRAFT_CLOUD_ARTIFACT_BASE_URL: See Artifact URLs, below.

Artifacts #

At the end of the build step, the contents of the project’s “artifact path” (the web root, by default) are copied to your storage bucket.

You can specify a different artifact-path in craft-cloud.yaml, but when using something other than your web root, files in your web root will no longer be published or accessible. Generally speaking, you should only change the webroot, and let Cloud keep the settings synchronized.

Artifact URLs #

If you need to refer to the final, published URL of a build artifact from your build script, a file it generates, or at runtime, a special CRAFT_CLOUD_ARTIFACT_BASE_URL is provided to your environment (including the Node build container). On Cloud, it will always look something like this:

https://cdn.craft.cloud/{environment-uuid}/builds/{build-uuid}/artifacts

Within that artifacts/ directory, the file structure of your existing artifact path will be preserved. This means that—in most cases—a relative path will work as you’d expect (say, for ES6 modules or CSS @import statements).

There is no need for filename-based cache-busting, as all artifact URLs will change with every build!

The Cloud extension also provides the artifactUrl() Twig function for generating URLs to files published during your build. If you have historically used the siteUrl() or url() functions to link a stylesheet or JavaScript file (or any other static asset) in your web root, use this function instead.

Outside of Cloud, artifactUrl() falls back to your normal @web URL—and anything in your web root will resolve normally. The special @artifactBaseUrl alias mirrors this behavior, and can be used in Project Config—or anywhere else that evaluates aliases:

{# Register a `script` tag to a static asset: #}
{% js '@artifactBaseUrl/dist/js/app.js' %}

{# Equivalent to: #}
<script src="{{ artifactUrl('dist/js/app.js') }}"></script>

If your local development setup serves assets at a different host (like a webpack dev server, running on a different port), you may want to explicitly set the CRAFT_CLOUD_ARTIFACT_BASE_URL variable:

CRAFT_CLOUD_ARTIFACT_BASE_URL="http://my-project.ddev.site:9000/"

This will override the default @web base URL when using the artifactUrl() helper.

Hot-linking Build Artifacts #

In case you need to link to a build artifact (or any other static file uploaded to the CDN) from outside your site, we provide a stable URL to the current build:

https://cdn.craft.cloud/{environment-uuid}/builds/current/artifacts

The current segment takes the place of a specific build ID, and will always point to the most recent successful build.

Reading Files #

Reading the contents of a build artifact from the CDN can incur a performance penalty, but when properly cached, the impact will be minimal.

Only files that are created during a build must be loaded from the CDN. Anything that is already committed to your artifact-path will be available on-disk at runtime.

SVGs

Embedding an SVG generated by your build process with Craft’s svg() Twig function requests a copy from the CDN each time it is called. Consider pre-processing SVGs in a development environment and committing them to Git to make them available on the function’s disk at runtime.

Manifests and Build Hashes

Some front-end build tools write out a “manifest” that maps predictable artifact names (like my-app.js) to a build-specific filename that includes an unpredictable hash or digest (like my-app.656e74f158356.js) as a means of cache-busting stale assets.

This is not necessary on Craft Cloud, as each build’s assets are published to a unique URL.

If you would like to continue to support this workflow, your configuration may require an update to point to the manifest.json file on our CDN instead of by path on the local disk. Use file_get_contents() to load the contents of a remote file into memory, and the Cloud extension’s craft\cloud\Helper::artifactUrl('path/to/manifest.json') to get the build-specific URL.

Users of the Twigpack plugin are protected from performance impacts by its built-in cache. The Asset Rev plugin memoizes manifest files for the duration of a request, but it does not cache them between requests.

Craft Cloud’s static cache can also mitigate latency issues when interacting with remote files.

Applies to Craft Cloud.