Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): get Env from API endpoint #678

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open

feat(web): get Env from API endpoint #678

wants to merge 13 commits into from

Conversation

xFJA
Copy link
Collaborator

@xFJA xFJA commented Jan 9, 2025

Checklist

  • My change requires a documentation update, and I have done it.
  • I have added tests to cover my changes.
  • I have filled out the description and linked the related issues.

Description

The environment variables on the client side are now obtained from an api endpoint when the app initializes. This way, you should be able to change their values without redeploying for future deployment changes.

Related Issue (Optional)

Closes #87

Copy link

changeset-bot bot commented Jan 9, 2025

🦋 Changeset detected

Latest commit: a84d3d6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@blobscan/web Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

vercel bot commented Jan 9, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
blobscan-staging ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jan 28, 2025 4:51am
5 Skipped Deployments
Name Status Preview Comments Updated (UTC)
blobscan-docs ⬜️ Ignored (Inspect) Visit Preview Jan 28, 2025 4:51am
blobscan-gnosis ⬜️ Ignored (Inspect) Visit Preview Jan 28, 2025 4:51am
blobscan-holesky ⬜️ Ignored (Inspect) Visit Preview Jan 28, 2025 4:51am
blobscan-mainnet ⬜️ Ignored (Inspect) Visit Preview Jan 28, 2025 4:51am
blobscan-sepolia ⬜️ Ignored (Inspect) Visit Preview Jan 28, 2025 4:51am

@xFJA xFJA changed the title feat: get Env from API endpoint feat(web): get Env from API endpoint Jan 9, 2025
Copy link

codecov bot commented Jan 9, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 88.50%. Comparing base (2b252b1) to head (a84d3d6).
Report is 10 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #678      +/-   ##
==========================================
+ Coverage   87.79%   88.50%   +0.71%     
==========================================
  Files         158      160       +2     
  Lines       10871    10919      +48     
  Branches     1164     1201      +37     
==========================================
+ Hits         9544     9664     +120     
+ Misses       1327     1255      -72     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

github-actions bot commented Jan 9, 2025

📦 Next.js Bundle Analysis for @blobscan/web

This analysis was generated by the Next.js Bundle Analysis action. 🤖

⚠️ Global Bundle Size Increased

Page Size (compressed)
global 318.58 KB (🔴 +72.96 KB)
Details

The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.

Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis

If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!

New Pages Added

The following pages were added to the bundle from the code in this PR:

Page Size (compressed) First Load % of Budget (350 KB)
/block_neighbor 251 B 318.83 KB 91.09%
/stats 348.26 KB 666.84 KB 190.53%

Eight Pages Changed Size

The following pages changed size from the code in this PR compared to its base branch:

Page Size (compressed) First Load % of Budget (350 KB)
/ 355.55 KB 674.13 KB 192.61% (🟢 -3.94%)
/address/[address] 30.17 KB 348.75 KB 99.64% (🟢 -3.87%)
/blob/[hash] 30.51 KB 349.09 KB 99.74% (🟢 -3.41%)
/blobs 81.5 KB 400.08 KB 114.31% (🟡 +13.91%)
/block/[id] 15.65 KB 334.23 KB 95.49% (🟢 -3.77%)
/blocks 78.65 KB 397.23 KB 113.49% (🟡 +13.74%)
/tx/[hash] 18.85 KB 337.43 KB 96.41% (🟡 +1.60%)
/txs 78.05 KB 396.63 KB 113.32% (🟡 +11.70%)
Details

Only the gzipped size is provided here based on an expert tip.

First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.

Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis

The "Budget %" column shows what percentage of your performance budget the First Load total takes up. For example, if your budget was 100kb, and a given page's first load size was 10kb, it would be 10% of your budget. You can also see how much this has increased or decreased compared to the base branch of your PR. If this percentage has increased by 20% or more, there will be a red status indicator applied, indicating that special attention should be given to this. If you see "+/- <0.01%" it means that there was a change in bundle size, but it is a trivial enough amount that it can be ignored.

Copy link
Member

@PJColombo PJColombo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good.

I left some comments with some changes we should do.

packages/env/index.ts Outdated Show resolved Hide resolved
apps/web/sentry.client.config.ts Outdated Show resolved Hide resolved
apps/web/sentry.client.config.ts Outdated Show resolved Hide resolved
apps/web/src/pages/api/env/index.ts Outdated Show resolved Hide resolved
packages/env/index.ts Outdated Show resolved Hide resolved
apps/web/src/pages/api/env/index.ts Outdated Show resolved Hide resolved
apps/web/src/pages/api/env/index.ts Outdated Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a suggested change we could follow in order to export a client env vars schema that we can use later to enforce typing in the exposed env object in the Env provider

import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";

// See booleanSchema from packages/zod/src/schemas.ts
// We need to redefine it because we can't import ts files from here
const booleanSchema = z
  .string()
  .refine((s) => s === "true" || s === "false")
  .transform((s) => s === "true");

const networkSchema = z.enum([
  "mainnet",
  "holesky",
  "sepolia",
  "gnosis",
  "chiado",
  "devnet",
]);

const clientEnvVars = {
  PUBLIC_BEACON_BASE_URL: z.string().url().default("https://beaconcha.in/"),
  PUBLIC_BLOBSCAN_RELEASE: z.string().optional(),
  PUBLIC_EXPLORER_BASE_URL: z.string().url().default("https://etherscan.io/"),
  PUBLIC_NETWORK_NAME: networkSchema.default("mainnet"),
  PUBLIC_SENTRY_DSN_WEB: z.string().url().optional(),
  PUBLIC_POSTHOG_ID: z.string().optional(),
  PUBLIC_POSTHOG_HOST: z.string().default("https://us.i.posthog.com"),
  PUBLIC_SUPPORTED_NETWORKS: z
    .string()
    .default(
      '[{"label":"Ethereum Mainnet","href":"https://blobscan.com/"},{"label":"Gnosis","href":"https://gnosis.blobscan.com/"},{"label":"Holesky Testnet","href":"https://holesky.blobscan.com/"},{"label":"Sepolia Testnet","href":"https://sepolia.blobscan.com/"}]'
    ),
  PUBLIC_VERCEL_ANALYTICS_ENABLED: booleanSchema.default("false"),
  PUBLIC_VERCEL_GIT_COMMIT_SHA: z.string().optional(),
};

export const clientEnvVarsSchema = z.object(clientEnvVars);

export const env = createEnv({
  /**
   * Specify your server-side environment variables schema here. This way you can ensure the app isn't
   * built with invalid env vars.
   */
  server: {
    DATABASE_URL: z.string().url(),
    FEEDBACK_WEBHOOK_URL: z.string().optional(),
    NODE_ENV: z.enum(["development", "test", "production"]),
    METRICS_ENABLED: booleanSchema.default("false"),
    TRACES_ENABLED: booleanSchema.default("false"),
    ...clientEnvVars,
  },

  /**
   * Destructure all variables from `process.env` to make sure they aren't tree-shaken away.
   */
  runtimeEnv: {
    DATABASE_URL: process.env.DATABASE_URL,
    FEEDBACK_WEBHOOK_URL: process.env.FEEDBACK_WEBHOOK_URL,
    METRICS_ENABLED: process.env.METRICS_ENABLED,
    NODE_ENV: process.env.NODE_ENV,
    TRACES_ENABLED: process.env.TRACES_ENABLED,

    PUBLIC_BEACON_BASE_URL: process.env.PUBLIC_BEACON_BASE_URL,
    PUBLIC_BLOBSCAN_RELEASE: process.env.PUBLIC_BLOBSCAN_RELEASE,
    PUBLIC_EXPLORER_BASE_URL: process.env.PUBLIC_EXPLORER_BASE_URL,
    PUBLIC_NETWORK_NAME: process.env.PUBLIC_NETWORK_NAME,
    PUBLIC_SENTRY_DSN_WEB: process.env.PUBLIC_SENTRY_DSN_WEB,
    PUBLIC_POSTHOG_ID: process.env.PUBLIC_POSTHOG_ID,
    PUBLIC_POSTHOG_HOST: process.env.PUBLIC_POSTHOG_HOST,
    PUBLIC_SUPPORTED_NETWORKS: process.env.PUBLIC_SUPPORTED_NETWORKS,
    PUBLIC_VERCEL_ANALYTICS_ENABLED:
      process.env.PUBLIC_VERCEL_ANALYTICS_ENABLED,
    PUBLIC_VERCEL_GIT_COMMIT_SHA: process.env.PUBLIC_VERCEL_GIT_COMMIT_SHA,
  },
  skipValidation: !!process.env.CI || !!process.env.SKIP_ENV_VALIDATION,
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would import the clientEnvVarsSchema in the Env provider to parse the returned json coming from the api

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@PJColombo
Copy link
Member

One more thing: don't forget to update the docs

Copy link
Member

@PJColombo PJColombo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some more comments.

/**
* Specify your client-side environment variables schema here.
* For them to be exposed to the client, prefix them with `NEXT_PUBLIC_`.
*/
client: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should avoid redeclaring all the env vars in the client field again, which is what we're trying to avoid by exposing them from the server.

Upon further inspection, I realise that there're some of them we should keep defined at build time. Those are:

  • NEXT_PUBLIC_BLOBSCAN_RELEASE: This one we actually set it when building the docker image.
  • NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA: This is a default variable that Vercel uses so we can't remove the prefix

@@ -26,34 +44,11 @@ export const env = createEnv({
DATABASE_URL: z.string().url(),
FEEDBACK_WEBHOOK_URL: z.string().optional(),
NODE_ENV: z.enum(["development", "test", "production"]),
METRICS_ENABLED: booleanSchema.default("false"),
TRACES_ENABLED: booleanSchema.default("false"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the env vars we want to expose now from the server:

  • PUBLIC_BEACON_BASE_URL
  • PUBLIC_EXPLORER_BASE_URL
  • PUBLIC_NETWORK_NAME
  • PUBLIC_POSTHOG_HOST
  • PUBLIC_POSTHOG_ID
  • PUBLIC_SENTRY_DSN_WEB
  • PUBLIC_SUPPORTED_NETWORKS

We remove the prefix NEXT_ to prevent nextjs from injecting them during build time

Copy link
Member

@PJColombo PJColombo Jan 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, remember to update the docs with the new renamed env vars and any reference to them (i.e. deploy_vercel_env.sh , turbo.json, etc)

Comment on lines +47 to +48
METRICS_ENABLED: z.boolean().default(false),
TRACES_ENABLED: z.boolean().default(false),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rollback to booleanSchema here

It's necessary because the true or false values are set as string and we need to parse them to their boolean counterparts

@@ -0,0 +1,33 @@
import type { NextApiRequest, NextApiResponse } from "next";

import { env } from "@blobscan/env";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should send the env vars located in the env.mjs file

Also, let's remove the @blobscan/env package from the package.json as those are not used in the web app


switch (method) {
case "GET": {
const parsedEnv = clientEnvVarsSchema.safeParse(env);
Copy link
Member

@PJColombo PJColombo Jan 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to parse this again as env object is already typified.


const clientEnv = Object.fromEntries(
Object.entries(parsedEnv.data)
.filter(([key]) => key.startsWith("NEXT_"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we apply the change mentioned above about removing the NEXT_ prefix we should update this to filter en vars starting with PUBLIC_ instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Show network name
3 participants