Skip to content

adapter-node breaks paths to sourcemap sources by copying files during build #10040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
danieldiekmeier opened this issue May 25, 2023 · 10 comments
Milestone

Comments

@danieldiekmeier
Copy link
Contributor

Describe the bug

When you turn on sourcemaps in Vite, SvelteKit will generate sourcemaps even for the server. This is great! But during the build, @sveltejs/adapter-node moves the generated files, for example from .svelte-kit/output/server/foo.js to .svelte-kit/adapter-node/foo.js, breaking the relative paths to the sources in the sourcemaps.

This is the code that moves the files:

writeServer(dest) {
return copy(`${config.kit.outDir}/output/server`, dest);
}

I noticed this because I wanted to setup Sentry's new SvelteKit integration, but the sourcemaps would just not work. Sentry is actually using sorcery to try to flatten all the sourcemaps from the different steps of the build: https://github.com/getsentry/sentry-javascript/blob/41fef4b10f3a644179b77985f00f8696c908539f/packages/sveltekit/src/vite/sourceMaps.ts#L136-L139

This almost works, except that adapter-node moves the files, thus breaking the chain.

A fix could be to update the source maps while copying them. (But maybe there are better options.)

Reproduction

Repo: https://github.com/danieldiekmeier/reproduction-adapter-node-sourcemaps

pnpm i
pnpm build
diff .svelte-kit/output/server/chunks/index.js.map .svelte-kit/adapter-node/chunks/index.js.map
# nothing will be printed, which is the problem: it's the same file

Logs

No response

System Info

System:
    OS: macOS 13.3.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 303.64 MB / 64.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.13.0 - ~/.asdf/installs/nodejs/18.13.0/bin/node
    Yarn: 1.22.19 - ~/.asdf/installs/nodejs/18.13.0/bin/yarn
    npm: 8.19.3 - ~/.asdf/plugins/nodejs/shims/npm
  Browsers:
    Chrome: 113.0.5672.126
    Edge: 113.0.1774.57
    Firefox: 103.0.2
    Firefox Developer Edition: 113.0
    Safari: 16.4
    Safari Technology Preview: 16.4
  npmPackages:
    @sveltejs/adapter-node: ^1.2.4 => 1.2.4
    @sveltejs/kit: ^1.5.0 => 1.18.0
    svelte: ^3.54.0 => 3.59.1
    vite: ^4.3.0 => 4.3.8

Severity

annoyance

Additional Information

No response

@Lms24
Copy link
Contributor

Lms24 commented May 26, 2023

Hi, Sentry dev 👋

I asked about this a while ago here along with some other source maps related stuff: #9608

We would really appreciate it if this was fixed. Ideally, the source maps from the Node adapter would directly map to the actual sources and not the built files in .svelte-kit. Then we wouldn't have to flatten them at all :)

Thanks!

@iandoesallthethings
Copy link

Adding a +1 on this! It's crazy difficult to track client-side errors without it, and we're building into a custom express server that runs a ton of legacy code, so we can't afford to use anything other than adapter-node.

@iandoesallthethings
Copy link

Since this got rolled back, has anyone seen anything about when they'll reattempt the adapter-node sourcemap fix? Clientside sentry is unusable until that gets resolved :(

@Lms24
Copy link
Contributor

Lms24 commented Jul 20, 2023

A fix could be to update the source maps while copying them. (But maybe there are better options.)

I'm wondering if a simple option might be just changing the output path in the node adapter to match the original directory hierarchy?

@Glench
Copy link

Glench commented Sep 4, 2023

I think this was fixed in #10041

@jindraregal
Copy link

I think this was fixed in #10041

It got reverted in 1.3.1 #10314 so it is still an issue.

@Lms24
Copy link
Contributor

Lms24 commented Feb 13, 2024

We would really appreciate it if this issue was bumped in priority. The current behaviour is blocking some of our users because our source maps flattening approach with sorcery fails sometimes due to faulty source maps in the chain (example: getsentry/sentry-javascript#10589).

My request would be that adapter-node either completely removes the build step or, if not possible otherwise, the source maps emitted by adapter-node just link back to the actual source files. Right now, they link to the intermediate source files in .svelte-kit which is why we need to flatten them. (more context in #9608)

Obviously, it's not ideal that the path to the source files isn't correct at the moment but at least this doesn't fully block our users.

@Cluster2a
Copy link

@Rich-Harris this is stopping us from using sentry in a way so we can read the stack traces.
For enterprise applications, this seems to be a must-have.
Are there any plans to work on this issue?

@jamesbirtles
Copy link

I've just put some effort into getting sourcemaps working for our app. Here's what worked:

  1. Enable sourcemaps in vite.config.ts

    export default defineConfig({
      // ...
      build: {
        sourcemap: true
      }
    })
  2. Build the app

  3. Run the following script to fix the sourcemap paths and flatten them - this seems to be necessary to get node to use the sourcemaps
    (Make sure to npm i --save-dev sorcery)

    fixSourcemaps.cjs
    const { readdir, stat, readFile, writeFile } = require("node:fs/promises");
    const { resolve } = require("node:path");
    const fs = require("node:fs/promises");
    
    async function* walkFiles(dir) {
        const files = await readdir(dir);
        for (const file of files) {
            const path = resolve(dir, file);
            const info = await stat(path);
            if (info.isDirectory()) {
                yield* walkFiles(path);
            } else {
                yield path;
            }
        }
    }
    
    (async () => {
        // Fix source paths being wrong by one directory level
        for await (const file of walkFiles(".svelte-kit/adapter-node")) {
            if (!file.endsWith(".js.map")) {
                continue;
            }
    
            const content = await readFile(file, "utf-8");
            const json = JSON.parse(content);
            json.sources = json.sources.map((source) => {
                if (source.startsWith("../../../")) {
                    return source.slice("../".length);
                }
                return source;
            });
            await writeFile(file, JSON.stringify(json));
        }
    
        // Amazingly horrific hack to avoid sorcery complaining about missing files
        const originalReadFile = fs.readFile;
        fs.readFile = async (...args) => {
            try {
                return await originalReadFile(...args);
            } catch (error) {
                console.warn("ignoring issue reading file", args[0]);
                return "";
            }
        };
    
        // Run sorcery over everything to get ✨ working sourcemaps ✨
        const sorcery = await import("sorcery");
        for await (const file of walkFiles("build/server")) {
            if (!file.endsWith(".js")) {
                continue;
            }
    
            try {
                const chain = await sorcery.load(file);
                if (chain) {
                    await chain.write();
                }
            } catch (err) {
                console.warn("failed to write chain", file, err);
            }
        }
    })();
  4. Run the app with the --enable-source-maps flag

    node --enable-source-maps build/index.js

This seems sufficient for getting errors reporting with their correct source locations

I'm unsure if/how this relates the the original issue - whilst the script I made does patch the sources paths to remove the extra '../', all that seems to really have an affect on is the final rendered source line (i.e. without it will be one directory too high).
The key thing to actually get node to use the sourcemap seems to be to run each js file in build/ through sorcery

Sourcemaps are dark magic to me so i'm not sure what the real end fix is, but these steps have given us useful error messages in production at least.

@ktarmyshov
Copy link

@Lms24 Hi, Lukas,
I know that this is the old issue, I am using sentry and had the same issues but with different adapter (https://github.com/kt-npm-modules/svelte-adapter-azure-swa). I noticed that sveltekit fails to bundle the @sentry/sveltekit for the server part (but does not complain about it). Discovered when used rollup for bundling the server part - rollup cannot resolve the dep (fixed that with using plugin-alias to manyally resolve).

Anyways, after fixing sourcemaps with re-bundling client js files (could be a solution for any other adapter or even for writeClient/writeServer for the builder), Sentry seems to work and pickup sourcemaps for the client, but fails to do so for the backend part. VSCode debugging works just fine and picks up the sourcemaps.

Could you take at the issue on Sentry side?
getsentry/sentry-javascript#16189

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants