webpack-encore
webpack-encore copied to clipboard
Incorrect paths for fonts
Hi :)
I have comeback of known issue https://github.com/symfony/webpack-encore/issues/88 in new version of Encore :) So far I used the same solution as https://github.com/symfony/webpack-encore/issues/88#issuecomment-327773492
webpackConfig.module.rules[2].options.publicPath = './';
webpackConfig.module.rules[3].options.publicPath = './';
but this option is not valid anymore. I tried to modify config using
.configureLoaderRule('fonts', (loaderRule) => {
})
but there's not much to do here
{
test: /\.(woff|woff2|ttf|eot|otf)$/,
type: 'asset/resource',
generator: { filename: 'fonts/[name].[hash:8][ext]' },
parser: {}
}
Do you have any idea how to do this correctly?
Temporary working (but with warning from Encore about public path) solution:
Encore
.setOutputPath('web/build/')
.setPublicPath('.')
.setManifestKeyPrefix('.')
.configureManifestPlugin((options) => {
options.publicPath = './build/';
})
// ...
Doesn't work with .enableVersioning()
Hey @giero!
Is the problem only that the paths are wrong in manifest.json? Or is there some other problem? It could be related to #907 if it's just about manifest.json.
Cheers!
Reffering to https://github.com/symfony/webpack-encore/issues/88#issuecomment-327773492 we have the same case - multiple Symfony instances under sub-directories e.g:
http://example.org/site-1/web/app.php
http://example.org/site-2/web/app.php
Our current Encore config looks like this:
Encore
.setOutputPath('web/assets/')
.setPublicPath('/assets')
and maybe it's important
.splitEntryChunks()
.configureSplitChunks((splitChunks) => {
splitChunks.chunks = 'all';
splitChunks.cacheGroups = {
css: {
test: /\.(css|sass|scss|less)$/,
name: 'styles',
chunks: 'all',
},
};
})
to aggregate all style files into single css file.
Production entrypoints (with versioning) looks like this
{
"entrypoints": {
"attribute/index": {
"js": [
"/assets/runtime.5b7a9943.js",
"/assets/styles.b54955b2.js",
"/assets/0.cf60d32b.js",
"/assets/attribute/index.1561a3ba.js"
],
"css": [
"/assets/styles.55053e81.css"
]
},
and some examples from manifest.json
{
...
"assets/attribute/index.js": "/assets/attribute/index.1561a3ba.js",
"assets/styles.js": "/assets/styles.b54955b2.js",
"assets/styles.css": "/assets/styles.f6a7beab.css",
...
"assets/fonts/fontawesome-webfont.woff2?v=4.7.0": "/assets/fonts/fontawesome-webfont.20fd1704.woff2",
...
}
Everithing is ok so far, but in styles.css we need relative fonts/images/icons path ... because it looks like this:
url(/assets/fonts/glyphicons-halflings-regular.be810be3.woff2) format("woff2")
So
const config = Encore.getWebpackConfig();
config.module.rules[2].options.publicPath = './';
config.module.rules[3].options.publicPath = './';
module.exports = config;
was a "hack" to fix that css paths - after that we have
url(fonts/glyphicons-halflings-regular.be810be3.woff2) format("woff2")
And now, with Asset Modules
I have to find working solution to fix those paths.
I am not sure if this is a bug. This works fine, as long as the application is not running in a subdirectory.
In this case, since the styles.css
and fonts
are in the web/assets/
directory, that's why the path to fonts should be relative. The question is whether at the moment it is possible to force the path relativity in the css file (maybe it's not a matter of Encore itself but the less/scss configuration).
Yea, I understand. It's a matter of having relative paths in the final CSS files. I don't know if that's possible - it's not something I've looked into recently. Sorry I can't be more helpful! This would require some deep research.
After hours of trial and error I have found working (but not very best I suppose) solution. But maybe someone could come up with their own solution based on that.
My goals:
- generate single styles.css (from all in-project css/less/scss files) file in Encore's
outputPath
- gather all font files in
outputPath/fonts
- gather all image files in
outputPath/image
- (the most important) have all URLs for fonts/images as RELATIVE inside styles.css file - this is because we have single build and project may be in different sub-directories on clients server.
Point 1. can be simply done by
.splitEntryChunks()
.configureSplitChunks((splitChunks) => {
splitChunks.cacheGroups = {
css: {
test: /\.(css|sass|scss|less)$/,
name: 'styles',
chunks: 'all',
},
};
})
But for the others the solution is ... "do not use Asset Modules" ...
My configuration is based on:
https://webpack.js.org/guides/asset-modules/
https://webpack.js.org/loaders/file-loader/
and ... .configureFontRule
/ .configureImageRule
comments ...
.configureFontRule(
{ type: 'javascript/auto' },
(rule) => {
rule.loader = 'file-loader';
rule.options = { outputPath: 'fonts', name: '[name].[ext]', publicPath: './fonts/' };
}
)
.configureImageRule(
{ type: 'javascript/auto' },
(rule) => {
rule.loader = 'file-loader';
rule.options = { outputPath: 'images', name: '[name].[ext]', publicPath: './images/' };
}
)
After all of this every font/image is in its directory in public path and my URLs for fonts in styles.css
look like this
@font-face {
font-family: "Glyphicons Halflings";
src: url(./fonts/glyphicons-halflings-regular.eot);
src: url(./fonts/glyphicons-halflings-regular.eot?#iefix) format("embedded-opentype"), url(./fonts/glyphicons-halflings-regular.woff2) format("woff2"), url(./fonts/glyphicons-halflings-regular.woff) format("woff"), url(./fonts/glyphicons-halflings-regular.ttf) format("truetype"), url(./images/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format("svg");
}
Works like a charm ;) If I don't find a better solution using Assets Modules, I think I'll leave it as it is. Cheers :)
After upgrading to latest web pack (was still on 0.28) I ran into #88 again.
Thanks @giero for posting your solution, saved me a couple of hours.
@weaverryan this is an issue for every (open source) app, where the devs don't know anything about the host system. This should be (at least) documented.
Edit: btw. the default config sets filenames to [name].[hash:8].[ext]
instead of your example [name].[ext]
The solution from @giero appears to have stopped working. I believe this release is the cause: https://github.com/webpack-contrib/mini-css-extract-plugin/releases/tag/v2.0.0
I have managed to get relative URLs working again by using the following in my webpack.config.js:
.configureMiniCssExtractPlugin((loaderConfig) => {
loaderConfig.publicPath = './';
})
@andyexeter you made my day!
I'll describe my situation so anyone looking in google for this will know your solution works:
- Symfony 6.2
- scss working perfect
- required "@fortawesome/fontawesome-free": "^6.3.0" with yarn
- imported in the scss
- @import '~@fortawesome/fontawesome-free/scss/fontawesome';
- @import '~@fortawesome/fontawesome-free/scss/regular';
- @import '~@fortawesome/fontawesome-free/scss/solid';
- @import '~@fortawesome/fontawesome-free/scss/brands';
- Developing inside a docker at port 23180 inside a subdirectory
- In webpack.config.js I had:
Encore
.setOutputPath('public/build/')
.setPublicPath('build') // removed / for subdirectory deploy
Problem:
- Icons not showing up.
- Reason: The URL was (wrongly) set to http://localhost:23180/repos/hello-trip/admin-panel/public/build/build/fonts/fa-solid-900.bdb9e232.woff2 - Note the double
/build/build/
path.
With @andyexeter's solution, ie: this:
Encore
.setOutputPath('public/build/')
.setPublicPath('build') // removed / for subdirectory deploy
.configureMiniCssExtractPlugin((loaderConfig) => {
loaderConfig.publicPath = './';
})
now the final path is: http://localhost:23180/repos/hello-trip/admin-panel/public/build/fonts/fa-solid-900.bdb9e232.woff2 (ie: no double /build/build but a single one) and the icons properly load.