homeresume
 
   
🔍

Error tracking with Sentry

February 14, 2023

Error tracking and alerting are crucial in the production environment, proactively fixing the errors leads to a better user experience. Sentry is one of the error tracking services, and it provides alerting for unhandled exceptions. You should receive an email when something wrong happens.

Sentry issues show the error stack trace, device, operating system, and browser information. The project dashboard shows an unhandled exception once it's thrown. This post covers the integration of several technologies with Sentry.

Node.js

  • Create a Node.js project on Sentry

  • Install the package

npm i @sentry/node
  • Run the following script
const Sentry = require('@sentry/node');
Sentry.init({
dsn: SENTRY_DSN
});
test();

Next.js

  • Create a Next.js project on Sentry (version 13 is not yet supported)

  • Run the following commands for the setup

npm i @sentry/nextjs
npx @sentry/wizard -i nextjs

Gatsby

  • Create a Gatsby project on Sentry

  • Install the package

npm i @sentry/gatsby
  • Add plugin in Gatsby config
module.exports = {
plugins: [
// ...
{
resolve: '@sentry/gatsby',
options: {
dsn: SENTRY_DSN
}
}
]
};

React Native

  • Create a React Native project on Sentry

  • Run the following commands for the setup

npm i @sentry/react-native
npx @sentry/wizard -i reactNative -p android
2022

Gatsby blog as PWA (Progressive Web App)

November 26, 2022

Starting with some of the benefits, installed PWAs can bring more user engagement and conversions. On the user side, it brings the possibility to read posts offline. Progressive Web App 101 post covers more details about PWAs.

Prerequisites

  • bootstrapped Gatsby blog
  • installed manifest (gatsby-plugin-manifest) and offline (gatsby-plugin-offline) plugins

Setup

Add plugin configurations to the Gatsby configuration file. The manifest plugin should be loaded before the offline plugin.

Prepare the app icon in 512x512 pixels, and the manifest plugin will generate the icons in all the necessary dimensions. PWA usage can be logged with the UTM link in start_url property.

Runtime caching for static resources (JavaScript, CSS, and page data JSON files) is set to network-first caching, so it retrieves the latest changes before showing them to the user. In case of issues with caching in a local environment, an offline plugin can be disabled.

// gatsby-config.js
const plugins = [
// ...
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `app name`,
short_name: `app name`,
start_url: `/?utm_source=pwa&utm_medium=pwa&utm_campaign=pwa`,
background_color: `#FFF`,
theme_color: `#2F3C7E`,
display: `standalone`,
icon: `src/assets/icon.png`
}
}
];
if (process.env.NODE_ENV !== 'development') {
plugins.push({
resolve: `gatsby-plugin-offline`,
options: {
workboxConfig: {
runtimeCaching: [
{
urlPattern: /(\.js$|\.css$|static\/)/,
handler: `NetworkFirst`
},
{
urlPattern: /^https?:.*\/page-data\/.*\.json/,
handler: `NetworkFirst`
},
{
urlPattern: /^https?:.*\.(png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
handler: `StaleWhileRevalidate`
},
{
urlPattern: /^https?:\/\/fonts\.googleapis\.com\/css/,
handler: `StaleWhileRevalidate`
}
]
}
}
});
}
module.exports = {
// ...
plugins
};

Service worker updates can also be detected. For a better user experience, a user should approve refreshing the page before updating it to the latest version.

// gatsby-browser.js
exports.onServiceWorkerUpdateReady = () => {
const shouldReload = window.confirm(
'This website has been updated. Reload to display the latest version?'
);
if (shouldReload) {
window.location.href = window.location.href.replace(/#.*$/, '');
}
};
exports.onRouteUpdate = async () => {
if (!navigator) {
console.log('Navigator is not defined, skipping service worker registration...');
return;
}
if (!navigator.serviceWorker) {
console.log('Service worker is not supported, skipping registration...');
return;
}
try {
const registration = await navigator.serviceWorker.register('/sw.js');
await registration.update();
} catch (error) {
console.error('Service worker registration failed', error);
}
};

Chronoblog (Gatsby) theme with RSS feed

March 7, 2022

Chronoblog is one of the Gatsby blogging themes. RSS feed can be used to get the latest posts for Github actions, dev.to, etc. The following steps can easily add it. Use a similar approach for other Gatsby themes.

Initial setup

Run the following commands to clone the repository and install the required packages.

npx gatsby new chronoblog-site https://github.com/Chronoblog/gatsby-starter-chronoblog
cd chronoblog-site
npm i gatsby-plugin-feed@2 gatsby-transformer-remark@3 gatsby-source-filesystem

GraphQL setup

Populate GraphQL fields to avoid null errors. Add canonical_url: http://example.com to content links frontmatter-placeholder index.md file.

Gatsby config

Add plugin configurations in gatsby-config.js. Draft content, links, and placeholder post are skipped.

module.exports = {
// ...
plugins: [
// ...
{
resolve: `gatsby-plugin-feed`,
options: {
query: `
{
site {
siteMetadata {
title
description
siteUrl
site_url: siteUrl
}
}
}
`,
feeds: [
{
serialize: ({ query: { site, allMarkdownRemark } }) => {
return allMarkdownRemark.edges.map(edge => {
return Object.assign({}, edge.node.frontmatter, {
description: edge.node.excerpt,
date: edge.node.frontmatter.date,
url: edge.node.frontmatter.canonical_url || edge.node.frontmatter.url,
guid: edge.node.frontmatter.canonical_url || edge.node.frontmatter.url,
custom_elements: [{ "content:encoded": edge.node.html }],
})
})
},
query: `
{
allMarkdownRemark(
filter: {
frontmatter: {
draft: { ne: true },
link: { eq: null },
title: { ne: "Ghost Post" }
},
},
sort: { order: DESC, fields: [frontmatter___date] },
) {
edges {
node {
excerpt
html
fields { slug }
frontmatter {
title
canonical_url
date
}
}
}
}
}
`,
output: "/rss.xml",
title: "RSS Feed",
},
],
},
},
{
resolve: `gatsby-transformer-remark`
},
],
// ...
};

Gatsby node setup

Implement onCreateNode function in gatsby-node.js file

const { createFilePath } = require(`gatsby-source-filesystem`);
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}

Npm scripts setup

Add serve script in package.json

{
// ...
"scripts": {
// ...
"serve": "gatsby serve"
}
}

Demo

Run npm run build && npm run serve. RSS feed should be populated on http://localhost:9000/rss.xml page.