How to add Sentry to your Vue.js app and integrate it into GitLab CI/CD

Here at Soplaya, we have many projects to handle and monitor, both public and internal tools and we want to be sure that they meet our standard for performance and bug-free.
Our frontend apps are written both in VueJS, Angular, and React so we needed to create a common ground in order to easily maintain our custom CI/CD pipeline.
In this guide, we will see all the steps you need to follow in order to configure your Vue.js project to integrate Sentry to track bugs and performance. You will also learn how to properly create Sentry Releases and automatically upload javascript/typescript Source Map to easily map the transpiled code to your source code.
An Angular and React tutorial will be release in the incoming weeks so don’t worry!
Here’s the list of things you need to do to achieve this result:
- Install Sentry
- Initialize and configure Sentry to track bug and performance
- Import Sentry into Vue.js lifecycle
- Update your CI/CD Pipeline
- Bonus: Track the user
Install Sentry
First of all, you need to create a new Sentry project in order to get your Data Source Name (DSN). Think about it like your Project ID on Sentry.
Now you need to install the npm packages needed by Sentry
npm install --save @sentry/vue @sentry/tracing
Initialize and configure Sentry to track bug and performance
In our case, we want to track bugs and performance only if we’re not in the development/local environment.
First of all, as you can see we use a lot of env variables. Here’s an example of our .env.production
file used for the production build
NODE_ENV=production
VUE_APP_ENVIRONMENT=production
VUE_APP_API_URL=https://YOUR_WEBSITE_URL
VUE_APP_SENTRY_DSN=###REPLACE_WITH_YOUR_SENTRY_DSN###
Other env
variables are initialized in our vue.config.js
but you could directly load those values directly in the sentry.ts
file.
Here’s what you need to add to your vue.config.js
process.env.VUE_APP_NAME = require('./package.json').name;
process.env.VUE_APP_VERSION = require('./package.json').version;
As you can see we’re taking the App Name and App Version (used to create the Sentry release name) directly from our package.json
. You will understand this in the next steps.
Now let’s take a deep dive into the Sentry SDK configuration:
- environment: this option specifies in which environment your app will be released. It will allow you to filters performance/bugs on the Sentry website.
- release: here you are specifying which will be the release name of the app. Releases in Sentry must be unique across your whole organization. That’s why we’re using a pattern like
app-name@version-number
. The release name must match the same release name used on your CI/CD script that will create a release with your source maps. - dsn: this is your unique Sentry Project ID. It will be the same for every environment.
- tracingSampleRate: this is an option for the performance. We’re just saying that in production we want to track only the performance of 25% of all the sessions (1 = 100%).
- trackComponents: enable this option if you want to also track child components and see more details about the rendering process
- logErrors: Sentry will call original Vue’s logError function as well, we think that this option should only be enabled on staging env.
- attachProps: Sentry will send all Vue components’ props for logging purpose
- attachStacktrace: stack traces are automatically attached to all messages logged
Import Sentry into Vue.js lifecycle
Perfect, our Sentry SDK has been initialized and configured correctly.
If you need to configure more options, you can take a look directly at the official Sentry guide for Vue. We just scratched the surface of what you can do with it.
This step is really straightforward, we just need to import sentry.ts
in order to correctly initialize the Sentry SDK after we have loaded our Vue app.
So just open themain.ts
of your Vue project and let’s import it
import '@/sentry';
Ok, this is the bare minimum, if we would, we could already deploy our application, and Sentry would perfectly work, tracing bugs and monitoring performance.
BUT. There’s a catch! All the stack traces would have the transpiled code and not the typescript’s one. And that’s a big no-no because we couldn’t easily understand where’s the problem and how to fix it. Without the source map attached to our release is like trying to read obfuscated code and we can assure you that’s not a pleasant feeling.
Update your CI/CD Pipeline
This is the hard part. Take a good sip of your brewed coffee because you really need to focus. Now we’re going to automate our build, release and deploy process on the GitLab Pipeline.
Our pipeline will be divided into three stages:
- build: where we’re building our Vue project
- post-build: where we’re going to create a Sentry release and upload our source map
- deploy: where we’re going to deploy our source code on our AWS infrastructure. We won't explain this step but we can tell you that internally we’re using AWS CDK to do it. Our stack is a mix of Route53, CloudFront, and S3 like every SPA app deployed on AWS.
First thing first, we need to generate our build with source maps. Those source maps (for security reasons) should not be included in your JavaScript file. We just need to generate them, upload them, and then delete them before deploying the source code.
To generate those source map we need to edit our vue.config.js
and tell to Webpack to generate source map and expose them as “hidden”
module.exports = {
chainWebpack: (config) => {
config.devtool(process.env.NODE_ENV === 'development' ? 'eval-source-map' : 'hidden-source-map')
},
css: {
sourceMap: true
},
}
If you want, you can have a look at the documentation to know all the options Webpack is exposing. In our case for both staging
and production
env we are using the hidden-source-map
options:
Same as source-map, but doesn’t add a reference comment to the bundle. Useful if you only want SourceMaps to map error stack traces from error reports, but don’t want to expose your SourceMap for the browser development tools.
The next step is to tell our GitLab Pipeline what to do during each stage.
Open your .gitlab-ci.yml
and configure it like this
image: node:14stages:
- build
- post-build
- deploybuild-production:
stage: build
before_script:
- npm config set prefix /usr/local
- npm install
script:
- npm run buildwebsite:production
artifacts:
expire_in: 10 mins
paths:
- dist/
only:
- masterpost-build-production:
stage: post-build
script:
- npm install -g @sentry/cli --unsafe-perm
- export PKG_NAME=$(node -p "require('${CI_PROJECT_DIR}/package.json').name")
- export PKG_VERSION=$(node -p "require('${CI_PROJECT_DIR}/package.json').version")
- export SENTRY_RELEASE_VERSION="${PKG_NAME}@${PKG_VERSION}"
- export SENTRY_AUTH_TOKEN=$SENTRY_GIT_AUTH_TOKEN
- export SENTRY_ORG=$SENTRY_GIT_ORG
- export SENTRY_PROJECT=$SENTRY_GIT_PROJECT
- echo "Create a new release $SENTRY_RELEASE_VERSION"
- sentry-cli releases new $SENTRY_RELEASE_VERSION
- sentry-cli releases set-commits --auto $SENTRY_RELEASE_VERSION
- sentry-cli releases files $SENTRY_RELEASE_VERSION upload-sourcemaps $CI_PROJECT_DIR/dist
- sentry-cli releases finalize $SENTRY_RELEASE_VERSION
- echo "Finalized release for $SENTRY_RELEASE_VERSION"
only:
- masterdeploy-production:
stage: deploy
before_script:
- npm config set prefix /usr/local
- npm install -g aws-cdk
- npm install
script:
- rm $CI_PROJECT_DIR/dist/**/*.map || true
- npm run buildcdk:production
- npm run deploycdk:productiononly:
- master
Let’s focus on each individual stage to understand what each command does. I’m going to assume that you have at least a minimum understanding of GitLab CI/CD.
Stage: build
In this stage, we are going to build our SPA. The buildwebsite:production
is just an alias for this command vue-cli-service build
. This is the standard command to create a production release of your Vue app.
This command will generate the distribution release of your application under the /dist
folder. In that folder, you will find also all the .map
files that contain the source maps we need to upload on Sentry.
The next important step is to tell GitLab that we want to store across all the stages an artifact pointing to our /dist
folder. That artifact will be temporarily available for the next 10 minutes, after that time it will be automatically deleted.
Stage post-build-production
In this step we’re going to create a Sentry release and upload the app’s source map attaching them to this specific release.
From the Sentry Release documentation:
A release is a version of your code deployed to an environment. When you notify Sentry about a release, you can easily identify new issues, regressions, whether an issue is resolved in the next release, and apply source maps.
Releases also offer significant additional features when you fully configure Sentry SDK:
- Determine the issues and regressions introduced in a new release
- Predict which commit caused an issue and who is likely responsible
- Resolve issues by including the issue number in your commit message
- Receiving email notifications when your code gets deployed
In order to use the sentry-cli
in your pipeline, you need to create an Auth Token on Sentry. That token must have these scopes:
- project:read
- project:releases
- org:read
The next thing to do is to create three GitLab env variables to safely store the token and some other info that will be required in our pipeline. So go into your GitLab project page and create those variables from Project > Settings > CI/CD > Variables
. We need to define these variables:
- SENTRY_GIT_PROJECT: it must have the same name as your app’s name used to create the release.
- SENTRY_GIT_ORG: it will store the Organization Slug you will find on your Sentry org profile. It’s a unique ID used to identify this organization.
- SENTRY_GIT_AUTH_TOKEN: it will store the value of the Sentry Auth Token you have just created.
Perfect, we’re now ready to set up all the local variables we need, install the sentry-cli
, create the release and upload the source maps. We think that those CLI commands are pretty much self-explanatory but if you need some clarifications just hit us with some comments!
Stage deploy-production
In this section, the most important thing we need to do is to delete those source maps we generated because we don’t want to deploy our website with source maps publicly available.
In order to delete them, you just need to do rm $CI_PROJECT_DIR/dist/**/*.map || true
The buildcdk:production
and deploycdk:production
are scripts that just build our CDK pipeline and deploy our website creating or updating an AWS Cloud Formation.
All the CDK build processes will be part of different blog posts that will be released in the upcoming weeks with a fully working example!
Bonus: Track the user
Ok so now we have everything we need to monitor our performance and squash all those nasty bugs as soon as they are caught by Sentry. The next step is to track (with the consent) the user’s session in order to know who’s having the problem.
That’s really easy, you just need to add this little snippet of code as soon as you have the user’s info:
Sentry.setUser({
id: String(user.id),
username: user.username,
email: user.email,
});
What’s next?
Stay tuned because we are also going to release the same guide for both Angular and React!
I hope that you have enjoyed the blog post, if you want to know more on how we are doing frontend, backend, and DevOps on Soplaya, just follow our Soplaya TechBlog.