Script imports in preprocessor templates are resolved relative to the including file
Closed this issue · 1 comments
Current behaviour
In templates which are included in another file (such as by using Handlebars partials), <script>
tags in the template will have their src
paths resolved relative to the file which included them.
Expected behaviour
The src
should be resolved relative to the template file itself.
Reproduction
https://github.com/gingershaped/template-script-import-mre
Environment
- OS: Windows
- version of Node.js: 20.16.0
- version of Webpack: 5.1.4
- version of the Plugin: 4.0.0
Hello @gingershaped,
thanks for the issue.
All resources, including scripts, are resolved relative to entrypoint template.
This is not a bug, this is the feature. I know, this can be confusing.
Why?
The plugin uses various templating engines and not all engines supports the feature to allow walk through source template includings to resolve assets in child partials.
For example, it works in Pug and I have implemented using relative asset path in child partials. This works via require()
function.
How works resolving of assets?
To resolve assets in all templating engines with the same rule, firstly the template entry point (including all partials) is rendered into pure HTML and then in the HTML (the path to entry template) will be resolved assets. Therefore all relative paths in partials must be relative to entry point, not to self partials. The same behaviour works in html-loader.
Additional, only at this stage can be implement the source filter like it works in html-loader.
Solution
independent of using templating engine I strongly recommend to use the Webpack aliases for your assets.
This is bests practice and simplify using assests in templates.
The path to assets is relative to the alias and not to partial. It's very comfortable to use.
Define aliases in config:
const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');
module.exports = {
resolve: {
alias: {
'@scripts': path.join(__dirname, 'src/scripts/'), // alias to scripts used in template
'@styles': path.join(__dirname, 'src/scss/'), // alias to styles used in template
'@images': path.join(__dirname, 'src/images/'), // alias to images used in template
},
},
plugins: [
new HtmlBundlerPlugin({
entry: {
index: "src/index/index.hbs"
},
preprocessor: "handlebars",
preprocessorOptions: {
partials: ["src/templates/"]
}
})
]
};
Use aliases in the template:
<html>
<head>
<link href="@styles/main.scss" rel="stylesheet" />
<script src="@scripts/main.ts" defer="defer"></script>
</head>
<body>
<h1>Hello World!</h1>
<img src="@images/picture.png" />
</body>
</html>
P.S.
I'm sorry, but your feature request can't be implemented. Use please the working solution.