url-loader / file-loader 使用 webpack 破坏 css 输出中的相对路径
Posted
技术标签:
【中文标题】url-loader / file-loader 使用 webpack 破坏 css 输出中的相对路径【英文标题】:url-loader / file-loader breaking relative paths in css output using webpack 【发布时间】:2019-05-16 04:24:48 【问题描述】:我正在使用带有一些插件和加载器的 webpack 来获取我的 src/ 文件夹并构建一个 dist/ 文件夹。 url-loader(当图像大于特定限制时回退到文件加载器)正在按预期将它在我的 html 和 scss 文件中找到的图像输出到正确的目录。但是,它会更改这些文件中的相对路径,并且这样做会输出一个路径不正确的 css 文件。
文件结构:
src/
index.html
assets/
js/
index.js
scss/
style.scss
img/
pic.jpg
background.jpg
dist/
index.html
assets/
js/
index.js
css/
style.css
img/
pic.jpg
background.jpg
正如你所见,我的 dist/ 文件夹镜像了我的 src/ 文件夹,只是 scss 被编译为 css。
src/index.js 导入 index.html 和 style.scss 以便这些文件可以被 webpack 解析并且其中的任何图像都可以被 url-loader 处理:
index.js
import '../../index.html';
import '../scss/style.scss';
style.scss 使用相对路径在 body 上设置背景图片:
style.scss
body
background: url('../img/background.jpg');
index.html 只显示一个图像,也使用相对路径:
index.html
<img src="./assets/img/pic.jpg" >
我使用 HtmlWebpackPlugin 跨我的 html 文件进行复制,因为它允许我指定要自动包含哪些块作为脚本标签。对于 css,我要么在开发中使用 style-loader 将其注入到 html 文件中,要么在生产中使用 MiniCssExtractPlugin 将其提取到自己的文件中。
但是,当 webpack 解析 index.html 和 style.scss 时,相对路径会分别替换为 'assets/img/pic.jpg' 和 'assets/img/backgorund.jpg'。这不会破坏 index.html 中的路径,因为它恰好是相同的相对路径,但这显然是 style.css 的问题。我将如何阻止 url-loader 更改相对路径,或者只生成正确的路径?另请注意,在开发中使用 style-loader 将 css 注入 html 时,该路径有效,因为它是相对于 html 文件的。理想情况下,webpack 应该能够生成正确的相对路径,具体取决于我是在生产中提取 css 还是在开发中注入它。
我尝试过使用resolve-url-loader,指定publicPath和outputPath,当然还可以在线搜索答案,但没有成功。
webpack.config.js
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const devMode = process.env.NODE_ENV !== 'production';
module.exports =
mode: devMode ? 'development' : 'production',
entry:
index: './src/assets/js/index.js',
,
output:
filename: 'assets/js/[name].js',
path: path.resolve(__dirname, 'dist')
,
devServer:
contentBase: path.join(__dirname, 'src'),
watchContentBase: true,
hot: devMode,
,
devtool: devMode ? 'source-map' : '(none)',
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin(
filename: 'index.html',
template: 'src/index.html',
),
new MiniCssExtractPlugin(
filename: 'assets/css/style.css',
)
],
module:
rules: [
test: /\.html$/,
use: [
loader: 'html-loader'
]
,
test: /\.(jp(e?)g|png|svg|gif)$/,
use: [
loader: 'url-loader',
options:
limit: 8192,
name: 'assets/img/[name].[ext]'
]
,
test: /\.scss$/,
use: [
loader: devMode ? 'style-loader' : MiniCssExtractPlugin.loader
,
loader: 'css-loader',
options:
sourceMap: devMode,
importLoaders: 2
,
loader: 'sass-loader',
options:
sourceMap: devMode
]
]
;
if (devMode)
module.exports.plugins.push(new webpack.HotModuleReplacementPlugin());
【问题讨论】:
【参考方案1】:已解决 感谢github上的这篇帖子:https://github.com/webpack-contrib/mini-css-extract-plugin/issues/44#issuecomment-379059788.
只需像这样将 publicPath 选项添加到 MiniCssExtractPlugin 中:
...
test: /\.scss$/,
use: [
loader: MiniCssExtractPlugin.loader,
options:
publicPath: '../../' // path to director where assets folder is located
,
loader: 'css-loader',
options:
sourceMap: devMode,
importLoaders: 2
,
loader: 'sass-loader',
options:
sourceMap: devMode
]
,
...
要在开发模式下使用样式加载器而不是像我原来的 webpack.config.js 中那样使用 MiniCssExtractPlugin,您必须有条件地添加选项,因为样式加载器不接受 publicPath 选项。我在 webpack.config.js 的底部这样做了:
if (!devMode)
module.exports.module.rules[0].use[0].options = publicPath: '../../' ;
然后确保规则数组中的第一个对象是用于 scss。有条件地添加这个有点乱,但现在可以了。
【讨论】:
【参考方案2】:在这上面花了很多时间! publicPath
下面的设置丢失了!
output:
publicPath: '/'
,
【讨论】:
【参考方案3】:尝试添加 publicPath 选项
loader: 'url-loader',
options:
limit: 8192,
name: "[name].[ext]"
publicPath: '/assets/img/ //<-- assuming assets is in web root
并将 style.scss 更改为
body
background: url('background.jpg');
【讨论】:
然后 webpack 无法从 style.scss 文件中找到图像,因为它在同一个文件夹中查找它。 (未找到模块:错误:无法解析“/Users/jlwalker/demo/src/assets/scss”中的“./background.jpg”)。它还使 dist/ 输出文件中的路径成为绝对路径,而理想情况下我更喜欢使用相对路径。 resolve-url-loader 有什么问题。你是在 sass-loader 上面加的吗? 据我所知,resolve-url-loader 允许您在 sass 部分中使用与这些部分相关的路径,而不是相对于导入这些部分的 sass 文件。我有一个不同的问题。但是由于comment,我现在已经设法让它工作了。将很快更新我的帖子。无论如何,感谢您为我调查! 使用文件加载器为我工作【参考方案4】:这是我的解决方案:
const devMode = process.env.NODE_ENV !== 'production';
...rules: [
test: /\.scss$/,
use: [
devMode ? 'style-loader' :
loader: MiniCssExtractPlugin.loader,
options:
publicPath: '../',
,
// translates CSS into CommonJS
loader: 'css-loader',
options:
sourceMap: true,
,
,
// Autoprefixer usw.
loader: 'postcss-loader',
options:
ident: 'postcss',
,
,
// compiles Sass to CSS, using Node Sass by default
loader: 'sass-loader',
options:
sourceMap: true,
,
],
,
]
【讨论】:
以上是关于url-loader / file-loader 使用 webpack 破坏 css 输出中的相对路径的主要内容,如果未能解决你的问题,请参考以下文章
url-loader / file-loader 使用 webpack 破坏 css 输出中的相对路径
Webpack url-loader 或 file-loader 不起作用反应应用程序
Webpack 使用url-loader和file-loader打包资源文件