【问题标题】:webpack - the file-loader is deleting images copied from CopyPluginwebpack - 文件加载器正在删除从 CopyPlugin 复制的图像
【发布时间】:2020-03-14 01:53:23
【问题描述】:

我认为我的 Webpacking 错误。在我的 Webpack 配置中,我有一个模块规则来在 scss 文件中遇到文件时加载文件,并且我还使用 CopyPlugin 复制大量其他图像。

问题是,当我在开发中运行 Webpack 并将“watch”设置为 true 时,文件加载器将删除 dist 文件夹中的所有内容,然后复制 SCSS 文件中引用的图像。因此,通过 CopyPlugin 复制的所有其他内容都将被删除。

我是否应该以不同的方式处理我的 SCSS/JS 中引用的图像。理想情况下,我会忽略 SCSS/JS 中对这些东西的所有引用,只需通过 CopyPlugin 手动复制文件

这是我的配置:

module.exports = {
  mode: 'development',
  watch: true,
  entry: {
    frontend: './_src/entry.js',
  },
  output: {
    filename: 'js/[name].js',
    path: path.resolve(__dirname, paths.distRoot),
  },
  module: {
    rules: [
      // js
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          },
        },
      },
      // css
      {
        test: /\.css$/,
        use: [
          { loader: MiniCssExtractPlugin.loader },
          { loader: 'css-loader' },
        ],
      },
      // scss
      {
        test: /\.scss$/,
        use: [
          { loader: MiniCssExtractPlugin.loader },
          // css 
          {
            loader: 'css-loader',
            options: { sourceMap: true },
          },
          // autoprefix things
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              sourceMap: true,
              plugins: [
                autoprefixer({ browsers: ['last 2 version'] }),
              ],
            },
          },
          // sass
          {
            loader: 'sass-loader',
            options: {
              includePaths: [
                paths.npmRoot + '/font-awesome',
                paths.srcRoot + '/scss',
                paths.npmRoot,
              ],
            },
          },
        ],
      },
      // fonts
      {
        test: /\.(woff(2)?|ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]',
          outputPath: 'fonts',
          publicPath: '../fonts',
        },
      },
      // images
      {
        test: /\.(jpg|png|svg|gif)$/,
        loader: 'url-loader',
        options: {
          limit: 1,
          name: '[name].[ext]',
          outputPath: 'img',
          publicPath: '../img',
        },
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new MiniCssExtractPlugin({
      filename: 'css/[name].css',
    }),
    new CopyPlugin([
      {
        from: path.resolve(__dirname, paths.srcRoot + '/img'),
        to: path.resolve(__dirname, paths.distRoot + '/img'),
        copyUnmodified: true,
      },
    ]),
    new (webpack.optimize.OccurenceOrderPlugin || webpack.optimize.OccurrenceOrderPlugin)(),
  ],
};

【问题讨论】:

  • 为什么需要 CopyWebpackPlugin?我认为你不需要它。您已经使用 url 加载器处理了图像,它会将您的图像作为 base64 加载到 js 输出文件中。我也无法在您的配置中看到文件加载器。即使你使用文件加载器,你也不需要 copywebpackplugin。
  • 因为 IIRC 文件加载器和 url-loader 仅在遇到 JS 或 SCSS 中的图像时才会起作用。但是,我的一些图像在这些文件中没有直接引用,而是可以通过用户输入进行切换。因此,那些“可选”图像永远不会得到处理。

标签: webpack sass webpack-4 webpack-file-loader


【解决方案1】:

你没看错。 Webpack 无法获取有关您未在 js/scss 中直接引用的图像的任何知识。一些想法如何处理这样的图像:

1) 使用 copy-webpack-plugin 复制图像,但不要由任何加载器处理。或者使用插件和加载器,但为其设置不同的输出路径。 如何使用文件加载器设置输出路径:

{
        test: /\.(png|jpe?g|gif)$/i,
        loader: 'file-loader',
        options: {
          name: 'my-super-assets/[path][name].[ext]', 
          // OR outputPath: 'my-super-assets'
        },
},

将强制您的图像到my-super-assets 文件夹
以及用于复制 webpack-plugin

new CopyPlugin([
      {
        from: path.resolve(__dirname, paths.srcRoot + '/img'),
        to: path.resolve(__dirname, paths.distRoot + '/another-super-assets''),
        copyUnmodified: true,
      },
    ]),

2) 使用dynamic imports在用户输入上动态加载图像
一些简单的 html/js 代码如何使用它:

<input id="input" type="checkbox">

document.querySelector("#input").addEventListener('change', event => {
  if(event.target.checked) {
    // it will be handled with loader you choose, url-loader or file loader for example
    // or you can write import to js file, which have multiple imports to images already
    import("./assets/foo.svg").then((image) => // image is ready to use)
  }
})

PS:我认为 webpack-dev-server(它使用内存文件系统)不会发生你描述的关于带有 watch 模式的 webpack 的问题

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-31
    • 1970-01-01
    • 2018-06-03
    • 2016-10-06
    • 2019-01-16
    • 2018-03-01
    • 2017-07-04
    • 1970-01-01
    相关资源
    最近更新 更多