Maybe Don't Use NodeJS

June 24th, 2022

Chipper CI is continuous integration, just for Laravel. Give it a try - free!

Building static assets is slow and resource-intensive.

It's often done in CI pipelines (via Mix, Webpack, and friends) to ensure test pass, even if we don't need the static assets.

Let's see how to avoid building static assets!

Feature Tests

The primary reason to build static assets in a CI pipeline is to generate the mix-manifest.json file.

This allows the mix() helper to work when running Laravel Feature tests. The feature tests make HTTP calls into your app, and thus often render blade templates that use the mix() helper.

If you don’t have a manifest file, an error is thrown!

To generate the manifest file, we typically use npm (or yarn) to install dependencies and run Webpack/Vite tasks:

# Build static assets

npm ci --no-audit
npm run dev

Sidenote: You should almost definitely be committing your package-lock.json file and running npm ci --no-audit instead of npm install!

Skipping NodeJS Tasks

Your public/mix-manifest.json file likely looks something like this:

{
    "/js/app.js": "/js/app.js",
    "/js/foo.js": "/js/foo.js",
    "/css/app.css": "/css/app.css"
}

Or if you're using Vite, your public/build/manifest.json file might look like this:

{
  "resources/css/app.css": {
    "file": "assets/app.74390ffe.js",
    "src": "resources/css/app.css",
    "isEntry": true
  },
  "resources/js/app.js": {
    "file": "assets/app.f40b63e3.js",
    "src": "resources/js/app.js",
    "isEntry": true
  }
}

As noted, without these files, the mix() and vite() helpers will raise an error.

Here's the secret: You don't necessarily need this file to exist for your tests!

Within your test's setUp() method, you can add the following magic:

protected function setUp(): void
{
    parent::setUp();
    
    // If using Mix
    $this->withoutMix();

    // If using Vite
    $this->withoutVite();
}

With that in place, the mix()/vite() helper won't return any errors with a missing manifest file. Your tests can pass without needing to run NodeJS tasks!

Alternative Method

Another thing you can do is create a manifest file for your CI pipeline that you copy for testing.

We can commit a "test" manifest file (perhaps in tests/mix-manifest.json. Then, in our CI pipeline scripts, we copy that "fake" mix file just before running tests:

# What if we created a manifest file just for testing?
# During CI, we can just move it where it needs to go

# Mix/Webpack
cp tests/mix-manifest.json public/mix-manifest.json

# Vite
mkdir -p public/build
cp tests/text-manifest.json public/build/manifest.json

# And then run your tests, no NodeJS required!
php artisan test

This (or any method!) that creates a correct manifest file can help you save a LOT of time and server resources in your CI build pipelines.

With this method, you'll need to keep tests/mix-manifest.json up to date with the correct list of files your configuration generates.

When do you need to build assets?

Here's the most common times you can't use the above, and DO need to build assets in your CI pipelines:

  1. When building a deployable "artifact" (zip file, container image, etc) that needs static assets
  2. Running Node commands (eslint) as part of your test suite
  3. When you are browser testing with something like Laravel Dusk or Cypress

What if I need to build assets?

You can still save precious time even if you need to build your static assets in your CI scripts!

My favorite package for this is Airdrop (by Aaron Francis). It helps you build static assets only if they’ve changed between commits. If they have not changed, you can download them from a file system driver such as S3.

Try out Chipper CI!
Chipper CI is the easiest way to test and deploy your Laravel applications. Try it out - it's free!