webpack-contrib / html-loader

HTML Loader
MIT License
1.16k stars 205 forks source link

Support <link href=""/> #17

Closed natew closed 6 years ago

natew commented 9 years ago

Wanting to use it with a template that has this in the head tag:

<link rel="apple-touch-icon" href="icon.png"/>

But it doesn't seem to pick it up! The syntax seems simple enough to add.. want a pull request?

natew commented 9 years ago

Ok, so getting interesting results. I'd like this:

./layout.html
./icon.png
./main.js

layout:

<!DOCTYPE html>
<html>
<head>
  <link rel="apple-touch-icon" href="icon.png"/>
</head>
<body></body>
</html>

main.js

 require('./layout.html');

loader:

  { test: /\.html$/, loader: 'html-loader!file-loader?name=index.html' }

And the output to be:

index.html
XXXX.png

where index.html has the path to the icon properly inserted.

But I've tried a variety of combinations. Without the file-loader it outputs the icon.png but no layout. With file-loader the layout but no icon.

sokra commented 9 years ago

You cannot combine html-loader and file-loader this way.


You can send a PR adding this syntax, but restrict it to known rels as not every link should be processed.

natew commented 9 years ago

I can't get the build to output the html and the png together, even without file-loader renaming. That should be possible, right? Even just using <img src="icon.png" /> it just outputs the html file.

cbrewer1689 commented 9 years ago

+1

jhnns commented 9 years ago

:+1:

choonkending commented 9 years ago

:+1:

shprink commented 9 years ago

+1

nmabhinandan commented 9 years ago

+1

ivanmayes commented 9 years ago

+1

iDVB commented 9 years ago

+1

mlegenhausen commented 8 years ago

+1

ehgoodenough commented 8 years ago

+1

choonkending commented 8 years ago

Just for reference, I ended up using react helmet in my solutions. :)

mxstbr commented 8 years ago

:+1:

Also, what about <meta property="og:image" content="someimage.jpg" />?

jhnns commented 8 years ago

Sounds reasonable. We probably need a more configurable solution. I think, there is an infinite number of possible tags which reference other files :)

mxstbr commented 8 years ago

Very true, a custom function that gets passed all the tags would be really nice! (Similar to how postcss works maybe?)

tikhonbelousko commented 8 years ago

Currently I'm doing the following trick:

{
  test: /\.html$/,
  loader: ExtractTextPlugin.extract('html?attrs=link:href')
},
mxstbr commented 8 years ago

@DaZzz I'm pretty sure that's not a trick, that's intended usage of that option, but we need a better solution for tags like <meta property="og:image" content="someimage.jpg" />.

resistdesign commented 8 years ago

+1

vbarbarosh commented 8 years ago

Until there is no other solution, interpolation syntax may be used (with interpolate flag turned on):

<link rel="shortcut icon" href="${require('./favicon.ico')}">
<meta property="og:image" content="${require('./someimage.jpg')}" />

And, of course, loaders should be configured appropriately:

...
module: {
    loaders: [
        ...
        {
            test: /\.(ico|png|eot|svg|ttf|woff|woff2)$/,
            loader: 'file?name=[name]-[hash:6].[ext]'
        },
        ...
    ]
},
...
michael-ciniawsky commented 8 years ago

posthtml maybe :) ?

resistdesign commented 8 years ago

@vbarbarosh That's actually pretty interesting, what is the result like?

vbarbarosh commented 8 years ago

@resistdesign As expected: ./favicon.ico and ./someimage.jpg will be copied into the destination directory, and the whole expression will be replaced by path to the file (e.g. ${require('./favicon.ico')} will be replaced by favicon-123456.ico).

gaearon commented 8 years ago

Can we add an option to treat all attribute values starting with ./ as ones to be resolved by loaders? Or even make it a default. I imagine this would satisfy most use cases without explicit attribute whitelists unless I’m missing something.

resistdesign commented 8 years ago

@gaearon Interesting, does that work for icons, js, css, manifest and all that? It just might. You have to also consider ../ and things like that in case of relative paths, but I guess you could still have ./../ which is wonky but should work.

So what would be the result, it would run the file through a loader and return the new path/URL? The loader CAN'T return code or content because the result will be set as the value of an attribute. I mean it could be a data URL but that seems problematic for code and such I would think.

jhnns commented 7 years ago

Currently, we have a mixture between sane defaults (all src attributes) and additional opt-ins. @gaearon 's suggestion is to extend the sane default to all attribute values that look like a path. We can make the pattern a little bit smarter, for instance, we could also enforce a file extension at the end of the path (like \.[a-z]{3,4}$).

This would be nice, because it reduces the need to configure things and many instances will just work out of the box. But we would still need to provide a way to exclude certain attributes because there are always exceptions and people will come and say: "Oh, webpack should not handle these kind of attributes".

gaearon commented 7 years ago

FYI we decided to stop using html-loader completely and just tell people to maintain a "public" folder for assets that go with HTML. Worked great for us.

The biggest issue I couldn't figure out how to resolve are JSON files. When used in <link> I want them to be treated as files, not JS modules. On the other hand I don't want user to write !!file!./something.json. So I decided the whole abstraction is leaky for our use case, and dropped it.

jhnns commented 7 years ago

Totally understandable. It doesn't make sense to handle JSONs as javascript modules when referenced from an HTML file. Sometimes, it makes sense to express that as a directory-specific rule (like "all JSONs inside this directory should be emitted as separate files"), but the current way of configuring loaders lacks this type of expression.

jhnns commented 7 years ago

Webpack 2 has more powerful way to configure these loader rules. Now you can define loader rules based on the "issuer" which is the module that contains the import statement. Your use-case would be solved like this:

module: {
    rules: [
        {
            test: /\.json$/,
            issuer: /\.html$/,
            loader: "file-loader"
        }
    ]
}
gaearon commented 7 years ago

Very neat.

7kms commented 7 years ago

I have solve it like this,but not pure html-loader,I make it with html-webpack-plugin

<link rel="apple-touch-icon" sizes="114*114" href="<%= require('../assets/images/logo.png') %>">
<link rel="icon" type="image/x-icon" href="<%= require('../assets/images/favicon.ico') %>" sizes="48x48">
loaders =  [
{
    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    exclude: '/nolimit/',                
    loader: 'url-loader',
     query: {
           limit: 10,
           name: utils.assetsPath('img/[name].[hash:6].[ext]')
                }
     },
 {
      test: /.(ico)$/,
      loader: 'file?name=[name].[hash:6].[ext]'
 }
]

then the finally rendered html like this

<link rel="apple-touch-icon" sizes="114*114" href="static/img/logo.32893a.png"> 
<link rel="icon" type="image/x-icon" href="favicon.aacd9e.ico" sizes="48x48">
ChristianUlbrich commented 7 years ago

@baotang I doubt this will work with the html-loader. For it to work set interpolate: 'require' option and use ${require('./image.png')}:

somehwere in the WebPack config:

module: {
      loaders: [

     //..
        {
          test: /\.html$/,
          loader: 'html',
          query: {
            interpolate: 'require'
          }
     ] //..
    }

And then:

<link rel="apple-touch-icon" sizes="114*114" href="${require('static/img/logo.32893a.png')">    
<link rel="icon" type="image/x-icon" href="${require('favicon.aacd9e.ico')" sizes="48x48">

This works for me.

Dixin commented 7 years ago

I came here from google.

https://www.npmjs.com/package/html-loader

attrs: ['img:src', 'link:href']

michael-ciniawsky commented 6 years ago

https://github.com/webpack-contrib/html-loader/releases/tag/v1.0.0-alpha.0

ChoppinBlockParty commented 3 years ago

Hi, it is not very clear to me, is link:href supported? I am trying

    <link rel="icon" type="image/x-icon" href="./favicon.ico" >

But does not get picked up by webpack.

ChoppinBlockParty commented 3 years ago

I have all the suggestions from this topic, none has worked. Probably it is because I am on webpack 5, and many things have changed since then. I have ended up adding link:href to the attributes, works fine. I just wonder why it is not added by default, what was the concern there?

trullock commented 3 years ago

@ChoppinBlockParty could you humour me with the complete webpack config snippet I need to do this using todays tool versions? Thanks

dkrasnove commented 3 years ago

@trullock, and for anybody who may come across this in the future if it hasn't been fixed, this works as of webpack 5.21.2:

{
    test: /\.html$/i,
    loader: 'html-loader',
    options: {
      attributes: {
        list: [
          '...',
          {
            tag: 'link',
            attribute: 'href',
            type: 'src',
          }
        ]
      }
   }
}