Skip to content

Commit 2d3fc43

Browse files
authored
ref(nuxt): Build the Nuxt module in-house instead of @nuxt/module-builder (#22190)
Replaces `@nuxt/module-builder` with a plain rollup + tsc setup for the `build/module` output. Rollup bundles the module entry and emits the runtime files one-to-one (preserveModules), tsc emits the declarations, and a small script writes `module.cjs`, `module.json` and `types.d.ts`. The point is to drop a build tool that consumes the TypeScript compiler API, so the package no longer pins us to a specific TS compiler, also streamlines nuxt SDK build step for future changes like rolldown. We still have E2E tests ensuring the module output is consumable by Nuxt apps, so that's not something I would worry about drifting in the future. Stacked on #22186.
1 parent 7edbb8b commit 2d3fc43

9 files changed

Lines changed: 121 additions & 354 deletions

packages/nuxt/build.config.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/nuxt/generate-build-stubs.bash

Lines changed: 0 additions & 19 deletions
This file was deleted.

packages/nuxt/package.json

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@
3333
},
3434
"./module": {
3535
"types": "./build/module/types.d.ts",
36-
"import": "./build/module/module.mjs",
37-
"require": "./build/module/module.cjs"
36+
"import": "./build/module/module.mjs"
3837
},
3938
"./module/plugins": {
4039
"types": "./build/module/runtime/plugins/index.d.ts",
@@ -66,7 +65,6 @@
6665
"local-pkg": "^1.1.2"
6766
},
6867
"devDependencies": {
69-
"@nuxt/module-builder": "^0.8.4",
7068
"@nuxt/nitro-server": "^3.21.6",
7169
"nitro": "^3.0.260311-beta",
7270
"nuxi": "^3.25.1",
@@ -76,7 +74,7 @@
7674
"scripts": {
7775
"build": "run-s build:types build:transpile",
7876
"build:dev": "yarn build",
79-
"build:nuxt-module": "bash ./generate-build-stubs.bash && nuxt-module-build build --outDir build/module",
77+
"build:nuxt-module": "rollup -c rollup.module.config.mjs && tsc -p tsconfig.module.json && node scripts/build-module-meta.mjs",
8078
"build:transpile": "rollup -c rollup.npm.config.mjs && yarn build:nuxt-module",
8179
"build:types": "tsc -p tsconfig.types.json",
8280
"build:watch": "run-p build:transpile:watch",
@@ -87,7 +85,7 @@
8785
"clean": "rimraf build coverage sentry-nuxt-*.tgz",
8886
"lint:fix": "OXLINT_TSGOLINT_DANGEROUSLY_SUPPRESS_PROGRAM_DIAGNOSTICS=true oxlint . --fix --type-aware",
8987
"lint": "OXLINT_TSGOLINT_DANGEROUSLY_SUPPRESS_PROGRAM_DIAGNOSTICS=true oxlint . --type-aware",
90-
"lint:es-compatibility": "es-check es2020 ./build/cjs/*.js && es-check es2020 ./build/esm/*.js --module && es-check es2020 ./build/module/*.cjs && es-check es2020 ./build/module/*.mjs --module",
88+
"lint:es-compatibility": "es-check es2020 ./build/cjs/*.js && es-check es2020 ./build/esm/*.js --module && es-check es2020 ./build/module/*.mjs --module",
9189
"test": "yarn test:unit",
9290
"test:unit": "vitest run",
9391
"test:watch": "vitest --watch",
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { readdirSync } from 'node:fs';
2+
import { join } from 'node:path';
3+
import esbuild from 'rollup-plugin-esbuild';
4+
5+
// The Nuxt module ships two kinds of output that live side by side in `build/module`:
6+
// - `module.mjs`: the module entry, bundled from `src/module.ts`.
7+
// - `runtime/**`: the files Nuxt injects into the consuming app, emitted one-to-one
8+
// (never bundled) because the app's own build re-processes them.
9+
// This config replaces `@nuxt/module-builder` so the package builds with plain rollup + tsc
10+
// and doesn't couple us to a build tool that consumes the TypeScript compiler API.
11+
12+
// Anything that isn't a relative path is provided by the consuming app or Node at runtime
13+
// (this covers `@sentry/*`, `nuxt/app`, `#imports`, node builtins), so it stays external.
14+
const isExternal = id => !id.startsWith('.') && !id.startsWith('/') && !id.startsWith('\0');
15+
16+
const transpile = esbuild({
17+
target: 'es2020',
18+
// Don't read a per-package tsconfig; pin only what affects codegen.
19+
tsconfig: false,
20+
tsconfigRaw: { compilerOptions: { useDefineForClassFields: false } },
21+
sourceMap: false,
22+
});
23+
24+
function runtimeEntrypoints(dir = 'src/runtime', acc = []) {
25+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
26+
const full = join(dir, entry.name);
27+
if (entry.isDirectory()) {
28+
runtimeEntrypoints(full, acc);
29+
} else if (entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts')) {
30+
acc.push(full);
31+
}
32+
}
33+
34+
return acc;
35+
}
36+
37+
export default [
38+
{
39+
input: 'src/module.ts',
40+
output: { file: 'build/module/module.mjs', format: 'esm' },
41+
external: isExternal,
42+
plugins: [transpile],
43+
},
44+
{
45+
input: runtimeEntrypoints(),
46+
output: {
47+
dir: 'build/module/runtime',
48+
format: 'esm',
49+
preserveModules: true,
50+
preserveModulesRoot: 'src/runtime',
51+
entryFileNames: '[name].js',
52+
},
53+
external: isExternal,
54+
plugins: [transpile],
55+
},
56+
];
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { readFileSync, writeFileSync } from 'node:fs';
2+
import { join } from 'node:path';
3+
4+
// Emits the two non-compiled artifacts a Nuxt module needs alongside `module.mjs`,
5+
// replacing what `@nuxt/module-builder` used to generate:
6+
// - `module.json`: module metadata Nuxt reads. Keep the `meta` fields in sync with
7+
// `defineNuxtModule({ meta })` in `src/module.ts`.
8+
// - `types.d.ts`: the type entry referenced by the `./module` export.
9+
10+
const outDir = 'build/module';
11+
const { version } = JSON.parse(readFileSync('package.json', 'utf-8'));
12+
13+
writeFileSync(
14+
join(outDir, 'module.json'),
15+
`${JSON.stringify(
16+
{
17+
name: '@sentry/nuxt/module',
18+
configKey: 'sentry',
19+
compatibility: { nuxt: '>=3.7.0' },
20+
version,
21+
},
22+
null,
23+
2,
24+
)}\n`,
25+
);
26+
27+
writeFileSync(join(outDir, 'types.d.ts'), "export { type ModuleOptions, default } from './module'\n");

packages/nuxt/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"extends": "../../tsconfig.json",
33

4-
"include": ["src/**/*", "build.config.ts"],
4+
"include": ["src/**/*"],
55

66
"compilerOptions": {
77
// package-specific options

packages/nuxt/tsconfig.module.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"include": ["src/module.ts", "src/runtime/**/*"],
4+
"compilerOptions": {
5+
"declaration": true,
6+
"declarationMap": false,
7+
"emitDeclarationOnly": true,
8+
"outDir": "build/module",
9+
"rootDir": "src"
10+
}
11+
}

packages/nuxt/tsconfig.types.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"extends": "./tsconfig.json",
3-
"exclude": ["build.config.ts"],
43
"compilerOptions": {
54
"declaration": true,
65
"declarationMap": true,

0 commit comments

Comments
 (0)