Webpack文件加载器publicPath

5

我有一个React项目,其中我使用webpack 3.10.0和file loader 1.1.6将一些图像和json文件移动到我的分发文件夹中。

Webpack按预期发出文件,但React接收到了错误的json和图像资产URL

我的标记看起来像:

<img src="../images/helloworld_a49183cf48e4a0f12aa2124fe2ed9d3a.png" 
alt="Hello World!!">

但是应该是:
<img src="/assets/images/helloworld_a49183cf48e4a0f12aa2124fe2ed9d3a.png" 
alt="Hello World!!">

我的文件夹结构如下所示: C:. ├───dist │ └───assets │ ├───css │ ├───data │ ├───images │ └───js ├───src │ ├───css │ ├───data │ ├───images │ └───js │ ├───actions │ ├───components │ ├───containers │ └───reducers └───tests 我认为file-loader的publicPath应该可以解决这个问题,但是似乎我要么理解错了,要么我的配置有问题。是否有人能够帮助我解决这个问题呢?
webpack.config.js
var path = require('path');
const ExtractCSS = require("extract-text-webpack-plugin");

module.exports = {
  entry: [
    './src/js/index.js'
  ],
  output: {
    path: path.resolve(__dirname, 'dist/assets/js'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['env','react']
          }
        }
      },
      {
        test: /\.scss$/,
        loader: ExtractCSS.extract('css-loader!sass-loader')
      },
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name (file) {
                /*if (env === 'development') {
                  return '[path][name].[ext]'
              }*/
                return '[name]_[hash].[ext]'
              },
              publicPath: '/assets/images/',
              outputPath: '../images/'
            }  
          }
        ]
      },
      {
        test: /\.json$/,

        use: [
          {
            loader: 'file-loader',
            options: {
              name (file) {
                /*if (env === 'development') {
                  return '[path][name].[ext]'
              }*/
                return '[name].[ext]'
              },
              publicPath: '/assets/data/',
              outputPath: '../data/'
            }  
          }
        ]
      }
    ]
  },
  plugins: [
    new ExtractCSS('../css/app.css', {
        allChunks: true
    }) 
  ],
  resolve: {
    extensions: ['.js', '.jsx']
  },
  //devtool: 'eval-source-map',
  devServer: {
    historyApiFallback: true,
    contentBase: './dist/'
  }
};

Webpack 5 的新特性:内置的资源管理器能够很好地处理字体。请参阅 https://bytepursuits.com/using-webpack-5-with-font-awesome-5。 - ron
3个回答

3
所以,与其使用

标签来表示段落的结束,
{
    test: /\.(png|jpg|gif)$/,
    use: [
      {
        loader: 'file-loader',
        options: {
          name (file) {
            /*if (env === 'development') {
              return '[path][name].[ext]'
          }*/
            return '[name]_[hash].[ext]'
          },
          publicPath: '/assets/images/',
          outputPath: '../images/'
        }  
      }
    ]
  },

您可以尝试类似以下的方法:
{
    test: /\.(png|jpg|gif)$/,
    use: [
      {
        loader: 'file-loader',
        options: {
          name (file) {
            /*if (env === 'development') {
              return '[path][name].[ext]'
          }*/
            return '[name]_[hash].[ext]'
          },
          publicPath: function(url) {
              return url.replace(../, '/assets/')
          },
        }  
      }
    ]
  },

谢谢您的建议。不幸的是,它没有起作用。在您的示例中,没有输出路径,因此文件将以与我的捆绑包相同的目录结构结束。我添加了输出路径,发射的文件最终出现在正确的文件夹中。无论是否有输出路径,img src标签仍然反映错误的路径。 - Mark Priem
我不小心在url.replace的第一个参数外加了引号。现在我已经去掉了。可能这就是它没有工作的原因。无论如何,很高兴你现在找到了解决方案。 - mu_sa
谢谢你,但是你误解了我的意思。我还没有让它工作。如果你想试一下,我创建了一个代码仓库:https://github.com/mpriem/BrokenWebPack 非常感谢你的帮助! - Mark Priem

1
你也可以将输出对象配置为上一级,然后仅指定文件的名称:
  output: {
    path: path.resolve(__dirname, 'dist/assets'),
    filename: 'js/bundle.js'
  },

例如,对于JSON:

{
    test: /\.json$/,
    use: [
        {
            loader: 'file-loader',
            options: {
                name: 'data/[name].[ext]',
            }
      }
    ]
}

谢谢!我会尝试一下。虽然感觉像是一个变通方法 :). 不过 file-loader 应该能够做到我想要的吧? - Mark Priem
是的,但它做了你想要的事情。你指定了 ../images/,而你的链接以 ../images/[...] 开头,所以它可以工作。 - ChrisR
1
那么 publicPath 是用来做什么的呢?据我所知,outputPath 应该驱动文件输出的路径,而 publicPath 则应返回到您的 import 或 include 函数中。 - Mark Priem

1
今早在我的机器重启后,问题发生了变化?!?(缓存问题?!)……现在它不再忽略publicPath,而是将publicPath与outputPath连接起来。和这里讲解的问题相同:https://github.com/webpack-contrib/file-loader/issues/228 回退到0.10.1可以解决我的问题。
感谢所有尝试帮助我的人!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接