Search code examples
laravelsasswebpackwebpack-2laravel-5.4

Laravel Mix and SASS changing font directory


I'm using Laravel 5.4 and Laravel Mix to output SASS files.

In my font definitions I'm configuring them so that when the CSS is output it will point to files such as public/assets/fnt/font-name/filename.ext but the processor changes the output so that it will instead point to public/fonts/filename.ext. Is there a way to stop it from changing the output paths?

It makes little sense to me that it would do something like this by default.

Edit

I've seen that the defaults they're using in Mix are the culprit:

module.exports.module = {
    rules: [
        // ...
        {
            test: /\.(woff2?|ttf|eot|svg|otf)$/,
            loader: 'file-loader',
            options: {
                name: 'fonts/[name].[ext]?[hash]',
                publicPath: '/'
            }
        }
    ]
};

I've tried using null-loader instead of file-loader but instead it causes it to fail because it can't find the files in node_modules which is not where it should be looking in the first place.

Removing the rule in question results in a flood of errors from trying to open and evaluate the font files in question:

 error  in ./public/assets/fnt/fanfare-jf/fanfare-jf.ttf

Module parse failed: DIRECTORY\public\assets\fnt\fanfare-jf\fanfare-jf.ttf Unexpected character '' (1:0)
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)

 @ ./~/css-loader!./~/postcss-loader!./~/resolve-url-loader!./~/sass-loader?sourceMap&precision=8!./resources/assets/sass/app.scss 6:2525-2590
 @ ./resources/assets/sass/app.scss
 @ multi ./resources/assets/js/app.js ./resources/assets/sass/app.scss

I can at least add emitFiles: false to options to prevent it from making copies of the file, but the paths are still being altered.


Solution

  • I ended up with the following configuration to at least get it to a working state.

    let assetDir = 'assets/build';
    
    mix.config.fileLoaderDirs.fonts = `${assetDir}/${mix.config.fileLoaderDirs.fonts}`;
    mix.config.fileLoaderDirs.images = `${assetDir}/${mix.config.fileLoaderDirs.images}`;
    
    mix.sass('resources/sass/app.scss', `public/${assetDir}/css`)
       .js('resources/js/app.js', `public/${assetDir}/js`);
    

    Updated:

    In newer versions this has been made customizable via mix.options() and can be adjusted as below:

    let assetDir = 'assets/build';
    
    mix.options({
        fileLoaderDirs: {
            images: `${assetDir}/img`,
            fonts: `${assetDir}/fonts`
        }
    });
    
    // adjust build commands accordingly, for example:
    mix.js('resources/js/app.js', `public/${assetDir}/js`);