Skip to content
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

Different absolute/relative css image url path resolution between Windows and Linux #822

Closed
jsilveira opened this issue Feb 16, 2021 · 2 comments

Comments

@jsilveira
Copy link

I have a deploy script for a project that compiles .less into a .css containing styles of the form background-image: url('/subfolder/image.png') and a file loader for .png (to hash and output all the linked images). I developed and tested the script in Windows, but when deploying it to Heroku (aws instances) the script failed with errors of the form 'Could not read from file: /subfolder/image.png'. It took me quite a while to debug and narrow down the issue, which I'm guessing has to do with /path considered absolute in Linux but somehow not in Windows?

I understand that technically '/path' is absolute, but in the context of a css file served from /public/ I think this is a pretty common situation. To work around this issue I used a Resolver plugin to postprocess and replace all the paths in the css to the actual absolute paths (I tried absWorkingDir but it didn't help).

The real pain was not being able to reproduce (and anticipate) the error in Windows. I think I managed to make a small self contained test that shows the different behavior on each OS:

(install esbuild in a folder, save code in .js and run)

const fs = require('fs');

try {
  fs.writeFileSync(`${__dirname}/fake.less`, 'fake')
  fs.mkdirSync(`${__dirname}/subfolder`);
  fs.writeFileSync(`${__dirname}/subfolder/image.png`, 'bogus png data')
} catch (err) {
}

const fakePlugin = {
  name: 'lessParser',
  setup(build) {
    build.onLoad({ filter: /\.less$/ }, async (args) => {
      return {
        contents: ".caca{background-image: url('/subfolder/image.png');}",
        loader: 'css'
      };
    });
  }
};

require('esbuild').build({
  entryPoints: [__dirname + '/fake.less'],
  bundle: true,
  plugins: [fakePlugin],
  loader: { '.png': 'file' },
  outfile: `fake.css`,
}).then(() => console.log(`✔ Success`)).catch(console.error);

This tiny example fails in Ubuntu with error Could not read from file: /subfolder/image.png but works fine in Windows.

Maybe this is something dumb and expected, but It caused me some headaches, so I wanted to document it and check it just in case.

@evanw
Copy link
Owner

evanw commented Feb 17, 2021

Yeah unfortunately URLs and paths look the same but have different semantics and it's not possible to derive intent from the source code itself.

I suppose I could prevent absolute paths being interpreted as relative paths on Windows, which would make this case fail on Windows too. I actually wasn't aware of this edge case although I can see now why Windows would do this.

Just to check: is there a reason why you did not write url('subfolder/image.png') or url('./subfolder/image.png') in your source code?

@evanw evanw closed this as completed in 5b346ca Feb 17, 2021
@jsilveira
Copy link
Author

Just to check: is there a reason why you did not write url('subfolder/image.png') or url('./subfolder/image.png') in your source code?

It was part of a set of static css files that were originally served from that top level directory in the domain, and parcel was able to resolve those paths in both platforms, so I guess this never came up.

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

Successfully merging a pull request may close this issue.

2 participants