webpack-encore: Incorrect paths for fonts
My context: I host my webiste under a given path. I do not use symfony but we don’t care here. I used (of course) webpack-encore to manage my assets. It works well except for fonts because of my extra path.
My website is hosted under /my-path. I generate my stylesheets using sass. Stylesheets paths are composed of my base path and the path found in manifest.json. I’ve got for example /my-path/build/css/style.css I use font-awesome to add web-fonts. The url() in the generated stylesheets is url(/build/fonts/fontawesome-webfont.eot); and so one. I don’t know (just start to investigate) how to fix it. I usually used webpack (without webpack-encore) and webpack used a relative path to fonts from stylesheets instead of an absolute path; something like:
@font-face {
font-family: 'FontAwesome';
src: url(./fonts/fontawesome-webfont.eot);
src: url(./fonts/fontawesome-webfont.eot?#iefix&v=4.7.0) format("embedded-opentype"), url(./fonts/fontawesome-webfont.woff2) format("woff2"), url(./fonts/fontawesome-webfont.woff) format("woff"), url(./fonts/fontawesome-webfont.ttf) format("truetype"), url(./images/fontawesome-webfont.svg#fontawesomeregular) format("svg");
font-weight: normal;
font-style: normal;
}
And I’ve got
@font-face {
font-family: 'FontAwesome';
src: url(/my/public/conf/path/build/fonts/fontawesome-webfont.eot);
src: url(/my/public/conf/path/build/fonts/fontawesome-webfont.eot?#iefix&v=4.7.0) format("embedded-opentype"), url(/my/public/conf/path/build/fonts/fontawesome-webfont.woff2) format("woff2"), url(/my/public/conf/path/build/fonts/fontawesome-webfont.woff) format("woff"), url(/my/public/conf/path/build/fonts/fontawesome-webfont.ttf) format("truetype"), url(/my/public/conf/path/build/images/fontawesome-webfont.svg#fontawesomeregular) format("svg");
font-weight: normal;
font-style: normal;
}
Any idea to solve that issue is appreciate. If you have any question, don’t hesitate.
About this issue
- Original URL
- State: open
- Created 7 years ago
- Comments: 16 (7 by maintainers)
Thanks for the details!
Try this:
The issue is that your
setPublicPath
isn’t correct. Because you’re under a sub-directory, your true public path is/my-path/themes/default/build
. You need to tell webpack your actual, true public path because (in some cases - specifically something called code splitting) - webpack needs to be able to make AJAX requests back for assets (and it uses the publicPath to know where those live).This should fix your problem - it will dump something like this:
It shouldn’t matter to us whether these paths are absolute or relative - so I wouldn’t worry about that detail. Webpack just makes sure that these paths are correct - as long as you give it the correct public path 😃.
Let me know if this fixes things!
Sorry for the noise on this one but I just figured out a solution to the problem I described above using Symfony’s Json manifest versioning strategy.
After retrieving the versioned path from the manifest, Symfony’s
PathPackage
checks if it is an absolute URL or it starts with ‘/’ and if true returns the value as is. If false, the method prefixes the correct base path to the path and returns that instead: https://github.com/symfony/symfony/blob/d8ee14f9a075f8a45c261e810c4caa441ae72ca3/src/Symfony/Component/Asset/PathPackage.php#L60-L67In practical terms, say for example we have a Symfony app hosted under
/var/www/my-app
which we access viahttp://local.domain/my-app/web
and we have the following config in our webpack.config.js:We run
yarn run encore dev
which generates our manifest file with an entry like so:In a twig template, a call to
asset('build/css/style.css')
will output/build/css/style.css
because it starts with a ‘/’ but this actually requestshttp://local.domain/build/css/style.css
which does not exist.Removing the ‘/’ from the beginning of the publicPath forces Symfony to add the correct base path so our call to
asset('build/css/style.css')
now outputs/my-app/build/css/style.css
which is the correct path.Passing a non-absolute or non ‘/’ prefixed value to setPublicPath currently throws an error: https://github.com/symfony/webpack-encore/blob/799720602aab2069f827704e4a6d672d03d38d76/lib/WebpackConfig.js#L122-L127
To get around this I’m using the configureManifestPlugin method like so:
This only fixes the issue when using Symfony and its manifest based versioning strategy so I’m not sure what the implications of removing the thrown error in setPublicPath would be to other non-Symfony apps.
Any movement on this? We run multiple Symfony installs under sub-directories e.g:
http://example.org/site-1/web/app_dev.php http://example.org/site-2/web/app_dev.php
We’re finding it hard to use Encore with this set up for the reasons discussed above. I added the following to my webpack.config.js:
This fixes the issue with paths referenced in code but the manifest.json still starts each file with
/assets
, so it tries to load the non-existent URL http://example.org/assets/asset.png instead of http://example.org/site-1/web/assets/asset.pngMaybe a solution to be independant of the URL of you site and if your application is a subdirectoy. I can run the symfony 5.x demo with webpack ( the awefont are loaded)
In your weebpack.config.js file replace
By:
I tried setting the output path to
public/build
and the public path tobuild
. It does fix the manifest.json, but then the urls of the fonts referenced in my css begin withbuild/fonts/...
which resolves tohttp://mysite.local/build/build/fonts/...
. Is there some way to force the font urls tofont/...
?Edit: I tried using
useRelativePath
with no luck, but addingconfig.module.rules[3].options.publicPath = './'
works for now, in all environments, thanks Ryan.Hmm, interesting…
I wonder if we could update Encore to use relative paths internally. I mean, logically, it makes sense to output a CSS file with a relative path to the fonts - webpack knows where both are placed. Here’s an issue that’s somewhat related: https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27
I would need to do some playing…
Until then, the hack would be to change this key manually. It would look something like this:
The
3
key should be the key to this loader. But, as this is a bit of a hack, that could change in future releases. Longer term, this should get a more proper solution - i.e. using relative paths (if possible) or adding a decent hook 😃.