From 2d5b8f865e113bd42d310066c4171e8b074991da Mon Sep 17 00:00:00 2001 From: Onur Temizkan Date: Fri, 17 Nov 2023 10:11:16 +0000 Subject: [PATCH] feat(remix): Add Vite support (#495) Adds Vite sourcemaps upload support to Remix wizard. Also: - Runs `npx run reveal` when `entry.client` / `entry.server` files do not exist in the project. - Fixes a bug (using `project.name` instead of `project.slug`) while populating build upload script with the `project` argument. --- CHANGELOG.md | 1 + src/remix/remix-wizard.ts | 66 ++++++++++++++++++++++++++++++--------- src/remix/sdk-setup.ts | 31 ++++++++++++++++++ 3 files changed, 83 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4a171d5..cf2fdf56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 3.16.5 +- feat(remix): Add Vite support (#495) - fix(wizard): Update wizard API data type and issue stream url creation (#500) ## 3.16.4 diff --git a/src/remix/remix-wizard.ts b/src/remix/remix-wizard.ts index b095145c..8853f693 100644 --- a/src/remix/remix-wizard.ts +++ b/src/remix/remix-wizard.ts @@ -22,11 +22,14 @@ import { instrumentRootRoute, isRemixV2, loadRemixConfig, + runRemixReveal, } from './sdk-setup'; import { debug } from '../utils/debug'; import { traceStep, withTelemetry } from '../telemetry'; import { isHydrogenApp } from './utils'; import { DEFAULT_URL } from '../../lib/Constants'; +import { findFile } from '../utils/ast-utils'; +import { configureVitePlugin } from '../sourcemaps/tools/vite'; export async function runRemixWizard(options: WizardOptions): Promise { return withTelemetry( @@ -55,7 +58,7 @@ async function runRemixWizardWithTelemetry( // We expect `@remix-run/dev` to be installed for every Remix project await ensurePackageIsInstalled(packageJson, '@remix-run/dev', 'Remix'); - const { selectedProject, authToken, sentryUrl } = + const { selectedProject, authToken, sentryUrl, selfHosted } = await getOrAskForProjectData(options, 'javascript-remix'); await installPackage({ @@ -67,24 +70,47 @@ async function runRemixWizardWithTelemetry( const isTS = isUsingTypeScript(); const isV2 = isRemixV2(remixConfig, packageJson); + const viteConfig = findFile('vite.config'); await addSentryCliConfig({ authToken }, rcCliSetupConfig); - await traceStep('Update build script for sourcemap uploads', async () => { - try { - await updateBuildScript({ - org: selectedProject.organization.slug, - project: selectedProject.slug, - url: sentryUrl === DEFAULT_URL ? undefined : sentryUrl, - isHydrogen: isHydrogenApp(packageJson), - }); - } catch (e) { - clack.log - .warn(`Could not update build script to generate and upload sourcemaps. + if (viteConfig) { + await traceStep( + 'Update vite configuration for sourcemap uploads', + async () => { + try { + await configureVitePlugin({ + orgSlug: selectedProject.organization.slug, + projectSlug: selectedProject.slug, + url: sentryUrl, + selfHosted, + authToken, + }); + } catch (e) { + clack.log + .warn(`Could not update vite configuration to generate and upload sourcemaps. + Please update your vite configuration manually using instructions from https://docs.sentry.io/platforms/javascript/guides/remix/sourcemaps/`); + debug(e); + } + }, + ); + } else { + await traceStep('Update build script for sourcemap uploads', async () => { + try { + await updateBuildScript({ + org: selectedProject.organization.slug, + project: selectedProject.slug, + url: sentryUrl === DEFAULT_URL ? undefined : sentryUrl, + isHydrogen: isHydrogenApp(packageJson), + }); + } catch (e) { + clack.log + .warn(`Could not update build script to generate and upload sourcemaps. Please update your build script manually using instructions from https://docs.sentry.io/platforms/javascript/guides/remix/sourcemaps/`); - debug(e); - } - }); + debug(e); + } + }); + } await traceStep('Instrument root route', async () => { try { @@ -96,6 +122,16 @@ async function runRemixWizardWithTelemetry( } }); + traceStep('Reveal missing entry files', () => { + try { + runRemixReveal(isTS); + } catch (e) { + clack.log.warn(`Could not run 'npx remix reveal'. + Please create your entry files manually`); + debug(e); + } + }); + await traceStep('Initialize Sentry on client entry', async () => { try { await initializeSentryOnEntryClient(dsn, isTS); diff --git a/src/remix/sdk-setup.ts b/src/remix/sdk-setup.ts index aa01fede..45bdb92e 100644 --- a/src/remix/sdk-setup.ts +++ b/src/remix/sdk-setup.ts @@ -8,6 +8,7 @@ import type { ProxifiedModule } from 'magicast'; import * as fs from 'fs'; import * as path from 'path'; import * as url from 'url'; +import * as childProcess from 'child_process'; // @ts-expect-error - clack is ESM and TS complains about that. It works though import clack from '@clack/prompts'; @@ -36,6 +37,32 @@ export type PartialRemixConfig = { }; const REMIX_CONFIG_FILE = 'remix.config.js'; +const REMIX_REVEAL_COMMAND = 'npx remix reveal'; + +export function runRemixReveal(isTS: boolean): void { + // Check if entry files already exist + const clientEntryFilename = `entry.client.${isTS ? 'tsx' : 'jsx'}`; + const serverEntryFilename = `entry.server.${isTS ? 'tsx' : 'jsx'}`; + + const clientEntryPath = path.join(process.cwd(), 'app', clientEntryFilename); + const serverEntryPath = path.join(process.cwd(), 'app', serverEntryFilename); + + if (fs.existsSync(clientEntryPath) && fs.existsSync(serverEntryPath)) { + clack.log.info( + `Found entry files ${chalk.cyan(clientEntryFilename)} and ${chalk.cyan( + serverEntryFilename, + )}.`, + ); + } else { + clack.log.info( + `Couldn't find entry files in your project. Trying to run ${chalk.cyan( + REMIX_REVEAL_COMMAND, + )}...`, + ); + + clack.log.info(childProcess.execSync(REMIX_REVEAL_COMMAND).toString()); + } +} function insertClientInitCall( dsn: string, @@ -192,6 +219,10 @@ export async function updateBuildScript(args: { buildCommand, instrumentedBuildCommand, ); + } else { + throw new Error( + "`build` script doesn't contain a known build command. Please update it manually.", + ); } await fs.promises.writeFile(