From 7f4b96897bd6ea32999507739ff2a4abf2f703ae Mon Sep 17 00:00:00 2001 From: Gorbachev Egor <7gorbachevm@gmail.com> Date: Wed, 24 Jun 2026 13:44:08 +0700 Subject: [PATCH 1/4] Shorten minified error URL --- .changeset/fix-minified-error-link.md | 5 ++ .gitignore | 1 + packages/mobx/src/errors.ts | 2 +- website/i18n/en.json | 4 ++ website/package.json | 2 + website/scripts/generate-error-docs.mjs | 69 +++++++++++++++++++++++++ website/sidebars.json | 1 + 7 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 .changeset/fix-minified-error-link.md create mode 100644 website/scripts/generate-error-docs.mjs diff --git a/.changeset/fix-minified-error-link.md b/.changeset/fix-minified-error-link.md new file mode 100644 index 0000000000..ac68f01ee4 --- /dev/null +++ b/.changeset/fix-minified-error-link.md @@ -0,0 +1,5 @@ +--- +"mobx": patch +--- + +Shorten minified error URL to reduce production bundle size. diff --git a/.gitignore b/.gitignore index 4170db41f5..4059224142 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ coverage test/babel-tests.js test/typescript/typescript-tests.js dist/ +/docs/errors.md **/.idea/* !/.idea/icon.png !/.idea/vcs.xml diff --git a/packages/mobx/src/errors.ts b/packages/mobx/src/errors.ts index 9a97bdc55c..5c72f2fe93 100644 --- a/packages/mobx/src/errors.ts +++ b/packages/mobx/src/errors.ts @@ -87,7 +87,7 @@ export function die(error: string | keyof typeof errors, ...args: any[]): never typeof error === "number" ? `[MobX] minified error nr: ${error}${ args.length ? " " + args.map(String).join(",") : "" - }. Find the full error at: https://github.com/mobxjs/mobx/blob/main/packages/mobx/src/errors.ts` + }. See http://mobx.js.org/errors` : `[MobX] ${error}` ) } diff --git a/website/i18n/en.json b/website/i18n/en.json index a387a8141d..85973a3fda 100644 --- a/website/i18n/en.json +++ b/website/i18n/en.json @@ -64,6 +64,10 @@ "title": "Decorators", "sidebar_label": "Decorators {🚀}" }, + "errors": { + "title": "MobX error codes", + "sidebar_label": "Error codes" + }, "faq/migrate-to-6": { "title": "Migrating from MobX 4/5" }, diff --git a/website/package.json b/website/package.json index 9e0ffd0f0c..31a1b50685 100644 --- a/website/package.json +++ b/website/package.json @@ -1,7 +1,9 @@ { "scripts": { "examples": "docusaurus-examples", + "prestart": "node scripts/generate-error-docs.mjs", "start": "docusaurus-start", + "prebuild": "node scripts/generate-error-docs.mjs", "build": "docusaurus-build", "publish-gh-pages": "docusaurus-publish", "write-translations": "docusaurus-write-translations", diff --git a/website/scripts/generate-error-docs.mjs b/website/scripts/generate-error-docs.mjs new file mode 100644 index 0000000000..4b34d58491 --- /dev/null +++ b/website/scripts/generate-error-docs.mjs @@ -0,0 +1,69 @@ +#!/usr/bin/env node + +import { readFileSync, writeFileSync } from "node:fs" +import { relative } from "node:path" +import { fileURLToPath } from "node:url" + +const repoRoot = fileURLToPath(new URL("../..", import.meta.url)) +const errorsPath = fileURLToPath(new URL("../../packages/mobx/src/errors.ts", import.meta.url)) +const outputPath = fileURLToPath(new URL("../../docs/errors.md", import.meta.url)) + +function readNiceErrors() { + const source = readFileSync(errorsPath, "utf8") + const match = source.match(/const niceErrors = ([\s\S]*?) as const/) + + if (!match) { + throw new Error(`Could not find niceErrors in ${errorsPath}`) + } + + const objectLiteral = match[1].replace(": PropertyKey", "") + return eval(`(${objectLiteral})`) +} + +function getParamNames(fn) { + const match = fn.toString().match(/^[^(]*\(([^)]*)\)/) + return match ? match[1].split(",").map(name => name.trim()).filter(Boolean) : [] +} + +function renderMessage(message) { + if (typeof message !== "function") { + return message + } + + const args = getParamNames(message).map(name => `{${name}}`) + return message(...args).replace("String", args[0]) +} + +function escapeMarkdownTableCell(value) { + return String(value).replace(/\r?\n/g, "
").replace(/\|/g, "\\|") +} + +function renderDocs(errors) { + const rows = Object.keys(errors) + .sort((left, right) => Number(left) - Number(right)) + .map(code => `| ${code} | ${escapeMarkdownTableCell(renderMessage(errors[code]))} |`) + .join("\n") + + return `--- +title: MobX error codes +sidebar_label: Error codes +hide_title: true +custom_edit_url: https://github.com/mobxjs/mobx/edit/main/packages/mobx/src/errors.ts +--- + + + +# MobX error codes + +In development builds, MobX throws full error messages. Production builds replace known messages with short numeric codes to keep the published bundle small. + +| Code | Message | +| ---- | ------- | +${rows} +` +} + +const docs = renderDocs(readNiceErrors()) +writeFileSync(outputPath, docs) + +console.log(`Generated ${relative(repoRoot, outputPath)} from ${relative(repoRoot, errorsPath)}`) diff --git a/website/sidebars.json b/website/sidebars.json index 107e059688..2d5d8196e8 100755 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -22,6 +22,7 @@ "understanding-reactivity", "subclassing", "analyzing-reactivity", + "errors", "computeds-with-args", "mobx-utils", "custom-observables", From 117a760b7db352311caa661a68a88f36ffd356ce Mon Sep 17 00:00:00 2001 From: Gorbachev Egor <7gorbachevm@gmail.com> Date: Wed, 24 Jun 2026 14:34:29 +0700 Subject: [PATCH 2/4] simpler check --- packages/mobx/src/errors.ts | 2 +- packages/mobx/src/internal.ts | 2 +- website/package.json | 4 +-- ...-error-docs.mjs => generate-error-docs.js} | 26 ++++++------------- 4 files changed, 12 insertions(+), 22 deletions(-) rename website/scripts/{generate-error-docs.mjs => generate-error-docs.js} (65%) diff --git a/packages/mobx/src/errors.ts b/packages/mobx/src/errors.ts index 5c72f2fe93..9ec23a018c 100644 --- a/packages/mobx/src/errors.ts +++ b/packages/mobx/src/errors.ts @@ -1,4 +1,4 @@ -const niceErrors = { +export const niceErrors = { 0: `Invalid value for configuration 'enforceActions', expected 'never', 'always' or 'observed'`, 1(annotationType, key: PropertyKey) { return `Cannot apply '${annotationType}' to '${key.toString()}': Field not found.` diff --git a/packages/mobx/src/internal.ts b/packages/mobx/src/internal.ts index 1317b234c3..48885069a4 100644 --- a/packages/mobx/src/internal.ts +++ b/packages/mobx/src/internal.ts @@ -6,7 +6,7 @@ With this file that will still happen, but at least in this file we can magically reorder the imports with trial and error until the build succeeds again. */ export * from "./utils/global" -export * from "./errors" +export { die } from "./errors" export * from "./utils/utils" export * from "./api/decorators" export * from "./core/atom" diff --git a/website/package.json b/website/package.json index 31a1b50685..3aaa2577f5 100644 --- a/website/package.json +++ b/website/package.json @@ -1,9 +1,9 @@ { "scripts": { "examples": "docusaurus-examples", - "prestart": "node scripts/generate-error-docs.mjs", + "prestart": "node scripts/generate-error-docs.js", "start": "docusaurus-start", - "prebuild": "node scripts/generate-error-docs.mjs", + "prebuild": "node scripts/generate-error-docs.js", "build": "docusaurus-build", "publish-gh-pages": "docusaurus-publish", "write-translations": "docusaurus-write-translations", diff --git a/website/scripts/generate-error-docs.mjs b/website/scripts/generate-error-docs.js similarity index 65% rename from website/scripts/generate-error-docs.mjs rename to website/scripts/generate-error-docs.js index 4b34d58491..8e74076564 100644 --- a/website/scripts/generate-error-docs.mjs +++ b/website/scripts/generate-error-docs.js @@ -1,24 +1,14 @@ #!/usr/bin/env node -import { readFileSync, writeFileSync } from "node:fs" -import { relative } from "node:path" -import { fileURLToPath } from "node:url" +const { writeFileSync } = require("fs") +const { relative, resolve } = require("path") -const repoRoot = fileURLToPath(new URL("../..", import.meta.url)) -const errorsPath = fileURLToPath(new URL("../../packages/mobx/src/errors.ts", import.meta.url)) -const outputPath = fileURLToPath(new URL("../../docs/errors.md", import.meta.url)) +const repoRoot = resolve(__dirname, "../..") +const errorsPath = resolve(repoRoot, "packages/mobx/src/errors.ts") +const outputPath = resolve(repoRoot, "docs/errors.md") -function readNiceErrors() { - const source = readFileSync(errorsPath, "utf8") - const match = source.match(/const niceErrors = ([\s\S]*?) as const/) - - if (!match) { - throw new Error(`Could not find niceErrors in ${errorsPath}`) - } - - const objectLiteral = match[1].replace(": PropertyKey", "") - return eval(`(${objectLiteral})`) -} +globalThis.__DEV__ = true +const { niceErrors } = require(errorsPath) function getParamNames(fn) { const match = fn.toString().match(/^[^(]*\(([^)]*)\)/) @@ -63,7 +53,7 @@ ${rows} ` } -const docs = renderDocs(readNiceErrors()) +const docs = renderDocs(niceErrors) writeFileSync(outputPath, docs) console.log(`Generated ${relative(repoRoot, outputPath)} from ${relative(repoRoot, errorsPath)}`) From 620da5bf7d071a5d6d5020a64aaaecbd94b9be28 Mon Sep 17 00:00:00 2001 From: Gorbachev Egor <7gorbachevm@gmail.com> Date: Wed, 24 Jun 2026 14:39:25 +0700 Subject: [PATCH 3/4] simpler code --- website/scripts/generate-error-docs.js | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/website/scripts/generate-error-docs.js b/website/scripts/generate-error-docs.js index 8e74076564..141ab3e28c 100644 --- a/website/scripts/generate-error-docs.js +++ b/website/scripts/generate-error-docs.js @@ -10,28 +10,26 @@ const outputPath = resolve(repoRoot, "docs/errors.md") globalThis.__DEV__ = true const { niceErrors } = require(errorsPath) -function getParamNames(fn) { - const match = fn.toString().match(/^[^(]*\(([^)]*)\)/) - return match ? match[1].split(",").map(name => name.trim()).filter(Boolean) : [] -} - -function renderMessage(message) { - if (typeof message !== "function") { - return message +function formatMarkdownCell(message) { + let value = message + + if (typeof message === "function") { + // Render dynamic errors with visible placeholders instead of real runtime values + const match = message.toString().match(/^[^(]*\(([^)]*)\)/) + const params = match ? match[1] : "" + const names = params.split(",").map(name => name.trim()).filter(Boolean) + const args = names.map(name => `{${name}}`) + value = message(...args).replace("String", args[0]) } - const args = getParamNames(message).map(name => `{${name}}`) - return message(...args).replace("String", args[0]) -} - -function escapeMarkdownTableCell(value) { + // Keep the generated table valid Markdown return String(value).replace(/\r?\n/g, "
").replace(/\|/g, "\\|") } function renderDocs(errors) { const rows = Object.keys(errors) .sort((left, right) => Number(left) - Number(right)) - .map(code => `| ${code} | ${escapeMarkdownTableCell(renderMessage(errors[code]))} |`) + .map(code => `| ${code} | ${formatMarkdownCell(errors[code])} |`) .join("\n") return `--- From ed467aa500bf651351819abcc73156169bdb4458 Mon Sep 17 00:00:00 2001 From: Gorbachev Egor <7gorbachevm@gmail.com> Date: Wed, 24 Jun 2026 14:48:14 +0700 Subject: [PATCH 4/4] wording --- website/scripts/generate-error-docs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/scripts/generate-error-docs.js b/website/scripts/generate-error-docs.js index 141ab3e28c..aa9db32ec5 100644 --- a/website/scripts/generate-error-docs.js +++ b/website/scripts/generate-error-docs.js @@ -43,7 +43,7 @@ custom_edit_url: https://github.com/mobxjs/mobx/edit/main/packages/mobx/src/erro # MobX error codes -In development builds, MobX throws full error messages. Production builds replace known messages with short numeric codes to keep the published bundle small. +In development builds, MobX throws full error messages. Production builds replace known messages with short numeric codes to keep the published bundle smaller. | Code | Message | | ---- | ------- |