Skip to content

Wrong path fonts #26

@dayze

Description

@dayze

When I include semantic or bootstrap in my main.js I end up with a 404 not found error for the fonts

Apparently, the output path of fonts go to the root of my web server like this

http://localhost/build/fonts/icons.woff2

Activity

weaverryan

weaverryan commented on Jun 16, 2017

@weaverryan
Member

Hey @dayze!

Can you post your webpack.config.js file and also the code for any relevant other files (like main.js)?

dayze

dayze commented on Jun 19, 2017

@dayze
Author

Hi,

webpack.config.js

var Encore = require('@symfony/webpack-encore');

Encore
// directory where should all compiled assets will be stored
    .setOutputPath('web/build/')

    // what's the public path to this directory (relative to your project's document root dir)
    .setPublicPath('/build')

    // empty the outputPath dir before each build
    .cleanupOutputBeforeBuild()

    // will output as web/build/app.js
    .addEntry('app', './assets/js/main.js')


    // will output as web/build/global.css
    .addStyleEntry('global', './assets/css/global.scss')


    // allow sass/scss files to be processed
    .enableSassLoader()

    // allows legacy applications to use $/jQuery as a global variable
    .autoProvidejQuery()


    .enableSourceMaps(!Encore.isProduction())



// create hashed filenames (e.g. app.abc123.css)
// .enableVersioning()
;

var webpackConfig = Encore.getWebpackConfig();
webpackConfig.module.rules.push({
    test: /\.vue$/,
    loader: 'vue-loader'
});
webpackConfig.module.rules.push({
    test: /\.js$/,
    loader: 'babel-loader',
    exclude: /node_modules/
});

// export the final configuration
module.exports = webpackConfig;

main.js

import Vue from 'vue/dist/vue'
import App from './app.vue'

require('semantic-ui/dist/semantic.min.css')

Errors

GET http://localhost/build/fonts/icons.woff2 
GET http://localhost/build/fonts/icons.woff 
GET http://localhost/build/fonts/icons.ttf 

heitorvrb

heitorvrb commented on Jun 19, 2017

@heitorvrb

Same issue here, with similar configuration. The situation seems to be that my app doesn't run on a ground-level domain, but on a alias on apache:

Alias /mySymfonyApp /var/www/html/mySymfonyApp/web

So webpack is trying to create the src: url() paths with /build/fonts/myFont.eot, when it should be /mySymfonyApp/build/fonts/myFont.eot.

webpack.config.js:

var Encore = require('@symfony/webpack-encore');

Encore
    .setOutputPath('web/build/')

    .setPublicPath('/build')

    .cleanupOutputBeforeBuild()

    .addEntry('app', './app/Resources/js/app.js')

    .addStyleEntry('global', './app/Resources/scss/global.scss')

    .enableSassLoader({
        resolve_url_loader: false
    })

    .autoProvidejQuery()

    .enableSourceMaps(!Encore.isProduction())
    
    // create hashed filenames (e.g. app.abc123.css)
    // .enableVersioning()
;

// export the final configuration
module.exports = Encore.getWebpackConfig(); 

global.scss:

@charset 'utf-8';

$fi-path: "~foundation-icon-fonts/";

@import '~foundation-sites/assets/foundation';
@import '~foundation-icon-fonts/foundation-icons';

Resulting global.css:

// [...]

@font-face {
  font-family: "foundation-icons";
  src: url(/build/fonts/foundation-icons.eot);
  src: url(/build/fonts/foundation-icons.eot?#iefix) format("embedded-opentype"), url(/build/fonts/foundation-icons.woff) format("woff"), url(/build/fonts/foundation-icons.ttf) format("truetype"), url(/build/images/foundation-icons.svg#fontcustom) format("svg");
  font-weight: normal;
  font-style: normal; }

// [...]

localhost/build/fonts/foundation-icons.ttf obviously 404s, the correct path would be localhost/mySymfonyApp/build/fonts/foundation-icons.ttf

weaverryan

weaverryan commented on Jun 20, 2017

@weaverryan
Member

@heitorvrb Ah, thanks for the extra info! If you're deployed under a subdirectory, that should be reflected in your setPublicPath:

// this is your *true* public path
.setPublicPath('/mySymfonyApp/build')
// this is now needed so that your manifest.json keys are still `build/foo.js`
// i.e. you won't need to change anything in your Symfony app
config.setManifestKeyPrefix('build')

You can see an example of this in the tests as well:

it('Deploying to a subdirectory is no problem', (done) => {

Webpack must be aware of the true public path, because if you use "code splitting", then webpack itself will make AJAX requests for assets (so it needs to know the real path). That's why the config lives in webpack.config.js, instead of allowing your app (i.e. Symfony) to "fix" the subdirectory.

Let me know if that helps! I'll open an issue on the docs about this.

heitorvrb

heitorvrb commented on Jun 20, 2017

@heitorvrb

It worked. Thanks for the help.

dayze

dayze commented on Jun 21, 2017

@dayze
Author

It worked too, thanks !

vctls

vctls commented on Oct 9, 2017

@vctls

What if my web root changes depending to the environment I'm deploying to?
On my local development environment, the web root will be /my-nth-app/web/build
whereas on the production server, it will just be /build.
What would be the recommended way to make this dynamic, or at least, configurable?

Lyrkan

Lyrkan commented on Oct 9, 2017

@Lyrkan
Collaborator

@vctls Maybe you could use Encore.isProduction() to set the web root dynamically?

Encore.setPublicPath(Encore.isProduction() ? '/build' : '/my-nth-app/web/build');
vctls

vctls commented on Oct 9, 2017

@vctls

@Lyrkan I will do that, thank you :)
It feels a little hacky, though. I wonder if there's any way of detecting the web root.

scaytrase

scaytrase commented on Nov 5, 2017

@scaytrase

@Lyrkan what if I use artifact-based deploying and the builder do not really know where the artifact would be deployed to?

Is it possible just make path relative to manifest?

Lyrkan

Lyrkan commented on Nov 5, 2017

@Lyrkan
Collaborator

Hi @scaytrase,

I guess you would need to call setPublicPath with a relative path... which isn't allowed right now:

if (publicPath.includes('://') === false && publicPath.indexOf('/') !== 0) {
// technically, not starting with "/" is legal, but not
// what you want in most cases. Let's not let the user make
// a mistake (and we can always change this later).
throw new Error('The value passed to setPublicPath() must start with "/" or be a full URL (http://...)');
}

@andyexeter had a similar issue here: #88 (comment)

We could probably add an allowRelativePath parameter to that method in order to disable that check... what do you think @weaverryan?

scaytrase

scaytrase commented on Nov 5, 2017

@scaytrase

@Lyrkan commenting this error and passing relative path makes internal CSS files to import like

basedir/build/build/fonts/fontawesome.ttf

The build doubles since CSS file is placed inside the build and it calls relative build/fonts/.../

So we really need the possibility to rewrite the paths

25 remaining items

dmeziere

dmeziere commented on Jan 8, 2019

@dmeziere

I am just desperated that SF team opted for a JavaScript solution to handle the assets. Nothing works no more with this technology. And there is no way to maintain it without absorbing a whole lot knowledge about JavaScript. I just hate this "language". When it's not the sass-loader that falls down, you discover that it just can't handle multiple environments. I think I will end with totally uninstalling webpack and find a working PHP solution, that can be configured, fixed, and adapted if necessary to anyone's needs. Frustrated. Why don't you use a stable language, something defined, something that runs the same on any environment. Something that works like any other language. Or maybe it's time to stop working with SF, but it is so sad ...

stof

stof commented on Jan 8, 2019

@stof
Member

@dmeziere you are still free to build your assets the way you want, and reference them with the asset() function in your Twig template. The Asset component has no requirement on webpack-encore.

Modern tooling regarding building frontend code is all written in JS. And we decided to recommend webpack (with this wrapper around its config to simplify it for the use cases we see). But it is not mandatory to use it with Symfony at all.

And regarding using a pure PHP solution, there is no PHP-based tooling implementing a module bundler for JS (JS developers build their tooling in the language they know: JS). And the Symfony core team has no interest into porting Webpack and its whole ecosystem to PHP (that would make no sense, and would require many full-time developers to catch up with the whole webpack community).
You can still do that yourselves if you want to use JS modules. And if you want to keep writing JS in the old way and only concatenate the files together in your final bundle, it is easy to implement that in any language (including a simple Bash command: cat assets/js/*.js > web/build/js/app.js)

dmeziere

dmeziere commented on Jan 10, 2019

@dmeziere

So, I finally found the problem. It was an impact on fos_js_routing. But the frustration of loosing days on this point didn't help me to see things clearly. Finally the solution provided by @Lyrkan was the key as I also use aliases on my dev server, but not on my production server. But if you, falling on this ticket, are using fos_js_routing; be aware that the generated js/json file is not called anymore. It is integrated by webpack encore to the main JS file (what makes sense, after all). So you must make it "prod friendly" before calling yarn encore production. And you no longer need to dump the routes in your deployment script, this will be useless. Finally, I don't like the fact that I must compile and commit my production assets to my repo before a deployment, but it is way better than being forced to install node on the production server, downloading all the node_modules, etc.

Lyrkan

Lyrkan commented on Jan 10, 2019

@Lyrkan
Collaborator

I don't like the fact that I must compile and commit my production assets to my repo before a deployment

@dmeziere Building the assets before a deployment is a good thing, but I'm not sure why you'd have to commit these files.

By the way, if you have more than two public paths to manage you can do something like this:

Encore.setPublicPath(process.env.ENCORE_PUBLIC_PATH || '/build');

Then simply set the ENCORE_PUBLIC_PATH environment variable before calling Encore.

trsteel88

trsteel88 commented on Feb 25, 2019

@trsteel88

I use sub directories for sites while in dev and it was a bit of a pain setting a publicPath. Especially when co-workers had different sub directory structures.

I wrote some code to automatically determine the public directory across all projects within the webpack config.

webpack.config.js

var Encore = require('@symfony/webpack-encore');

var publicPath = '/build';

if (!Encore.isProduction()) {
    require('dotenv').config({
        path: './.webpack.env',
    });

    if ('undefined' !== typeof process.env.ENCORE_PUBLIC_PATH) {
        publicPath = process.env.ENCORE_PUBLIC_PATH;
    } else {
        const guessFromPaths = [
            '/usr/local/var/www/htdocs',
            '/usr/local/var/www',
            process.env.HOME + '/Sites',
        ];

        for (var i = 0; i < guessFromPaths.length; i++) {
            var path = guessFromPaths[i];

            if (0 === __dirname.indexOf(path)) {
                path = __dirname.split(path);
                publicPath = path[1] + '/public/build';
                break;
            }
        }
    }
}

Encore
    // directory where compiled assets will be stored
    .setOutputPath('public/build/')
    // public path used by the web server to access the output path
    .setPublicPath(publicPath)
    // only needed for CDN's or sub-directory deploy
    .setManifestKeyPrefix('build/')
...

You will need to install dotenv from yarn for this to work.

In the above code we are just giving it an array of potential web root directories to look for. This is a list that a few different co-workers are using.

As soon as the loop find a value that matches the __dirname variable, it will take that value and append /public/build to the value.

e.g. if your build files are located in /usr/local/var/www/htdocs/clientXYZ/project123/public/build it will make the public path /clientXYZ/project123/public/build

We also have a .encore.env.dist where you can set a value for ENCORE_PUBLIC_PATH

toklok

toklok commented on Nov 1, 2019

@toklok

@dmeziere Building the assets before a deployment is a good thing, but I'm not sure why you'd have to commit these files.

Some of us don't use CI/CD builds and must commit these files.

Lyrkan

Lyrkan commented on Nov 1, 2019

@Lyrkan
Collaborator

@toklok Even without CI/CD I wouldn't recommend commiting them. Building them locally before a deployment, or even directly on the server (which is not really a good thing either) are probably better solutions.

zulus

zulus commented on Jun 16, 2021

@zulus

My temporary solution:

  1. .setPublicPath(Encore.isProduction() ? '.' : '/build/admin') - so css will contain font paths relative to css file
  2. .setManifestKeyPrefix('build')
  3. After module.exports = Encore.getWebpackConfig() add
if (Encore.isProduction()) {
  module.exports.plugins[2].options.publicPath = 'bundles/w3desadmin/build/' // [2] is WebpackManifestPlugin position
}

Now after yarn run build I have css with relative paths, and asset() function works fine. Unfortunately entrypoints.json have wrong paths, I cannot override it in similar way because AssetsWebpackPlugin calls webpackConfig.getRealPublicPath() directly.

carsonbot

carsonbot commented on Dec 16, 2024

@carsonbot
Collaborator

Thank you for this issue.
There has not been a lot of activity here for a while. Has this been resolved?

carsonbot

carsonbot commented on Jun 17, 2025

@carsonbot
Collaborator

Thank you for this issue.
There has not been a lot of activity here for a while. Has this been resolved?

carsonbot

carsonbot commented on Jul 1, 2025

@carsonbot
Collaborator

Just a quick reminder to make a comment on this. If I don't hear anything I'll close this.

carsonbot

carsonbot commented on Jul 15, 2025

@carsonbot
Collaborator

Hey,

I didn't hear anything so I'm going to close it. Feel free to comment if this is still relevant, I can always reopen!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @weaverryan@stof@kevinpapst@zulus@MasterB

        Issue actions

          Wrong path fonts · Issue #26 · symfony/webpack-encore