diff --git a/tools/workspace-plugin/src/executors/build/executor.spec.ts b/tools/workspace-plugin/src/executors/build/executor.spec.ts index 73cd97294c5e8..4ac6ea1cb3332 100644 --- a/tools/workspace-plugin/src/executors/build/executor.spec.ts +++ b/tools/workspace-plugin/src/executors/build/executor.spec.ts @@ -206,7 +206,8 @@ describe('Build Executor', () => { const styles = useStyles(); return \`

\${greeting} \${user.name} from \${(_user_hometown = user.hometown) === null || _user_hometown === void 0 ? void 0 : _user_hometown.name}

\`; } - " + + //# sourceMappingURL=greeter.js.map" `); expect(readFileSync(join(workspaceRoot, 'libs/proj/lib/greeter.js.map'), 'utf-8')).toMatchInlineSnapshot( `"{\\"version\\":3,\\"sources\\":[\\"../src/greeter.ts\\"],\\"sourcesContent\\":[\\"import { useStyles } from './greeter.styles';\\\\nexport function greeter(greeting: string, user: User): string {\\\\n const styles = useStyles();\\\\n return \`

\${greeting} \${user.name} from \${user.hometown?.name}

\`;\\\\n}\\\\n\\\\ntype User = {\\\\n name: string;\\\\n hometown?: {\\\\n name: string;\\\\n };\\\\n};\\\\n\\"],\\"names\\":[\\"useStyles\\",\\"greeter\\",\\"greeting\\",\\"user\\",\\"styles\\",\\"name\\",\\"hometown\\"],\\"mappings\\":\\"AAAA,SAASA,SAAS,QAAQ,mBAAmB;AAC7C,OAAO,SAASC,QAAQC,QAAgB,EAAEC,IAAU;QAEYA;IAD9D,MAAMC,SAASJ;IACf,OAAO,CAAC,WAAW,EAAEI,OAAO,EAAE,EAAEF,SAAS,CAAC,EAAEC,KAAKE,IAAI,CAAC,MAAM,GAAEF,iBAAAA,KAAKG,QAAQ,cAAbH,qCAAAA,eAAeE,IAAI,CAAC,KAAK,CAAC;AAC1F\\"}"`, @@ -228,7 +229,7 @@ describe('Build Executor', () => { var _user_hometown; const styles = (0, _greeterstyles.useStyles)(); return \`

\${greeting} \${user.name} from \${(_user_hometown = user.hometown) === null || _user_hometown === void 0 ? void 0 : _user_hometown.name}

\`; - } + } //# sourceMappingURL=greeter.js.map " `); @@ -243,7 +244,8 @@ describe('Build Executor', () => { } }, { d: [\\".fe3e8s9{color:red;}\\"] - });" + }); + //# sourceMappingURL=greeter.styles.js.map" `); expect(readFileSync(join(workspaceRoot, 'libs/proj/lib-commonjs/greeter.styles.js'), 'utf-8')) .toMatchInlineSnapshot(` @@ -266,7 +268,7 @@ describe('Build Executor', () => { d: [ \\".fe3e8s9{color:red;}\\" ] - }); + }); //# sourceMappingURL=greeter.styles.js.map " `); @@ -319,34 +321,35 @@ describe('Build Executor', () => { // assert raw styles content matches the original SWC-compiled styles (before Griffel transformation) // ===================== expect(readFileSync(join(workspaceRoot, 'libs/proj/lib/greeter.styles.raw.js'), 'utf-8')).toMatchInlineSnapshot(` - "import { makeStyles } from '@griffel/react'; - export const useStyles = makeStyles({ - root: { - color: 'red' - } - }); - " - `); + "import { makeStyles } from '@griffel/react'; + export const useStyles = makeStyles({ + root: { + color: 'red' + } + }); + + //# sourceMappingURL=greeter.styles.js.map" + `); expect(readFileSync(join(workspaceRoot, 'libs/proj/lib-commonjs/greeter.styles.raw.js'), 'utf-8')) .toMatchInlineSnapshot(` - "\\"use strict\\"; - Object.defineProperty(exports, \\"__esModule\\", { - value: true - }); - Object.defineProperty(exports, \\"useStyles\\", { - enumerable: true, - get: function() { - return useStyles; - } - }); - const _react = require(\\"@griffel/react\\"); - const useStyles = (0, _react.makeStyles)({ - root: { - color: 'red' - } - }); - " - `); + "\\"use strict\\"; + Object.defineProperty(exports, \\"__esModule\\", { + value: true + }); + Object.defineProperty(exports, \\"useStyles\\", { + enumerable: true, + get: function() { + return useStyles; + } + }); + const _react = require(\\"@griffel/react\\"); + const useStyles = (0, _react.makeStyles)({ + root: { + color: 'red' + } + }); //# sourceMappingURL=greeter.styles.js.map + " + `); // ===================== // showcase that babel transformation creates invalid source map - which differs with raw styles source maps produced by SWC-compiled source maps (before Griffel transformation) diff --git a/tools/workspace-plugin/src/executors/build/lib/babel.ts b/tools/workspace-plugin/src/executors/build/lib/babel.ts index 1660890894c85..d2ae76de4d06f 100644 --- a/tools/workspace-plugin/src/executors/build/lib/babel.ts +++ b/tools/workspace-plugin/src/executors/build/lib/babel.ts @@ -104,14 +104,7 @@ async function babel(esmModuleOutput: NormalizedOptions['moduleOutput'][number], sourceFileName: basename(filename), })) /* Bad `transformAsync` types. it can be null only if 2nd param is null(config)*/ as NonNullableRecord; - // FIXME: - // - NOTE: needs to be fixed primarily in {@link 'file://./swc.ts'} as well - // - swc does not add source mapping url when using @swc/core imperative APIs (unlike @swc/cli) (//# sourceMappingURL=) ! - // - we ship transpiled files without proper source mapping since - Wed, 31 May 2023 (the swithc from swc/cli to programatic api useage) - // - @swc/cli does add source mapping because besides invoking swc/core programatically it also contains custom logic to add source mapping url https://github.com/swc-project/pkgs/blob/main/packages/cli/src/swc/compile.ts#L42-L44 - // const resultCode = addSourceMappingUrl(result.code, basename(filename) + '.map'); - - const resultCode = result.code; + const resultCode = addSourceMappingUrl(result.code, basename(filename) + '.map'); if (resultCode === sourceCode) { logger.verbose(`babel: skipped ${filePath}`); diff --git a/tools/workspace-plugin/src/executors/build/lib/swc.ts b/tools/workspace-plugin/src/executors/build/lib/swc.ts index 370868830a8b4..466296237b873 100644 --- a/tools/workspace-plugin/src/executors/build/lib/swc.ts +++ b/tools/workspace-plugin/src/executors/build/lib/swc.ts @@ -1,6 +1,6 @@ import { mkdir, writeFile, copyFile } from 'node:fs/promises'; import { writeFileSync } from 'node:fs'; -import { dirname, join } from 'node:path'; +import { dirname, join, basename } from 'node:path'; import { globSync } from 'fast-glob'; import { isMatch } from 'micromatch'; @@ -64,15 +64,33 @@ export async function compileSwc( // Create directory folder for new compiled file(s) to live in. await mkdir(dirname(compiledFilePath), { recursive: true }); - await writeFile(compiledFilePath, resultCode); - await applyTransforms(compiledFilePath, transforms); + // If a source map was produced, write it and append a sourceMappingURL comment to the JS output + let finalCode = resultCode; if (result.map) { const mapFilePath = `${compiledFilePath}.map`; + + // write the map file await writeFile(mapFilePath, result.map); await applyTransforms(mapFilePath, transforms); + + // append sourceMappingURL to the JS file (use basename so it's a relative filename) + finalCode = addSourceMappingUrl(finalCode, basename(mapFilePath)); } + + await writeFile(compiledFilePath, finalCode); + await applyTransforms(compiledFilePath, transforms); + } +} + +// NOTE: The SWC CLI adds the sourceMappingURL comment itself. Programmatic @swc/core does not, +// so we add it here to mirror the CLI behavior. See swc CLI implementation for reference: +// https://github.com/swc-project/pkgs/blob/main/packages/cli/src/swc/compile.ts#L42-L44 +function addSourceMappingUrl(code: string, sourceMapLocation: string): string { + if (!code.includes('sourceMappingURL=')) { + return code + '\n//# sourceMappingURL=' + sourceMapLocation; } + return code; } type Transform = (filePath: string) => Promise;