使用时:
copy-webpack-plugin
并将
to:
指定为:'images/[name].[contenthash][ext]'
如何在模板中引用这些文件而不使用
html-webpack-plugin
还是handlebars-loader
?
我已经用以下解决方案解决了这个问题:
/**
* Create a new plugin class.
*/
const StoreAssetsInfoKeysPlugin = class StoreAssetsInfoKeysPlugin {
/**
* Define `apply` as its prototype method.
* @param hooks
*/
apply({ hooks }) {
/**
* Using the 'afterCompile' hook:
* Use the 'assetsInfo' Map which contains the output of all asset paths,
* construct an array containing all these paths,
* then write an 'assets.json' file somewhere in your project.
*/
hooks.afterCompile.tapAsync('StoreAssetsInfoKeysPlugin', ({ assetsInfo }, callback) => {
fs.writeFileSync('/path/to/assets.json', JSON
.stringify(Array
.from(assetsInfo.entries())
.map(([key]) => `/assets/${key}`)));
callback();
});
}
};
/**
* The Webpack configuration for this
* example looks like this.
*/
export default {
plugins: [
new StoreAssetsInfoKeysPlugin(),
new CopyPlugin({
patterns: [{
from: '/path/to/images/*',
to: 'images/[name].[contenthash][ext]',
}],
}),
],
};
/**
* Create a helper function which will find the
* correct path from the 'assets.json'
*/
export const getAssetPath = function getAssetPath(directory, filename, ext) {
return JSON
.parse(fs.readFileSync('/path/to/assets.json'))
.find((value) => value
.match(`^.*?\\b${directory}\\b.*?\\b${filename}\\b.*?\\.${ext}\\b.*?$`));
};
/**
* Then use the helper function within your
* server-side templating engine:
*/
getAssetPath('images', 'my-image', 'svg');
这是一个合适的解决方案吗?
这是我在服务器端模板中通过
[contenthash]
替换来实现获取文件名的第一个解决方案。
我是 Webpack 的新手,因此对这种方法的任何想法将不胜感激。
我尝试详细定义目标:
source files
脚本、样式、图像和其他资源output filenames
包含 contenthash
目标正确吗?
如果是,那么您可以使用一个强大的“html-bundler-webpack-plugin”,而无需
html-webpack-plugin
、handlebars-loader
、copy-webpack-plugin
。
例如有示例的文件结构:
src/views/index.hbs
src/scss/styles.scss
src/js/main.js
src/images/picture.png
dist/ <= output directory for processed files
有源模板文件
src/views/index.hbs
(或其他HTML文件):
<html>
<head>
<!-- source files with path relative to the template file -->
<link href="../scss/styles.scss" rel="stylesheet">
<script src="../js/main.js" defer="defer"></script>
</head>
<body>
{{> header }}
<h1>Hello World!</h1>
<!-- source image file with path relative to the template file -->
<img src="../images/picture.png">
{{> footer }}
</body>
</html>
webpack.config.js:
const path = require('path');
const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'), // output path for processed files
},,
plugins: [
new HtmlBundlerPlugin({
entry: {
// define templates here
// the key is output file path w/o extension, e.g.:
index: 'src/views/index.hbs', // => dist/index.hbs
},
js: {
// output filename of compiled JavaScript
filename: 'js/[name].[contenthash:8].js',
},
css: {
// output filename of extracted CSS
filename: 'css/[name].[contenthash:8].css',
},
// defaults used Eta (ESJ like) template engine to render into HTML
// if you will render .hbs to .html, then define as `handlebars`
preprocessor: false, // <= disable rendering into HTML to keep original template content
}),
],
module: {
rules: [
{
test: /\.(scss)$/,
use: ['css-loader', 'sass-loader'],
},
{
test: /\.(ico|png|jp?g|svg)/,
type: 'asset/resource',
generator: {
// output filename of images
filename: 'img/[name].[hash:8][ext]',
},
},
],
},
};
如果您要保留原始模板内容并仅将源资源文件替换为其散列输出文件名,则使用
preprocessor: false
插件选项禁用渲染。
处理后的(未渲染为 html)模板将如下所示:
<html>
<head>
<!-- output filenames relative to the dist/ directory -->
<link href="css/styles.0f23efdf.css" rel="stylesheet" />
<script src="js/main.5317c1f6.js" defer="defer"></script>
</head>
<body>
{{> header }}
<h1>Hello World!</h1>
<!-- output filenames relative to the dist/ directory -->
<img src="img/picture.7b396424.png" />
{{> footer }}
</body>
</html>
如果您要将任何模板渲染为 HTML,您可以“开箱即用”使用受支持的模板引擎之一:Eta、EJS、Handlebars、Nunjucks、LiquidJS。
将车把模板渲染为 HTML 的插件配置:
new HtmlBundlerPlugin({
entry: {
// define templates here
// the key is output file path w/o extension, e.g.:
index: 'src/views/index.hbs', // => dist/index.html
},
js: {
// output filename of compiled JavaScript
filename: 'js/[name].[contenthash:8].js',
},
css: {
// output filename of extracted CSS
filename: 'css/[name].[contenthash:8].css',
},
// specify the `handlebars` template engine
preprocessor: 'handlebars',
// define handlebars options
preprocessorOptions: {
partials: ['src/views/partials'],
},
})
渲染的 HTML:
<html>
<head>
<!-- output filenames relative to the dist/ directory -->
<link href="css/styles.0f23efdf.css" rel="stylesheet" />
<script src="js/main.5317c1f6.js" defer="defer"></script>
</head>
<body>
<div class="header">html of your header partials</div>
<h1>Hello World!</h1>
<!-- output filenames relative to the dist/ directory -->
<img src="img/picture.7b396424.png" />
<div class="footer">html of your footer partials</div>
</body>
</html>