question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Bug] Absolute paths leaking in the bundle

See original GitHub issue

Reporting a bug?

Absolute paths are found in the exported bundles. This is surprising, can leak information about your build system, and will cause webpack longterm caching to not work if you build your site in different directories over time (or on multiple servers).

I believe the caching is two fold, part of it would be to use contenthash and second would be to use relative path for referencing modules.

I know there’s been a lot of work put into using absolute paths over relative paths lately, and I wonder if we could achieve the same result with relative paths instead (unclear what the issue was) ?

Environment

envinfo result
❯ npx envinfo --system --npmPackages 'react*' --binaries --npmGlobalPackages 'react*' --browsers
npx: installed 1 in 1.434s

  System:
    OS: macOS 10.14.5
    CPU: (4) x64 Intel(R) Core(TM) i7-7567U CPU @ 3.50GHz
    Memory: 6.09 GB / 16.00 GB
    Shell: 5.3 - /bin/zsh
  Binaries:
    Node: 8.14.0 - ~/n/bin/node
    Yarn: 1.16.0 - /usr/local/bin/yarn
    npm: 6.9.0 - /usr/local/bin/npm
  Browsers:
    Chrome: 76.0.3809.132
    Firefox: 69.0
    Safari: 12.1.1
  npmPackages:
    react: ^16.9.0 => 16.9.0
    react-dom: ^16.9.0 => 16.9.0
    react-static: ^7.2.0 => 7.2.2
    react-static-plugin-reach-router: ^7.2.0 => 7.2.2
    react-static-plugin-sitemap: ^7.2.0 => 7.2.2
    react-static-plugin-source-filesystem: ^7.2.0 => 7.2.2

Steps to Reproduce the problem

  1. Install a “basic” react-static site
❯ react-static create

? What should we name this project? my-static-site
? Select a template below... basic
Creating new react-static project...
  1. cd my-static-site
  2. yarn build
  3. Look in the dist/main.*.js file and find absolute paths. If you’re on Mac, this mean you’d find /Users/[your-user]/... paths in there.

Another way to see these absolute path is to run yarn serve and look at the sources tab in the devtools. You should see absolute path there: Screen Shot 2019-09-06 at 9 25 55 AM

Expected Behavior

I would expect not to find absolute paths in the bundles.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:3
  • Comments:20 (5 by maintainers)

github_iconTop GitHub Comments

4reactions
warloquecommented, Apr 1, 2020

I’ve played around with node to remove the root paths from the js, json and html in dist/ directory and it finally works.

Beware hardcoded paths in my snippet – it works for my setup (Unix, MacOS and default /dist & /src paths). UPDATED: there has been some bugs on Linux builds, so I added several fixes to handle empty dirs after file moving operations. So, here is my plugin which runs after bundling and exporting during build:

import path from 'path';
import replace from 'replace-in-file';
import jsStringEscape from 'js-string-escape';
import regexStringEscape from 'lodash.escaperegexp';
import fsx from 'fs-extra';

const strCWD = regexStringEscape(jsStringEscape(path.resolve(process.cwd())));
const srcPathParent = './dist/templates';
const srcPath = `${srcPathParent}${strCWD}/src/pages`;
const dstPath = `${srcPathParent}/pages`;

const cleanEmptyFoldersRecursively = (folder) => {

    fsx.readdir(folder, function (err, files) {

        if (files && files.length !== 0) {

            files.forEach(function (fileName) {
                const file = `${folder}/${fileName}`;
                fsx.stat(file, function (err, stats) {
                    if (stats && stats.isDirectory()) {
                        const files = fsx.readdirSync(file);
                        if (files.length > 0) {
                            cleanEmptyFoldersRecursively(file);
                        }
                        if (files.length === 0) {
                            fsx.remove(file);
                            return;
                        }
                    }
                });
            });

        }

    });
}

const traverseDirectory = (dirname, callback) => {
    let directory = [];
    fsx.readdir(dirname, function (err, list) {
        dirname = fsx.realpathSync(dirname);
        if (err) {
            return callback(err);
        }
        let listlength = list.length;
        list.forEach(function (fileName) {
            const file = `${dirname}/${fileName}`;

            fsx.stat(file, function (err, stats) {

                directory.push(file);

                if (stats.isDirectory()) {
                    traverseDirectory(file, function (err, parsed) {
                        directory = directory.concat(parsed);
                        if (!--listlength) {
                            callback(null, directory);
                        }
                    });
                }

                if (stats.isFile()) {
                    if (file.match(/~/)) {
                        try {
                            const fileName = path.basename(file);
                            const fileSufExt = fileName.match(/[0-9a-z]+\.[0-9a-z]+$/);
                            const newName = `functions.${fileSufExt}`;
                            fsx.rename(file, `${srcPathParent}/pages/${newName}`);

                            cleanEmptyFoldersRecursively(dirname);

                            // fix functions.hash.js file links
                            replace({
                                files: path.resolve('./dist/**/*.html'),
                                from: [
                                    /<link.*?\/templates\/pages.*?~.*?\/>/,
                                    /<script.*src=.*\/templates\/pages.*?~.*?~.*?><\/script>/
                                ],
                                to: [
                                    `<link rel="preload" as="script" href="/templates/pages/${newName}"/>`,
                                    `<script defer="" type="text/javascript" src="/templates/pages/${newName}"></script>`
                                ]
                            });
                        } catch (err) {
                            console.error(err);
                        }
                    }
                }

            });
        });
    });
}

const cb = (err, result) => {
    if (err) {
        console.log('error', err);
    }
    return result;
}

export default pluginOptions => ({
    afterBundle: async state => {
        // fix absolute paths in vendors~main.js
        await replace({
            files: path.resolve(`${srcPathParent}/vendors~main*.js`),
            from: new RegExp(strCWD, 'g'),
            to: '.'
        });
        // fix absolute paths in main.js
        await replace({
            files: path.resolve('./dist/main*.js'),
            from: [
                new RegExp(`${strCWD.slice(1)}/src/`, 'g'),
            ],
            to: [
                '',
            ]
        });
        // rewrite path from abc~xyz.[hash].js to /pages/functions.[hash].js
        await replace({
            files: path.resolve('./dist/main*.js'),
            from: /pages\/.*~.*\/.*?[~]\d+\w+/g,
            to: 'pages/functions',
        });
        return state;
    },
    afterExport: async state => {
        await replace({
            files: path.resolve('./dist/**/routeInfo.json'),
            from: new RegExp(`${strCWD}/src/`, 'g'),
            to: '/'
        });

        // replace abs paths in links and scripts (except for abc~xyz file)
        await replace({
            files: path.resolve('./dist/**/*.html'),
            from: [
                new RegExp(`${strCWD}/src/`, 'g'),
            ],
            to: [
                '/',
            ]
        });

        try {
            // console.log(` moving from ${srcPath} into ${dstPath}...`)
            await fsx.move(srcPath, dstPath);
        } catch (err) {
            console.error(err);
        }

        const dir = dstPath;

        try {
            await traverseDirectory(dir, cb);
        } catch (err) {
            console.error(err);
        }

        try {
            await fsx.remove(`${srcPathParent}/Users`);
            await fsx.remove(`${srcPathParent}/home`);
        } catch (err) {
            console.error(err);
        }

        try {
            await cleanEmptyFoldersRecursively(dir);
        } catch (err) {
            console.error(err);
        }

        return state;
    },
});
2reactions
warloquecommented, Apr 1, 2020

@warloque It’s perfect !! 👌🏻

Thanks, but nothing is perfect, you know 😉 Check my code update, hope that will help better)

Read more comments on GitHub >

github_iconTop Results From Across the Web

ASP.NET MVC Bundle with absolute paths - Stack Overflow
I've solved this problem with a custom VirtualPathProvider and a controller. But it is very fragile implementation. You can modify so far as ......
Read more >
393993 - Run mochitests with leak-gauge.pl logging, and make the ...
While not a huge problem, it would make setup easier if we could just bundle it into the mochitest directory (or somewhere else...
Read more >
JDK-6717784 Memory leak in LogManager when ... - Bug ID
When ResourceBundle is subclassed and loaded by a custom class loader, this results in a memory leak because custom class loader is strongly...
Read more >
Possible path leak, unable to purge elements of base
I'm using LVOOP for an event driven state machine (the command pattern). You think it could be related to LVOOP? This error is...
Read more >
How To Datamine Games Such As Fortnite and Valorant ...
(FModel Leaking Tutorial) ... Settings 10:45 - Backups 11:17 - Loading Files 12:20 - Icon Not Loading Bug & Solution 13:35 - Icon...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found