{"id":23763913,"url":"https://github.com/tomashubelbauer/cra-sourcemap","last_synced_at":"2026-03-22T15:30:18.579Z","repository":{"id":53177451,"uuid":"226919313","full_name":"TomasHubelbauer/cra-sourcemap","owner":"TomasHubelbauer","description":"Demonstrating a problem with CRA source maps pointing to wrong locations","archived":false,"fork":false,"pushed_at":"2022-04-14T19:58:10.000Z","size":492,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-12-31T22:13:48.123Z","etag":null,"topics":["cra","create-react-app","source-map","source-maps","sourcemap","sourcemaps"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TomasHubelbauer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-12-09T16:41:54.000Z","updated_at":"2021-04-30T00:26:26.000Z","dependencies_parsed_at":"2022-09-14T09:52:22.578Z","dependency_job_id":null,"html_url":"https://github.com/TomasHubelbauer/cra-sourcemap","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fcra-sourcemap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fcra-sourcemap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fcra-sourcemap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fcra-sourcemap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TomasHubelbauer","download_url":"https://codeload.github.com/TomasHubelbauer/cra-sourcemap/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239937698,"owners_count":19721484,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cra","create-react-app","source-map","source-maps","sourcemap","sourcemaps"],"created_at":"2024-12-31T22:13:50.431Z","updated_at":"2026-03-22T15:30:18.502Z","avatar_url":"https://github.com/TomasHubelbauer.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Create-React-App Sourcemap Issue Repro\n\n1. Scaffold a new TypeScript CRA: `npx create-react-app . --template typescript`\n   (I've tried with JavaScript CRA as well, see below. Spoiler: it's the same.)\n2. `npm run build` to produce the optimized production bundle with sourcemaps\n3. Walk the generated JavaScript files and load their AST using TypeScript:\n\n`index.js`\n```js\nconst klaw = require('klaw');\nconst fs = require('fs-extra');\nconst ts = require('typescript');\nconst sourcemap = require('source-map');\nconst { relative } = require('path');\n\nvoid async function () {\n  for await (const file of klaw('build')) {\n    if (!file.stats.isFile()) {\n      continue;\n    }\n\n    if (!file.path.endsWith('.js')) {\n      continue;\n    }\n\n    let sourceMap;\n    try {\n      sourceMap = await new sourcemap.SourceMapConsumer(String(await fs.readFile(file.path + '.map')));\n    }\n    catch (error) {\n      // Ignore files without sourcemaps\n      continue;\n    }\n\n    const sourceFile = ts.createSourceFile(\n      file.path,\n      String(await fs.readFile(file.path)),\n      ts.ScriptTarget.ES5, // tsconfig.json\n      true\n    );\n\n    const nodes = [sourceFile];\n    do {\n      const node = nodes.shift();\n      nodes.unshift(...node.getChildren());\n      if (node.kind === ts.SyntaxKind.StringLiteral) {\n        const map = sourceMap.originalPositionFor({ line: 1, column: node.pos });\n        if (map.source === null || map.source === '../webpack/bootstrap') {\n          continue;\n        }\n\n        console.log(JSON.stringify(node.text));\n        console.log(`  source: src/${map.source}:${map.line}:${map.column + 1}`);\n        console.log(`  target: ${relative(process.cwd(), file.path)}:1:${node.pos + 1}`);\n      }\n    } while (nodes.length \u003e 0);\n  }\n}()\n```\n\n4. Inspect which string literal nodes in the output are correctly mapped and not:\n\nFrom `output.log`: does the `source` code location lead to the same string\nliteral symbol as the `target` code location (adjusting for JSX pointing to the\ntag name):\n\n```js\n// Irrelevant - no good way to map to the SVG\n\"static/media/logo.5d5d9eef.svg\"\n  source: src/logo.svg:1:44\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:119\n\n// Okay - points to the JSX tag name\n\"div\"\n  source: src/App.tsx:7:5\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:366\n\n// Okay - points to the attribute value string literal\n\"App\"\n  source: src/App.tsx:7:20\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:383\n\n// Okay - points to the JSX tag name\n\"header\"\n  source: src/App.tsx:8:7\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:408\n\n// Okay - points to the attribute value string literal\n\"App-header\"\n  source: src/App.tsx:8:25\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:428\n\n// Okay - points to the JSX tag name\n\"img\"\n  source: src/App.tsx:9:9\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:460\n\n// Okay - points to the attribute value string literal\n\"App-logo\"\n  source: src/App.tsx:9:35\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:485\n\n// Okay - points to the attribute value string literal\n\"logo\"\n  source: src/App.tsx:9:50\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:500\n\n// Okay - points to the JSX tag name\n\"p\"\n  source: src/App.tsx:10:9\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:527\n\n// !!! Incorrect - points to the parent JSX element's tag name\n\"Edit \"\n  source: src/App.tsx:10:9\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:536\n\n// Okay - points to the JSX tag name\n\"code\"\n  source: src/App.tsx:11:16\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:562\n\n// !!! Incorrect - points to the preceeding JSX element's tag name\n\"src/App.tsx\"\n  source: src/App.tsx:11:16\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:574\n\n// !!! Incorrect - points to the parent JSX element's tag name\n\" and save to reload.\"\n  source: src/App.tsx:10:9\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:589\n\n// Okay - points to the JSX tag name\n\"a\"\n  source: src/App.tsx:13:9\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:631\n\n// Okay - points to the attribute value string literal\n\"App-link\"\n  source: src/App.tsx:14:21\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:646\n\n// Okay - points to the attribute value string literal\n\"https://reactjs.org\"\n  source: src/App.tsx:15:16\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:662\n\n// Okay - points to the attribute value string literal\n\"_blank\"\n  source: src/App.tsx:16:18\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:691\n\n// Okay - points to the attribute value string literal\n\"noopener noreferrer\"\n  source: src/App.tsx:17:15\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:704\n\n// !!! Incorrect - points to the parent JSX element's tag name\n\"Learn React\"\n  source: src/App.tsx:13:9\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:727\n\n// Okay - points to the string literal\n\"localhost\"\n  source: src/serviceWorker.ts:14:32\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:754\n\n// Okay - points to the string literal\n\"[::1]\"\n  source: src/serviceWorker.ts:16:34\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:794\n\n// Okay - points to the string literal\n\"root\"\n  source: src/index.tsx:7:50\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:981\n\n// Okay - points to the string literal\n\"serviceWorker\"\n  source: src/serviceWorker.ts:140:7\n  target: build\\static\\js\\main.2cd7b09f.chunk.js:1:990\n```\n\nIt looks as though in JSX, React children which are bare string literals, are\nnot mapped to the correct range in the original source code. Instead of mapping\nonto the range where the literal string resides, the resolved code location\npoints to either the tag name of the parent JSX element if the string literal\nchild is the first child or it is preceeded by another string literal child. In\ncase it is preceeded by a JSX element, the code location resolves to its tag\nname.\n\nI've also tried to see how replacing `pos` with `end` in the script will behave.\nTaking `end` and mapping it back to the original source location should return a\nlocation which is at the end of the string literal, but it turns out, it will\nalways map at the start of the string literal in the case where `pos` worked as\nexpected and will map incorrectly to the exact same positions as `pos` did for\nthe cases which weren't working correctly even with `post`.\n\nThis leads me to believe the source map might not have enough information in it\nto be able to correctly place every location and the best we can get is the\nstart of the symbol when querying any location within the symbol in the output,\nbut this would not be a problem as we can derive the source end locations easily\njust by using the start location and the string literal symbol text length.\nHowever, with this bug, this approach won't work as we're not even getting the\ncorrect start locations.\n\nThe result of the script when ran with `end` instead of `pos` is in\n`output-end.log`.\n\n## JavaScript CRA\n\nTo distinguish whether this is a problem with TypeScript source map generator or\na general problem of CRA, I reran the same experiment on a JavaScript CRA\nscaffold. The script used is the same, I just copied it and ran it in the `js`\ndirectory where I placed the JS CRA scaffold.\n\n```sh\nnpx create-react-app js\ncd js\ncp ../index.js .\nnpm i klaw fs-extra typescript source-map\nnpm run build\nnode index.js\n```\n\nThe result is exactly the same - the incorrect mapping of JSX string literal\nchildren onto the predecesor or parent (if no JSX predecesor) element tag name.\n\n## To-Do\n\n### Help solve the Babel source map issue this ended up being\n\n- [GitHub issue](https://github.com/babel/babel/issues/10869)\n- [Slack thread](https://babeljs.slack.com/archives/C062RC35M/p1619742006022600)\n\n### Work on cra-ast-localize once the issue is resolved\n\nThat's the repo I've originally spotted the issue in.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomashubelbauer%2Fcra-sourcemap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomashubelbauer%2Fcra-sourcemap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomashubelbauer%2Fcra-sourcemap/lists"}