We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
If you are setting up error tracking for the JavaScript assets in your Phoenix app, you’ll need a source map to enable readable stack traces. In the following, I’m setting this up with Sentry for error tracking and GitHub Actions for CI/CD, but you can easily adapt this to any vendor.
Generating the source maps
With Phoenix 1.7 you generate the source maps by setting the --sourcemap
flag for esbuild
in config/config.exs
:
config :esbuild,
version: "0.17.11",
my_app_web: [
args:
~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/* --sourcemap=external),
cd: Path.expand("../assets", __DIR__),
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
]
In the above, I use --sourcemap=external
flag to generate the source map but importantly not include the reference in our .js
file. If you are fine with exposing the source map to the public you can just use --sourcemap
and be done with it; the browser can show the full stack trace and your error tracker might be able to automatically pick it up.
In my case, I want to keep the source map to myself, so I have to move it out of the assets directory in my build stage so it will not be included in my release build.
Add the following commands in the Dockerfile
right after the assets are compiled with mix assets.deploy
:
# ...
# Compile assets
RUN mix assets.deploy
# Move source maps out of assets
RUN mkdir ./sourcemaps
RUN mv apps/my_app_web/priv/static/assets/*.js.map ./sourcemaps
# ...
With these commands I’m moving the source map files out of priv/static/assets
to a place that will not be included in my release.
Upload the source maps
I’m using Github Actions for my CI/CD and will be using the Sentry Release Github Action task to upload the source map. This means that I first need to extract the source maps from the build.
Here we add a new stage named sourcemaps
to our Dockerfile
just before our final release stage:
# ...
# sourcemaps is a target used as remote context to push source maps to sentry
FROM scratch AS sourcemaps
COPY --from=builder /app/sourcemaps/ /
# Start a new build stage so that the final image will only contain
# the compiled release and other runtime necessities
FROM ${RUNNER_IMAGE}
# ...
The only thing we do in this stage is to copy the generated source maps so we can pull them out of the build to the host. We can pull them out of the build by running docker build . --output ./sourcemaps --target sourcemaps
.
Now we can set up Github Actions to upload the source maps when we build the release:
# ...
- name: Build and push image
id: docker-build
uses: docker/build-push-action@v4
with:
cache-from: type=gha
cache-to: type=gha,mode=max
# push: true
# tags: ...
# ...
- name: Output source maps
uses: docker/build-push-action@v4
with:
target: sourcemaps
cache-from: type=gha
cache-to: type=gha,mode=max
outputs: type=local,dest=./sourcemaps
- name: Create Sentry release
uses: getsentry/action-release@v1
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ vars.SENTRY_ORG }}
SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }}
with:
version: ${{ github.sha }}
sourcemaps: ./sourcemaps
We are using the Build and Push docker images GHA task to first build and push our release image. After that, we output the source maps to the ./sourcemaps
directory on our GHA host. Now the Sentry Release Github Actions task can pick them up and upload them.
Note that we are caching the layers so we won’t rebuild the image when running the ouput source maps task after the build and push.
Hi, I'm Dan Schultzer, I write in this blog, work a lot in Elixir, maintain several open source projects, and help companies streamline their development process