Html-webpack-plugin: Add option basePath which replace webpack path

Created on 27 Jan 2020  路  17Comments  路  Source: jantimon/html-webpack-plugin

Hi, @jantimon, I would like to ask about small modification of your plugin. I think, It can help with define absolute path in webpack, when app is not running on root of web address, for example: domain.com/myapp

In this case, in webpack I will set following option:
modules.output.publicPath: './' // relative path to the source codes

But your webpack html plugin will inject all the js/css files with the same way:
<script type="text/javascript" src="./myjs.hash.js">
...and this is the problem. I need to replace './' to full path.

But for rendering the html page, I'm using PHP templating system (as everybody). Therefore I want to ask you, If you can add new option for example basePath to your plugin, which will replace basePath from webpack.

new HtmlWebpackPlugin({ filename: ROOT_PATH + '/app/presenters/templates/@layout.latte', template: ROOT_PATH + '/app/assets/@layout.latte', basePath: '{$basePath}/dist/', chunks: ['index_head', 'front'], // inject: 'body' }),

and this will generate:
<script type="text/javascript" src="{$basePath}/dist/front.c91a135f.bundle.js"></script>

{$basePath} will be replaced by the PHP templating system with absolute path.

Only what is needed is add new property to option object and modify lines 533 and 544 of your plugin - something like this:
src: this.options.basePath + path.basename(scriptPath)

Please, is it possible to implement this small but very useful feature?
Thx a lot!

All 17 comments

For lazy and asset loading you should use an absolute publicPath.

If you really want to modify the path of all assets you can disable the inject option or add a plugin which hooks into the file paths

Ciao @jantimon, yes but... :-)

  1. The absolute public path is not a solution, because the absolute path is depend on place, where I will copy the app after build (it must be universal, and the absolute path is not known, when I'm building the app).

  2. "If you really want to modify the path of all assets you can disable the inject option or add a plugin which hooks into the file paths"
    I don't wan't disable inject option (I like it), only what I want is don't change paths defined in webpack output and modify it ONLY in your plugin. I want to modify the path, inject variable for example {$basePath} to the path and inject it to the html. The {$basePath} will be replaced in PHP by real path and this is I think most simple working solution.

please, check line 228
https://gist.github.com/acqsk/e0f840798f8b3f09135a77add56df140

rendered html by your plugin from template, line 5 and line 213
https://gist.github.com/acqsk/46779f1d5c5441573c04496a8ef3ad30

...but If you have another idea, how can I make the same, please give me an example.

Thanks a lot :-)

I believe adding a basePath might add confusion so I would prefer to keep it out as a plugin for now.

Your mini plugin might look like this (syntax is compatible for html-webpack-plugin 4.x beta)

const HtmlWebpackPlugin = require('html-webpack-plugin');
class HtmlBasePathPlugin {
  apply (compiler) {
    compiler.hooks.compilation.tap('HtmlBasePathPlugin', (compilation) => {
      HtmlWebpackPlugin.getHooks(compilation). beforeAssetTagGeneration.tapAsync(
        'HtmlBasePathPlugin', // <-- Set a meaningful name here for stacktraces
        (data, cb) => {
          // Manipulate the publicPath
          data.assets.publicPath = "${basePath}" + data.assets.publicPath
          // Tell webpack to move on
          cb(null, data)
        }
      )
    })
  }
}

Usage inside your webpack config:

plugins: [
   new BasePathPlugin()
]

You can not only change the public path but also the script paths

See all possible hooks here: https://github.com/jantimon/html-webpack-plugin#events

image

But for third party template language support like php disabling the inject option should also work quite well.

@jantimon Thank a lot for this example. I installed latest beta11 webpack-html-plugin and I used your example. But during the compilation, I received error: data is not defined :-(

// Tell webpack to move on
cb(null, data)

@jantimon ...I'm sad :-( I disabled the example and tryied to build ...and the new version of plugin have problem with latte syntax.

ERROR in Error: Parse Error:

https://gist.github.com/acqsk/46779f1d5c5441573c04496a8ef3ad30

I must go back to version 3 :-(

This is probably because the new html minifier default settings as the minifier is now enabled by default for prod builds and has troubles with minifying invalid html code.

You can disable it with minify: false

I updated the code example above to fix the issue with data

@jantimon I will try it. Thank you very much :-)

About the minify, I don't know, if it is a good idea to make minify option default with true value.

馃 We might hide the error if no minify option was set or show an error.
The idea was that most people generate html and will receive faster pages out of the box.

馃 We might hide the error if no minify option was set or show an error.
The idea was that most people generate html and will receive faster pages out of the box.

Yes, it can be better. Please, fix me if I'm thinking bad, but much from them are using templating systems, where minify is not possible to use.

By me, if primary role of this plugin is inject JS/CSS into HTML, current state is better :-)

If primary more important role of this plugin is compress HTML, than better is your idea, minify=true.

The main idea was to provide the index.html file for your webpack build.
Especially to create single page applications.

So if you only provide a template file e.g.

 new HtmlWebpackPlugin({
      title: 'My App',
      template: 'src/my-tempate.ejs'
})

It will return a minified html file called index.html with js and css files injected.

There are also people using the HtmlWebpackPlugin to generate non html files (e.g. *.php).
That is also fine but in that case they need to disable features which try to parse the generated html (e.g. inject or minify).

Thank you for deeper explanation, in this case, I agree with you.

I think, it's OK. Only, please modify please disabled to please disable.

Will do ty 馃憤

Ciao @jantimon , the data.assets is undefined in your example, but instead of it, thank you again for perfect example and explanation. I was created my first plugin a HtmlWebpackBasepathPlugin.

[https://www.npmjs.com/package/html-webpack-basepath-plugin]

Cool can you send me a link to the repository?

@jantimon Ciao, sorry for the later answer. The repository link is: https://github.com/acqsk/html-webpack-basepath-plugin

Thanks again for you help.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

laruiss picture laruiss  路  3Comments

lonelydatum picture lonelydatum  路  3Comments

Rowno picture Rowno  路  3Comments

MatthewKosloski picture MatthewKosloski  路  3Comments

mmjamal picture mmjamal  路  3Comments