简体   繁体   English

图像GET使用Webpack和AngularJS在生产中抛出404错误

[英]Images GETs throw 404 error in production using Webpack and AngularJS

I have this conundrum I can't solve after many tryouts: 我有这个难题,经过多次尝试后无法解决:

I'm unable to load static images in production; 我无法在生产中加载静态图像;

everything is fine while developing ( npm run serve ), even when serving files from dist ( npm run serve:dist ) 在开发( npm run serve )时一切都很好,即使从dist提供文件( npm run serve:dist

Versions 版本

Webpack: 3.12.0 Webpack:3.12.0

file-loader: 1.1.11 file-loader:1.1.11

url-loader: 1.1.2 url-loader:1.1.2

AngularJS: 1.6.9 AngularJS:1.6.9

While developing: 开发时:

My index.html contains this line and webpack won't load without 我的index.html包含这一行,webpack将不会加载

<base href="/"></base>

while my AngularJS config block contains 而我的AngularJS配置块包含

$locationProvider.hashPrefix('');

I use an URL like http://localhost:3000/#/appName/listingComponent/users 我使用像http:// localhost:3000 /#/ appName / listingComponent / users这样的URL

and I'm able to see every image using the ng-src (sometimes it's dynamically binded) like this 我能够像这样使用ng-src (有时是动态绑定)来查看每个图像

<img ng-src="app/images/image1.png">

the folder structure is like this 文件夹结构是这样的

ui/
├── conf/
│   ├── browsersync-dist.conf.js
│   ├── browsersync.conf.js
│   ├── gulp.conf.js
│   ├── webpack-dist.conf.js
│   └── webpack.conf.js
├── gulp_tasks/
│   ├── browsersync.js
│   ├── misc.js
│   └── webpack.js
├── node_modules/
├── src/
│   ├── app/
│   │   ├── config.js  //global variables
│   │   ├── favicon.ico
│   │   ├── index.html
│   │   ├── index.js
│   │   ├── index.less
│   │   ├── images/ <--
│   │   ├── actual_app_folders/
│   │   └── ...
├── gulpfile.js
└── package.json

In my webpack-dist.js I have the following 在我的webpack-dist.js中,我有以下内容

module.exports = {
  module: {
    loaders: [
      {
        test: /\.json$/,
        loaders: [
          'json-loader'
        ]
      },
      {
        test: /\.js$/,
        exclude: [
          /node_modules/
        ],
        loader: 'babel-loader',
        options: {
          presets: ['es2015']
        }
      },
      {
        test: /\.js$/,
        exclude: [
          /node_modules/
        ],
        loaders: [
          'eslint-loader'
        ],
        enforce: 'pre'
      },
      {
        test: /\.(css|less)$/,
        exclude: '/node_modules/roboto-fontface/',
        loaders: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: 'css-loader?minimize!less-loader!postcss-loader'
        })
      },
      {
        test: /\.html$/,
        loaders: [
          'html-loader'
        ]
      },
      {
        test: /\.(jpe?g|png|gif|svg|eot|woff|ttf|svg|woff2)$/,
        loader: 'url-loader?name=[name].[ext]'
      }
    ]
  },
  plugins: [
    new webpack.NoEmitOnErrorsPlugin(),
    FailPlugin,
    new HtmlWebpackPlugin({
      template: conf.path.src('/app/index.html'),
      inject: true,
      chunksSortMode: 'dependency'
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: ['vendors', 'config'],
      minChunks: Infinity
    }),
    new ExtractTextPlugin('index-[contenthash].css'),
    new webpack.LoaderOptionsPlugin({
      options: {
        postcss: () => [autoprefixer]
      }
    })
  ],
  output: {
    path: conf.paths.dist,
    filename: function(output) {
      return output['chunk']['name'] === 'config' ? '[name].js' : '[name]-[hash].js';
    },
    chunkFilename: '[name]-[hash].js'
  },
  entry: {
    app: `./${conf.path.src('/app/index')}`,
    config: `./${conf.path.src('/app/config')}`,
    vendors: Object.keys(pkg.dependencies).concat(['webpack-material-design-icons'])
  }
};

IN PRODUCTION 在生产中

The build process adds the /customer_company_name/our_company_name/ prefix to the path, which becomes 构建过程将/customer_company_name/our_company_name/前缀添加到路径中,该路径变为

http://<customer_domain>:<domain_port>/customer_company_name/our_company_name/#/appName/listingComponent/users

while the folder structure is like this 而文件夹结构是这样的

our_company_name/
├── app/
│   ├── images/ <--
│   │   ├── image1.png
│   │   └── image2.png
├── app-<random_number>.js
├── config.js
├── favicon.ico
├── index.html
├── index-<random_number>.css
└── vendors.js

THE PROBLEM 问题

Now every time there's a pic to be shown, the browser gets a 404 error like this 现在,每次显示图片时,浏览器都会收到404错误

GET http://<customer_domain>:<domain_port>/app/images/image1.png 404 (Not Found)

while the request should be made like this 而请求应该像这样

GET http://<customer_domain>:<domain_port>/customer_company_name/our_company_name/index.js

like every other file in the application does. 像应用程序中的每个其他文件一样。

What I tried 我尝试了什么

So far nothing of the following helped: 到目前为止,以下没有任何帮助:

  1. Change base tag upon build process in the following <base href="/customer_company_name/our_company_name/"></base> (this is currently retained) 在以下<base href="/customer_company_name/our_company_name/"></base>构建过程时更改基本标记(目前保留)
  2. Explicitly requiring the pictures together with every other file in the index.js require('./images/ODM_trasp48px.png'); 明确要求图片与index.js中的每个其他文件一起使用require('./images/ODM_trasp48px.png'); (this is currently retained) (目前保留)
  3. Using publicPath in webpack output.publicPath: '/customer_company_name/our_company_name/' and also output.publicPath: '/' 在webpack output.publicPath: '/customer_company_name/our_company_name/'使用publicPath output.publicPath: '/customer_company_name/our_company_name/'以及output.publicPath: '/'
  4. Using file-loader instead of url-loader (this is currently retained) 使用文件加载器而不是url-loader(目前保留)
  5. Using file-loader with options: { useRelativePath: true } 使用带有options: { useRelativePath: true }文件加载器options: { useRelativePath: true }
  6. Using file-loader with options: { publicPath: /customer_company_name/our_company_name/ } 使用带有options: { publicPath: /customer_company_name/our_company_name/ }文件加载器options: { publicPath: /customer_company_name/our_company_name/ }

Can you help me lads, please? 你能帮我小伙子们吗?

I think the problem is not with the replacement pattern since it works for other file types, but the fact that webpack does not know what to do with ng-src attribute. 我认为问题不在于替换模式,因为它适用于其他文件类型,但事实上webpack不知道如何处理ng-src属性。 I think it only looks at the img's src attribute by default. 我认为它默认只查看img的src属性。 You can change it to recognize ng-src like: 您可以将其更改为识别ng-src,如:

module.exports = {
  module: {
    loaders: [
    ...
    {
      test: /\.html$/,
      loaders: [ "html-loader?" + JSON.stringify({ attrs: ["img:src", "img:ng-src"] })]
    },
    ...
  ],
   ...

alt syntax: alt语法:

{
   test: /\.html$/,
   loaders: [ "html-loader?attrs=img:src img:ng-src" ]
}

Before changing your config, you can just test whether that is the reason by checking if the replacement currently works correctly for img tags with a plain static <img src="..."/>. 在更改配置之前,您可以通过检查替换当前是否正常用于具有普通静态<img src =“...”/>的img标记来测试是否是这个原因。

Instead of letting webpack parsing your templates, you might try to explicitly import your image(s) and pass it to your template. 您可以尝试显式导入图像并将其传递给模板,而不是让webpack解析模板。

The imported images will be then processed by the configured image-loader or url-loader . 然后,配置的image-loaderurl-loader将处理导入的图像。

Static image 静态图像

const myImage = require('./path/to/images/image1.png');

// In component declaration 
`<img ng-src="${myImage}">`

Dynamic image 动态图像

Using webpack's require.context 使用webpack的require.context

const pathToImages = require.context('./path/to/images', true);
const dynamicImageName = 'foo.jpg',

// In component declaration 
`<img ng-src="${pathToImages(dynamicImageName, true)}">`

你可以尝试下面改变你的index.html

<base href="./"></base>

SOLUTION Let's start with 解决方案让我们开始吧

output.publicPath: '/customer_company_name/our_company_name/'

this will take care of rewriting ng-/src paths correctly as explained here . 这将作为解释的正确利用改写NG-/ src目录路径护理在这里

We won't need the html-loader to parse ng-/src, the only thing needed is to always use ng-src, or the build won't be successful. 我们不需要html-loader来解析ng- / src,唯一需要的是始终使用ng-src,否则构建将不会成功。

Eventually, there's no need of <base> tag and neither the initial slash in every path used to refer to images. 最终,不需要<base>标记,并且每个路径中的初始斜杠都不用于引用图像。

I'll update this answer as I improve the webpack-dist.conf.js /the whole project for the better. 我将更新这个答案,因为我改进了webpack-dist.conf.js /整个项目。


No answer given worked per se, hence I'll try combinations of them since some suggestions look legit. 没有给出答案,因此我会尝试将它们组合起来,因为一些建议看起来合法。

Eventually, if I won't be able to solve this, I'll try to drop the production path prefix /customer_company_name/our_company_name/ . 最后,如果我无法解决这个问题,我将尝试删除生产路径前缀/customer_company_name/our_company_name/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM