webpack 5 изображения/шрифты в scss не компилируются правильно

#javascript #node.js #webpack #sass

Вопрос:

Моя проблема в том, что изображения и шрифты внутри моего файла .scss переименовываются в хэш, а URL-адрес в файле scss изменяется. Мой файл .scss импортируется в мой app.js в самом верху файла, например:

 import '../scss/app.scss';
 

Пример в моем файле .scss:

 @font-face {
  font-family: 'FTBase';
  src: url("../fonts/FTBase-Book.woff2") format("woff2"),
    url("../fonts/FTBase-Book.woff") format("woff");
  font-weight: 350;
  font-style: normal;
  font-display: swap
}
.event--1 {
  background: var(--salmon) url("../images/leading-women.jpg") no-repeat center;
  background-size: contain;
}
 

Результат после запуска разработки/сборки/производства:

 @font-face {
  font-family: "FTBase";
  src: url(../51ebe4030489fa0868f9.woff2) format("woff2"), url(../be034b081210fbdf38a2.woff) format("woff");
  font-weight: 350;
  font-style: normal;
  font-display: swap;
}
.event--2 {
  background: var(--salmon) url(../485639d38ea610d7bba2.jpg) no-repeat center;
  background-size: cover;
}
 

и он выводит изображения/шрифты в /dist.

Вот мои файлы webpack: webpack.config.js:

 const templateFiles = fs.readdirSync(environment.paths.source)
  .filter((file) => path.extname(file).toLowerCase() === '.html');

const htmlPluginEntries = templateFiles.map((template) => new HTMLWebpackPlugin({
  inject: 'body',
  hash: false,
  minify: false,
  filename: template,
  template: path.resolve(environment.paths.source, template),
  favicon: path.resolve(environment.paths.source, 'images', 'favicon.ico'),
}));

module.exports = {
  entry: {
    app: path.resolve(environment.paths.source, 'js', 'app.js'),
  },
  output: {
    filename: 'js/[name].js',
    path: environment.paths.output,
  },
  module: {
    rules: [{
        test: /.((c|sa|sc)ss)$/i,
        use: [{
          loader: MiniCssExtractPlugin.loader,
          options: {
            publicPath: '../',
          }
        }, {
          loader: 'css-loader',
        }, {
          loader: 'sass-loader',
        }, {
          loader: 'postcss-loader',
        }],
      },
      {
        test: /.js$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
      },
      {
        test: /.(png|gif|jpe?g|svg|jpg)$/i,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'images/',
          },
        }, ],
      },
      {
        test: /.(eot|ttf|woff|woff2)$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/',
          },
        }, ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/[name].min.css',
    }),
    new ImageminWebpWebpackPlugin({
      config: [{
        test: /.(jpe?g|png)/,
        options: {
          quality: 76,
        }
      }],
      overrideExtension: true,
      detailedLogs: false,
      silent: false,
      strict: true,
    }),
    new CleanWebpackPlugin({
      verbose: true,
      cleanOnceBeforeBuildPatterns: ['**/*', '!stats.json'],
    }),
    new CopyWebpackPlugin({
      patterns: [{
        from: path.resolve(environment.paths.source, 'images'),
        to: path.resolve(environment.paths.output, 'images'),
        toType: 'dir',
        globOptions: {
          ignore: ['*.DS_Store', 'Thumbs.db'],
        },
      }, ],
    }),
  ].concat(htmlPluginEntries),
  target: 'web',
};
 

webpack.dev.config.js:

 const webpackConfiguration = require('../webpack.config');
const environment = require('./environment');

module.exports = merge(webpackConfiguration, {
  mode: 'development',

  /* Manage source maps generation process */
  devtool: 'eval-source-map',

  /* Development Server Configuration */
  devServer: {
    contentBase: environment.paths.output,
    watchContentBase: true,
    publicPath: '/',
    open: true,
    historyApiFallback: true,
    compress: true,
    overlay: true,
    hot: false,
    watchOptions: {
      poll: 300,
    },
    ...environment.server,
  },

  /* File watcher options */
  watchOptions: {
    aggregateTimeout: 300,
    poll: 300,
    ignored: /node_modules/,
  },

  /* Additional plugins configuration */
  plugins: [],
});
 

webpack.prod.config.js:

 const webpackConfiguration = require('../webpack.config');

module.exports = merge(webpackConfiguration, {
  mode: 'production',

  /* Manage source maps generation process. Refer to https://webpack.js.org/configuration/devtool/#production */
  devtool: false,

  /* Optimization configuration */
  optimization: {
    splitChunks: {
      chunks: 'all',
      name: 'vendor',
    },
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: true,
      }),
      new CssMinimizerPlugin(),
    ],
  },

  /* Performance treshold configuration values */
  performance: {
    maxEntrypointSize: 512000,
    maxAssetSize: 512000,
  },

  /* Additional plugins configuration */
  plugins: [],
});
 

В моем webpack.config.js файл Я попытался установить исходные карты в значение true на css-загрузчике и sass-загрузчике, изменить общедоступный путь и еще несколько вещей, которые я пробовал на других форумах, но безуспешно.

Ответ №1:

Итак, я понял это, мне пришлось удалить загрузчик файлов из изображений и шрифтов. Я заменил его на этот:

 {
   test: /.(png|jpg|gif|svg)$/,
   type: 'asset/resource',
}, {
   test: /.(ttf|otf|eot|woff(2)?)(?[a-z0-9] )?$/,
   type: 'asset/resource',
},
 

а затем мне пришлось отредактировать вывод в этом:

   output: {
    filename: 'js/[name].js',
    path: environment.paths.output,
    assetModuleFilename: 'assets/[name][ext]',
  },
 

Поэтому теперь, когда я запускаю разработку/сборку/производство, он захватывает все ресурсы, которые находятся в файле scss, сохраняет их одинаковое имя и создает папку «активы», которая расположена «/dist/активы», и автоматически изменяет URL-адрес в файле scss на «../assets/image.jpg’

Комментарии:

1. Это сработало и для меня. Спасибо. Нам не нужен загрузчик файлов с webpack 5.