【问题标题】:Get versioned string name of font获取字体的版本化字符串名称
【发布时间】:2021-01-31 17:43:36
【问题描述】:

)

我想预取我使用 Tailwindcss 生成的字体。

我以这种方式包含字体:

@layer base {

       /* lato-300 - latin */
    @font-face {
        font-family: 'Lato';
        font-style: normal;
        font-weight: 300;
        src: local('Lato Light'), local('Lato-Light'),
        url('../fonts/lato-v16-latin-300.woff2') format('woff2'), /* Super Modern Browsers */ url('../fonts/lato-v16-latin-300.woff') format('woff'), /* Modern Browsers */ url('../fonts/lato-v16-latin-300.ttf') format('truetype'), /* Safari, Android, iOS */ url('../fonts/lato-v16-latin-300.svg#Lato') format('svg'); /* Legacy iOS */
        font-display: swap;
    }
    /* lato-300italic - latin */
    @font-face {
        font-family: 'Lato';
        font-style: italic;
        font-weight: 300;
        src: local('Lato Light Italic'), local('Lato-LightItalic'),
        url('../fonts/lato-v16-latin-300italic.woff2') format('woff2'), /* Super Modern Browsers */ url('../fonts/lato-v16-latin-300italic.woff') format('woff'), /* Modern Browsers */ url('../fonts/lato-v16-latin-300italic.ttf') format('truetype'), /* Safari, Android, iOS */ url('../fonts/lato-v16-latin-300italic.svg#Lato') format('svg'); /* Legacy iOS */
        font-display: swap;
    }
}

现在我使用 Laravel-mix 处理我的 css:

const {EnvironmentPlugin} = require ('webpack');
const mix = require ('laravel-mix');
const glob = require ('glob');
const path = require ('path');
const {CleanWebpackPlugin} = require ('clean-webpack-plugin');
const ChunkRenamePlugin = require ('webpack-chunk-rename-plugin');
const TargetsPlugin = require('targets-webpack-plugin');

require ('laravel-mix-tailwind');
require('laravel-mix-polyfill');
require('laravel-mix-brotli');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.webpackConfig ({
    output: {
        chunkFilename: 'js/chunks/[name].[chunkhash].js'
    },
    plugins: [
        new CleanWebpackPlugin ({
            cleanOnceBeforeBuildPatterns: ['js/chunks/**/*']
        }),
        new EnvironmentPlugin ({
            BASE_URL: '/'
        }),
        new ChunkRenamePlugin ({
            initialChunksWithEntry: true,
            '/js/app': 'js/app.js',
            '/js/vendor': 'js/vendor.js',
        }),
    ],
    module: {
        rules: [
            {
                test: /node_modules(?:\/|\\).+\.js$/,
                loader: 'babel-loader',
                options: {
                    presets: [['@babel/preset-env', {targets: 'last 2 versions, ie >= 10'}]],
                    plugins: ['@babel/plugin-transform-destructuring', '@babel/plugin-proposal-object-rest-spread', '@babel/plugin-transform-template-literals'],
                    babelrc: false
                }
            },
            {
                enforce: 'pre',
                test: /\.(js|vue)$/,
                loader: 'eslint-loader',
                exclude: /node_modules/
            }
        ]
    },
    resolve: {
        alias: {
            '@': path.join (__dirname, 'resources'),
            'node_modules': path.join (__dirname, 'node_modules')
        }
    },
});

mix.js ('resources/js/app.js', 'public/js')
.postCss ('resources/css/app.css', 'public/css')
.tailwind ('./tailwind.config.js');

if (mix.inProduction ()) {
    mix
    .version ()
    .polyfill({
        enabled: true,
        useBuiltIns: "usage",
        targets: "> 0.25%, not dead",
        corejs: 3
    })
    .brotli();
}

这是我处理后的 css 的样子:

@font-face {
  font-family: 'Lato';

  font-style: italic;

  font-weight: 300;

  src: local('Lato Light Italic'), local('Lato-LightItalic'),
        url(/fonts/lato-v16-latin-300italic.woff2?a21767e20d27a9c06007c981a8e5f827) format('woff2'),  url(/fonts/lato-v16-latin-300italic.woff?8e90b967ea69fc68b130d36cc34d41c0) format('woff'),  url(/fonts/lato-v16-latin-300italic.ttf?329d60785944501134891f948f41c001) format('truetype'),  url(/fonts/lato-v16-latin-300italic.svg?17e346950dce164549968b7b93d48f2d#Lato) format('svg'); /* Legacy iOS */

  font-display: swap;
}

不知何故,我需要找到一种方法将那些版本化的字体调用包含到我的预取中。

我的第一次尝试是遍历 public/fonts 中的所有文件,但当然我没有得到版本化的 url:

@foreach(File::files(public_path('fonts')) as $font)
    <link rel="preload" href="/fonts/{{$font->getFilename()}}" as="font">
@endforeach

我的一个想法是将网址添加到mix-manifest.json,但我有点卡在这里:-(

【问题讨论】:

    标签: css webpack laravel-mix tailwind-css postcss


    【解决方案1】:

    鉴于足够的上下文,可能会有更好的方法来解决您试图解决的潜在问题,但在您已有的基础上,我接下来将创建一个辅助函数:

    function fontVersion($filename){
      $source = file_get_content(public_path('css/app.css'));
      $start = strpos($source, $filename) + strlen($filename);
      $end = strpos($source, ')', $start);
      return substr($source, $start, $end - $start);
    }
    

    然后在我的视图中调用它以将版本字符串添加到我的 URL:

    @foreach(File::files(public_path('fonts')) as $font)
        <link rel="preload" href="/fonts/{{ $font->getFilename() . fontVersion(filename) }}" as="font">
    @endforeach
    

    这是一个live demo,稍作修改供您参考。

    【讨论】:

    • 在应用了一些小修复 (file_get_contents) 后,这解决了 :-) 非常感谢!
    【解决方案2】:

    我不太确定你想要什么,所以这里有两个选择:


    这将停止处理 URL,保留字体

    .options({
            processCssUrls: false,
    })
    

    您也许可以在 CSS 中使用它来保留字体

    @import url('https://fonts.googleapis.com/css2?family=Rowdies:wght@300&display=swap');
    

    唯一的问题是,如果字体是从 css 自定义的,您可能需要创建网站以便从中调用字体

    【讨论】:

      【解决方案3】:

      所以这里有一个更简洁的方法来做到这一点。您可以在 webpack.mix.js 中获取资产列表并生成您的预加载代码:

      mix.then((stats) => {
          let preload = [];
          for (let file of Object.keys(stats.compilation.assets)) {
              if (file.indexOf("woff2") == -1) {
                  continue;
              }
              preload.push(`<link rel="preload" href="${file}" as="font" type="font/woff2" crossorigin></link>`);
          }
          fs.writeFileSync("public/preload.txt", preload.join("\n"));
      });
      

      将它包含在您的刀片中。

      <?php @include public_path('preload.txt'); ?>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-04
        • 2019-08-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-24
        • 2016-03-05
        • 1970-01-01
        相关资源
        最近更新 更多