图像不显示在生产版本上,仅在dev(webpack / sass-loader)

时间:2018-04-01 03:42:57

标签: javascript image webpack sass sass-loader

在webpack dev服务器上运行我的应用程序时,我的所有图像文件都在工作,无论是我的index.html中的img标签还是background-image:url()..

在生产版本中运行我的项目,我收到了无法找到的文件引用错误。

GET file:///img/featured.png net::ERR_FILE_NOT_FOUND
GET file:///img/header-img1-1.jpg net::ERR_FILE_NOT_FOUND

我添加了复制webpack插件,因为我认为这会将我的src / img文件夹中的所有图像移动到dist中的img文件夹。

我应该使用webpack-dev-server的contentBase选项吗?或者copy-webpack-plugin没有得到正确的引用?超级混乱

项目树:

- webpack.config.js
- package.json
- .babelrc
- src
  - js
    - index.js
    - ...
  - img
    - ALL IMAGES LOCATED HERE
  - scss
    - layout
      - landing.scss
      - brands.scss 
    - base
  - index.html

在landing.scss中 我用过

background: url('~/img/img-title.png')

在brands.scss等其他文件中也是如此

background: url('~/img/img-title.png')

这一切都运行良好,我认为我已经把自己与webpack / sass加载器引用图像的方式混淆了,似乎无法弄清楚如何让图像路径适用于dev / production,我似乎只能让一个人一次工作。

生产树:

- dist
  - css
  - img
  - js
  - index.html

webpack.config.js:

const path = require('path');
const autoprefixer = require('autoprefixer');

const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractPlugin = new ExtractTextPlugin({
  filename: 'css/main.css'
});

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ScriptExtPlugin = require('script-ext-html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = (env) => {
  const isProduction = env.production === true

  return {
	entry: './src/js/index.js',
	output: {
		path: path.resolve(__dirname, 'dist'),
		filename: 'js/bundle.js', 
	},
	module: {
	  rules: [
		{
	      test: /\.js$/,
	      include: path.resolve(__dirname, 'src'),
		  use: 'babel-loader' 
		},
		{
		  test: /\.css$|\.scss$/,
		  include: path.resolve(__dirname, 'src'),
		  use: extractPlugin.extract({  
			fallback: "style-loader",
			use: [
			  { loader: 'css-loader', options: { importLoaders: 2, sourceMap: true }},
			  { loader: 'postcss-loader', options: { sourceMap: true, plugins: () => [autoprefixer] }},
			  { loader: 'sass-loader', options: { sourceMap: true }},
			],
		  }) 
		},
		{
		  test: /\.html$/,
		  use: ['html-loader']
		},
		{
		  test: /\.(jpe?g|png|gif)$/,
		  use: [
			{
		      loader: 'url-loader',
			  options: {
				limit: 1000,
				name: 'img/[name].[ext]',
			  }
			}
		  ]
		}
	  ]
	},
	plugins: [
	  extractPlugin,
	  new HtmlWebpackPlugin({ 
		filename: 'index.html',
		inject: true,
		template: './src/index.html'
	  }),
	  new ScriptExtPlugin({
	    defaultAttribute: 'async'
	  }),
	  new CleanWebpackPlugin(['dist']),
	  new CopyWebpackPlugin([
	    {from:'src/img',to:'img'} 
	  ]), 
	]
  }
}

4 个答案:

答案 0 :(得分:2)

我认为您在制作时使用的文件夹结构不同于本地文件夹结构,即在本地,它只是 http://localhost:PORT/app ,但是在产品上,它必须类似于 http://produrl/Some_Folder/app

现在遇到实际问题 - 它是你的CSS加载器。

默认 css-loader url = true ,导致所有网址都相对于root映射。因此这对你有用 -

background: url('~/img/img-title.png')

但这并不是

background: url('../../img/img-title.png')

只需设置 url = false ,您就可以提供相对网址,并且可以正确加载所有环境。

答案 1 :(得分:2)

虽然接受的答案可能适用于您的特定情况,但我认为有一个更好的解决方案,不涉及禁用css-loader url()处理,并且在大多数情况下效果会更好。

Tilde ~问题

当您使用~导入css中的内容时,css-loader将在 node_modules 中搜索该文件。您的图片位于 src / img 文件夹中,因此您需要使用代码~来导入图片。

url()问题

sass-loader doesn't not resolve url() correctly如果它们不在条目文件的同一目录中。

在您的具体示例中,您可以在 src / scss / layout / landing.scss src / scss / layout / brands.scss 中导入一些网址,但我猜您的主要内容scss入口点位于 src / scss 文件夹中。

注意:对于“主要scss入口点”我的意思是你在javascript入口点导入的scss文件 src / js / index.js

因此,在您的示例中,在 src / scss 文件夹中的scss文件中导入的每个图像都会导致错误。

要解决此问题,请使用resolve-url-loader根据原始源文件解析url()语句中的相对路径。

[
  { loader: 'css-loader'}, // set `importLoaders: 3` if needed but should works fine without it
  { loader: 'postcss-loader'},
  { loader: 'resolve-url-loader' }, // add this
  { loader: 'sass-loader',
    // sourceMap is required for 'resolve-url-loader' to work
    options: { sourceMap: true }
  }
]

CopyWebpackPlugin是可选的

根据您的配置,您不需要CopyWebpackPlugin,因为您的图片已由url-loader处理。

注意:url-loader不输出您的图片,但是内联它们,当文件大于限制(以字节为单位)时,图像由file-loader输出。

file-loader会在 dist / img 文件夹中输出您的图片,因为您设置了name: 'img/[name].[ext]',并设置了output.path: path.resolve(__dirname, 'dist')

答案 2 :(得分:0)

嘿我认为您的问题仅在于您如何引用scss中的图像。

根据您的文件夹结构,它应该是:

// suppose your function is already defined let testArr = [[1,1,1],[1,1,0]]; invert(testArr); // now testArr is [[0,0,0],[0,0,1]];

答案 3 :(得分:0)

您可以修改“ publicPath” URL(相对于服务器根目录)以匹配文件结构。

//webpack.config.js
 ...
   module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: [
          {
            loader: "file-loader",
            options: {
              name: "[name].[ext]",
              outputPath: "assets/images/",
              publicPath: "/other-dir/assets/images/"
            }
          }
        ]
      }
    ]
  }