Webpack:从 html 模板加载图像
Posted
技术标签:
【中文标题】Webpack:从 html 模板加载图像【英文标题】:Webpack: Loading images from html templates 【发布时间】:2015-12-21 14:27:03 【问题描述】:我正在尝试使用 Webpack 设置 Angular 项目,但我不知道如何从 html 模板中引用图像并将它们包含在构建中。
我的项目树如下:
package.json
app/
- images/
- foo.png
- scripts/
- styles/
- templates/
我正在尝试将html-loader
与url-loader
和file-loader
一起使用,但这并没有发生。
这是一个示例模板:app/templates/foo.html
<img src="../images/foo.png" />
问题#1:我希望能够参考与app/
相关的图像。现在,路径需要相对于模板文件,这将很快变得丑陋 (../../../images/foo.png
)。
问题#2:即使我指定了相对路径,正如我在上面所做的那样,项目构建成功,但没有真正发生。路径保持原样,dist/
中不显示任何图像。
这是我的 webpack 配置:
var path = require('path');
var webpack = require('webpack');
var ngminPlugin = require('ngmin-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var ngAnnotatePlugin = require('ng-annotate-webpack-plugin');
module.exports = function(config, env)
var appRoot = path.join(__dirname, 'app/')
if(!env) env = 'development';
var webpackConfig =
cache: true,
debug: true,
contentBase: appRoot,
entry:
app: path.join(appRoot, '/scripts/app.coffee')
,
output:
path: path.join(__dirname, 'dist/),
publicPath: '/',
libraryTarget: 'var',
filename: 'scripts/[name].[hash].js',
chunkFilename: '[name].[chunkhash].js'
,
module:
loaders: [
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
,
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader!sass-loader?outputStyle=expanded&includePaths[]=./node_modules/foundation/scss/')
,
test: /\.coffee$/,
loader: 'coffee-loader'
,
loader: 'ngtemplate?relativeTo=' + (path.resolve(__dirname, './app')) + '/!html'
,
test: /\.png$/, loader: "url-loader?limit=100000&mimetype=image/png&name=[path][name].[hash].[ext]"
,
test: /\.jpg$/, loader: "file-loader?name=[path][name].[hash].[ext]"
,
test: /\.(woff|woff2)(\?(.*))?$/,
loader: 'url?prefix=factorynts/&limit=5000&mimetype=application/font-woff'
,
test: /\.ttf(\?(.*))?$/,
loader: 'file?prefix=fonts/'
,
test: /\.eot(\?(.*))?$/,
loader: 'file?prefix=fonts/'
,
test: /\.svg(\?(.*))?$/,
loader: 'file?prefix=fonts/'
,
test: /\.json$/,
loader: 'json'
]
,
resolve:
extensions: [
'',
'.js',
'.coffee',
'.scss',
'.css'
],
root: [appRoot],
,
singleRun: true,
plugins: [
new webpack.ContextReplacementPlugin(/.*$/, /a^/),
new webpack.ProvidePlugin(
'_': 'lodash'
),
new ExtractTextPlugin("styles/[name].[chunkhash].css", allChunks: true),
new HtmlWebpackPlugin(
template: appRoot + '/app.html',
filename: 'app.html',
inject: 'body',
chunks: ['app']
)
],
devtool: 'eval'
if(env === 'production')
webpackConfig.plugins = webpackConfig.plugins.concat(
new ngAnnotatePlugin(),
new webpack.optimize.UglifyJsPlugin(),
new webpack.DefinePlugin(
'process-env':
'NODE_ENV': JSON.stringify('production')
),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin()
);
webpackConfig.devtool = false;
webpackConfig.debug = false;
return webpackConfig;
【问题讨论】:
你是如何解决问题 #1 的? 【参考方案1】:如果您在 Webpack 2 中使用 HTML 模板,除了使用文件加载器之外,您还需要在 HTML 中进行更改:
<img src="../images/foo.png" />
到这里
<img src=<%=require("../images/foo.png")%> />
【讨论】:
如果我以前有 -m.png"/> 怎么办?如何动态导入? 结果:<img src="[object" module]=""
,或带引号的<img src="[object Module]"
@ArthurShlain <img src=<%=require("../images/foo.png").default%> />
引用 .default
到方法调用。见***.com/questions/59070216/…
URIError: 无法解码参数'/%3C%=require(%22../assets/eotpeccy.png%22).default%'【参考方案2】:
-
是的,您必须这样做才能从不同的路径加载图像。
我遇到了类似的问题,我使用
file
loader 解决了这个问题:
.
loaders: [
// JS LOADER
test: /\.js$/,
loader: 'babel-loader?optional[]=runtime',
exclude: /node_modules/
,
// ASSET LOADER
test: /\.(woff|woff2|ttf|eot)$/,
loader: 'file-loader'
,
//IMAGE LOADER
test: /\.(jpe?g|png|gif|svg)$/i,
loader:'file-loader'
,
// HTML LOADER
test: /\.html$/,
loader: 'html-loader'
,
//SCSS LOADER
test: /\.scss$/,
loaders: ["style-loader", "css-loader", "sass-loader?indentedSyntax"]
]
祝你好运
【讨论】:
在使用加载器时不再允许省略'-loader'后缀。您需要指定“文件加载器”而不是“文件”。 不确定这如何解决@syko 的问题,因为它看起来与他的设置相同。是否有任何file-loader
选项可以让 html 文件简单地引用一个公共参考点(即使@syko app 文件夹也是一个开始),所以可以做<img src="./images/foo.png">
,因为图像的目录结构不太可能改变比许多模板文件。 Luis 在下面的回答是最正确的,因为模块别名也可以使用,但是在 require 中添加看起来很难看,也不是很直观。
@GuyPark 如果您想要使用文件加载器与<img src="./images/foo.png">
等效,您可以从 .js 文件中导入图像并通过原始 javascript 代码将其添加到模板中。
一个不错的接触,但不幸的是这是一个从 [authenticated] API 服务加载的动态图像,所以它有点棘手,否则我会。 :)【参考方案3】:
对于 Webpack 5,你必须这样写:
module:
rules: [
// other stuff above.....
test: /\.html$/,
use: [
loader: 'html-loader'
]
]
【讨论】:
源选项默认为 true,所以这可能没有太大帮助 webpack.js.org/loaders/html-loader【参考方案4】:使用 Webpack 4,我可以通过更新 html-loader
为我的文件指定 root
来解决这个问题。因此,鉴于@syko 的原始结构;在webpack.config.js
...
module:
rules: [
// other stuff above.....
test: /\.html$/,
use: [
// ...The other file-loader and extract-loader go here.
loader: 'html-loader'
options:
// THIS will resolve relative URLs to reference from the app/ directory
root: path.resolve(__dirname, 'app')
]
]
这告诉html-loader
解释来自/app
文件夹的所有绝对 url。因此在我们的app/templates/foo.html
中,您可以使用以下...
<img src="/images/foo.png" />
然后这告诉html-loader
将上面的内容视为path.resolve(__dirname, 'app', 'images', 'foo.png')
。那么如果你有extract-loader
和/或file-loader
,那么所有的路径都应该是正确的。
经过一段时间的努力,设法得到了这个解决方案。最大的困惑是在加载程序堆栈中/images/foo.png
被解释的位置,在这种情况下,它从html-loader
插件开始。之后的一切,更多的是关于如何发布图像文件。
希望对您有所帮助。
【讨论】:
除了以上url-loader
需要通过选项esModule: false
禁用es6模块
知道什么是 webpack 5 的替代品吗?
抱歉不能说。仅在使用它的旧项目(不再维护)上需要它。【参考方案5】:
您可以使用file-loader 提取图像。然后使用html-loader,您可以通过查询参数attrs
指定该加载程序应该处理哪个标签-属性组合。
我可以让它与这个配置一起工作:
test: /\.(jpe?g|png|gif|svg|ico)$/i,
use: [
loader: 'file-loader',
options:
name: '[name].[ext]',
outputPath: 'images/'
]
,
test: /\.(html)$/,
use:
loader: 'html-loader',
options:
attrs: ['img:src', 'link:href']
或者像这样的角度:
attrs: [':ng-src', ':ng-href']
【讨论】:
以上是关于Webpack:从 html 模板加载图像的主要内容,如果未能解决你的问题,请参考以下文章
vue - webpack.dev.conf.js for HtmlWebpackPlugin
webp/jpg - 仅在 html 文件中预加载所需的类型
Javascript 将图像加载到 Offscreen Canvas 中,执行 webp 转换