webpack-encore icon indicating copy to clipboard operation
webpack-encore copied to clipboard

Incorrect paths for fonts

Open giero opened this issue 4 years ago • 9 comments

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?

giero avatar Feb 04 '21 11:02 giero

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()

giero avatar Feb 04 '21 13:02 giero

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!

weaverryan avatar Feb 05 '21 00:02 weaverryan

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.

giero avatar Feb 05 '21 08:02 giero

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).

giero avatar Feb 09 '21 23:02 giero

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.

weaverryan avatar Feb 12 '21 00:02 weaverryan

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:

  1. generate single styles.css (from all in-project css/less/scss files) file in Encore's outputPath
  2. gather all font files in outputPath/fonts
  3. gather all image files in outputPath/image
  4. (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 :)

giero avatar Apr 27 '21 12:04 giero

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]

kevinpapst avatar Apr 29 '21 15:04 kevinpapst

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 avatar Jul 19 '22 16:07 andyexeter

@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.

xmontero avatar Feb 17 '23 00:02 xmontero