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-loaderurl-loaderfile-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 中进行更改:

&lt;img src="../images/foo.png" /&gt;

到这里

&lt;img src=&lt;%=require("../images/foo.png")%&gt; /&gt;

【讨论】:

如果我以前有 -m.png"/> 怎么办?如何动态导入? 结果:&lt;img src="[object" module]="",或带引号的&lt;img src="[object Module]" @ArthurShlain &lt;img src=&lt;%=require("../images/foo.png").default%&gt; /&gt; 引用 .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 文件夹也是一个开始),所以可以做&lt;img src="./images/foo.png"&gt;,因为图像的目录结构不太可能改变比许多模板文件。 Luis 在下面的回答是最正确的,因为模块别名也可以使用,但是在 require 中添加看起来很难看,也不是很直观。 @GuyPark 如果您想要使用文件加载器与&lt;img src="./images/foo.png"&gt; 等效,您可以从 .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 文件中预加载所需的类型

WebP 后备图像未加载

Javascript 将图像加载到 Offscreen Canvas 中,执行 webp 转换

webpack html-loaders 小写 angular 2 内置指令

如何使用 webpack 从模板加载 VueJS 应用程序?