colbyfayock / html-webpack-partials-plugin

🛠 Easy HTML partials for Webpack without a custom index!
MIT License
69 stars 20 forks source link

Image path resolving is incorrect #7

Open Wouter125 opened 5 years ago

Wouter125 commented 5 years ago

Hi,

First of all thanks for this plugin, really loving it. There is just one issue, and I'm not sure whether it's related to this plugin or not, but let's see.

In my dev environment everything is working fine, and running perfectly. But when I try to compile it, all my paths inside the partials are not getting resolved correctly. They remain the same as they were in my dev environment.

My webpack config looks like this;

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackPartialsPlugin = require('html-webpack-partials-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    context: path.resolve('./app'),
    entry: {
        app: './js/index.js'
    },
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: path.resolve(__dirname, './app/views/index.html'),
            inject: true
        }),
        new HtmlWebpackPartialsPlugin({
            path: path.resolve(__dirname, './app/views/partials/sz-main-footer.html'),
            location: "footer",
            template_filename: "index.html",
            options: {
                footerClass: 'sz-pitchdark',
                gradientClass: 'sz-gradient',
                buttonClass: 'dark'
            }
        }),
        new MiniCssExtractPlugin({
            filename: "styles/[name].css",
        }),
    ],
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules\/(?!(dom7|ssr-window|swiper)\/).*/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['minify'],
                        plugins: ["@babel/plugin-proposal-object-rest-spread"]
                    }
                }
            },{
                test: /\.(woff|woff2|eot|ttf)$/,
                loader: "file-loader",
                options: {
                    outputPath: "fonts/",
                    name: "[hash].[ext]",
                }
            }, { 
                test: /\.(html)$/,
                use: {
                    loader: 'html-loader',
                    options: {
                        attrs: ['img:src', ':srcset'],
                        interpolate: require,
                        minimize: true
                    },
                }
              }
        ]
    }
};

------PROD-------

const merge = require('webpack-merge');
const webpack = require('webpack');
const common = require('./webpack.common.js');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = merge(common, {
    mode: 'production',
    devtool: 'source-map',
    plugins: [
        new CleanWebpackPlugin(['dist']),
        new webpack.DefinePlugin({
            'process.ev.NODE_ENV': JSON.stringify('production')
        }),
    ],
    module: {
        rules: [
          {
            test: /\.scss$/,
            use: [{
                loader: MiniCssExtractPlugin.loader,
                options: {
                    publicPath: '../'
                }
            },{
                loader: "css-loader",
            },{
                loader: 'postcss-loader',
                options: {
                    plugins: () => [require('autoprefixer'), require('cssnano')]
                }
            },{
                loader: "sass-loader"
            }]
          },
          {
            test: /\.(gif|png|jpe?g|svg)$/i,
            use: [
                {
                    loader: 'file-loader',
                    options: {
                        name: '[path][name].[ext]'
                    }
                },
                {
                    loader: 'image-webpack-loader',
                    options: {
                      pngquant: {
                        quality: '70-90',
                        speed: 2
                      },
                      optipng: {
                        enabled: false,
                      },
                      mozjpeg: {
                        progressive: true,
                        quality: 70
                      },
                      gifsicle: {
                        enabled: false,
                      }
                    },
                },
            ]
        }
        ]
    }
});

sz-main-footer.html;

<div class="<%= footerClass %>">
    <div class="prefooter">
        <div class="sz-content-wrapper">
            <div class="grid-middle_md-12-center">
                <div class="col-9_md-12">
                    <h2>Let’s brew something together!</h2>
                    <h5>We're ready to be part of your adventure.</h5>
                </div>
                <div class="col-3_md-3_sm-4_xs-7">
                    <a class="sz-primary-button <%= buttonClass %>" href="#">Get in touch</a>
                </div>
            </div>
        </div>
    </div>
    <div class="footer"> 
        <div class="sz-content-wrapper">
            <div class="grid">
                <div class="col-12_md-12">
                    <div class="sz-footer">
                        <ul class="sz-footer-nav">
                            <li>&copy; 2019 Strakzat. All rights reserved.</li>
                            <li><a href="#">Privacy Policy</a></li>
                            <li><a href="#">Terms &amp; Conditions</a></li>
                        </ul>
                        <ul class="sz-footer-social">
                            <li>
                                <a href="#">
                                    <img type="image/svg+xml" src='../../images/general/facebook.svg'></img>
                                </a>
                            </li>
                            <li>
                                <a href="#">
                                    <img type="image/svg+xml" src='../../images/general/instagram.svg'></img>
                                </a>
                            </li>
                            <li>
                                <a href="#">
                                    <img type="image/svg+xml" src='../../images/general/twitter.svg'></img>
                                </a>
                            </li>
                            <li>
                                <a href="#">
                                    <img type="image/svg+xml" src='../../images/general/linkedin.svg'></img>
                                </a>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="gradient-line <%= gradientClass %> "></div>
</div>

Any ideas how I can fix this? And let my image path inside a partial be correct when compiling? Or is this related to the html-loader? All images inside the HtmlWebpackPlugin page do work tho.

colbyfayock commented 5 years ago

hey @Wouter125 any chance you can throw this together in a Github repo where you're able to reproduce the error? it will make it easier to help you debug

Wouter125 commented 5 years ago

Aah sure, sounds good! I'll be making a small sample project later this week, currently caught up in loads of other things. Thanks in advance. 🙏

colbyfayock commented 5 years ago

I'm gonna close this out for now since it's been >2w, feel free to reopen if you get a chance to put together a sample repo

Wouter125 commented 5 years ago

Heya, sorry this took almost a whole summer to get back to you, but I'm reopening it now because I finally got around to building a little sample project with the issue located (the other one where I previously had this issues is huge). You can find it over here;

https://github.com/Wouter125/partial-issue

If you run npm install, after that npm run build, you can see what I'm talking about. My html file get's moved towards a different folder on dist causing the path towards an image to change. The htmlwebpackplugin takes care of that for me and everything works as intended.

However all my image files inside partials (the footer image include) does not change and remains the same. Causing it to be incorrect and therefore I need to manually change it by hand after compiling.

Hopefully it's something small, or the fact that I'm doing something wrong. Either way, let me know if you need any additional info so we can sort this out. Once again thanks for building this plugin!

colbyfayock commented 5 years ago

okay, so unless I'm mistaken, you have to require the image into the partial when using HTML Webpack Plugin itself, so for instance, if you were including this file in index.html, you would include it as:

<img src="${require('../images/footer/foreignrap.png')}" />

However, using that same syntax in the partial isn't working, getting an error stating require isn't defined. I'm guessing thats due to how HTML Webpack Plugin is making it work and it doesn't get included when I inject the partial.

I'll try to find some time to take a look and see what I can figure out.

Wouter125 commented 5 years ago

I do not need the ${require } part in this project anymore. That's what the html-loader is for in common webpack configuration. More about it here;

https://github.com/webpack-contrib/html-loader

It might be that it is related to that, not completely sure? But if we do need a require, that will work for me as well. Let me know, happy to help!

colbyfayock commented 5 years ago

didnt forget about you. been poking at this here and there the last few days, just having trouble finding a solution integrating with html webpack plugin

Wouter125 commented 5 years ago

No stress, I'm not in a hurry but would be nice if we can get some kind of solution around this. Appreciate all the efforts. Thanks for the heads up anyways!

Legends commented 4 years ago

okay, so unless I'm mistaken, you have to require the image into the partial when using HTML Webpack Plugin itself, so for instance, if you were including this file in index.html, you would include it as:

<img src="${require('../images/footer/foreignrap.png')}" />

However, using that same syntax in the partial isn't working, getting an error stating require isn't defined. I'm guessing thats due to how HTML Webpack Plugin is making it work and it doesn't get included when I inject the partial.

I'll try to find some time to take a look and see what I can figure out.

That's actually the same problem I have: require isn't defined

<img src="${require('../img/dummy-user.png').default}" class="circle user">

Legends commented 4 years ago

I've forked your repo and reverted it back to use v3.2. Now I can again use require in my template, but still not use require in partials loaded by your plugin.

Perhaps you have to hook into a different webpack event? hm...

Legends commented 4 years ago

@colbyfayock

Just a thought, why this isn't working:

Example: My /index-body.html which should be injected into the main tag, contains require in its html page. When I use html-webpack-plugin v3.2 then the require inside of my specified template gets processed. As /index-body.html isn't referenced anywhere in my html/js it will not get picked up and processed by webpack.

Perhaps the injection happens to late in the pipeline when parsing of the require statement and replacing it with the respective content is already done?

The html-webpack-plugin v3.2 should be analyzed further to see in which hook it does the injection, so that the require gets processed correctly.

I've too little knowledge about the innerworkings of webpack, more precisely I don't know what plugin/loader (or webpack itself at a certain stage?) does this parsing and processing exactly.

That's what needs to be found out.

  new HtmlWebpackPartialsPlugin([
            {
                path: path.join(__dirname, './src/partials/index/index-body.html'), // uses `require`
                location: 'main',
                template_filename: 'index.html'
            },
colbyfayock commented 4 years ago

Yeah i think you're definitely right there, i've tried poking around some of the earlier stages but i couldn't seem to find one that i would be able to efficiently hook this plugin into.

as far as forking and reverting, does the plugin work "as is" with a simple downgrade? wondering if i should release that on npm until i figure out a way to resolve this

i don't have a ton of immediate time to look back into this, maybe by the weekend or next week after im through holiday travel

it's also interesting as html-webpack-plugin v4 has been in beta for a very long time. not sure what their roadmap looks like in terms of re-adding any of this or completely changing the api again

@Wouter125 if you need a solution still in the meantime, maybe you can try Legends' fork as well

Legends commented 4 years ago

Referencing an issue I opened in the html-webpack-plugin repo here

@colbyfayock I like the approach of your plugin.

Unrelated to your plugin, but with html-webpack-plugin@next the require doesn't work anymore, so it's not related to your plugin. At least while it is in beta, don't know if it will be supported again when it's released.

But when I use the current html-webpack-plugin@3.2 I can require resources directly from the template itself, but not from inside the partials. The partial gets injected correctly, but the require inside stays untouched.

We'll find a solution...

To make it more clear, when using html-webpack-plugin@3.2, see comments in code :

 new HtmlWebpackPlugin({       
            template: './src/pages/layout/layout.ejs', // require inside the template works
            templateParameters: {
                'title': 'Index'
            },           
            inject: true,
            chunks: ['index'],
            filename: 'index.html'
        }),
  new HtmlWebpackPartialsPlugin([
            {
                path: path.join(__dirname, './src/../index-body.html'), // require inside the partial DOES NOT WORK!
                location: 'main',
                template_filename: 'index.html'
            }
        ]),
colbyfayock commented 4 years ago

thanks - that might help someone else running into this issue that needs a temporary fix

the only thing that im worried about is that it was an intentional design decision for html-webpack-plugin and we may need to figure out a new solution. thanks for helping dig in on this

Legends commented 4 years ago

Just a short update: the "magic" happens in ./lib/compiler.js --> html-webpack-plugin@3.2.

We have to update the template to include the partials before the childCompiler runs compileTemplate. Not sure if there is a hook for this ootb...?!

Anyways, as said, require doesn't work in v4 at all, so we have to wait for Jan (jantimon) to give us advice on this one.

Or we/you implement the logic on our own, but this requires deeper knowledge of the webpack engine.

Legends commented 4 years ago

I've closed the issue in the html-webpack-plugin repo and opened a feature request. Besides the require issue, I guess with this approach we also don't have watch support when developing, means: if I change a partial it doesn't trigger a recompile.

Let's discuss all things there as I have made some suggestions how it can be solved. I can open the former issue again if you wish, just ping me.

colbyfayock commented 4 years ago

yeah - getting into the webpack specifics was where i was getting lost when i dug deep into this last time. thanks for getting that request out. im sensing a little pushback on it, but hopefully we can figure something out in some way whether it's with some first class functionality or a way forward here

Wouter125 commented 4 years ago

Sounds good. In the meanwhile I moved to gulp with a Webpack bundler inside the streams. Doing the partials through gulp and fixing the rest by using Webpack. That was an option that I still had luckily.

So I no longer needed a fix for the issue here. Hope you guys can sort it out! Thanks for all the efforts. Really appreciated!

colbyfayock commented 4 years ago

Just wanted to give a heads up - haven't been able to find some more time to look at this and I'll be unavailable for the next ~2 weeks. Hopefully after that I can try to spend some more time thinking through this and getting it through the html-webpack-plugin compilation train.

shariult commented 4 years ago

One way might be to 'import' assets using js. Then integrate it by DOM manipulation.

colbyfayock commented 4 years ago

@shariult if you're interested in giving it a shot, id be open to a PR :)

shariult commented 4 years ago

okay, I will. Though I am little bit busy at the moment. I really like this project, so I will try to solve both issues. For now @Wouter125 , you can use this sort of a hack I use as a work around. See the image I uploaded, Annotation 2020-05-15 154128

toabm commented 3 years ago

The problem still persits.... is there any solution or workaround? Thank you!

colbyfayock commented 3 years ago

i haven't been actively working on this, but i'd happily accept a pull request to get it fixed!

toabm commented 2 years ago

Same problem here. Images' paths inside partials do not get procesed. Any solutions?

Invincibear commented 2 years ago

For anybody else coming here, it looks like using require() in any html-webpack-plugin plugins broke in v4. There is an alternative coding pattern to replace html-webpack-partials-plugin suggested in this comment: https://github.com/jantimon/html-webpack-plugin/issues/1330#issuecomment-570077275